更新庫存SQL算法2.0版
Create Procedure sp_ComputeStock
@StoreroomId INT = NULL,--庫房編號
@EquipmentIds VARCHAR(5000) = NULL,--設備編號,各設備編號間用逗號隔開,例如:1,2,3,4
@EquipmentMount VARCHAR(5000) = NULL,--設備數量,各設備數量間用逗號隔開,例如:11,15,20,5
@Out_equipIdNotExists VARCHAR(5000) OUTPUT, --不存在的設備ID,各設備用逗號隔開
@Out_equipNameNotExists VARCHAR(5000) OUTPUT, --不存在的設備名稱,各設備用逗號隔開
@Out_equipIdNotEnough VARCHAR(5000) OUTPUT, --庫存不夠的設備ID,各設備用逗號隔開
@Out_equipNameNotEnough VARCHAR(5000) OUTPUT, --庫存不夠的設備名稱,各設備用逗號隔開
@Out_Stockpile VARCHAR(5000) OUTPUT --設備ID的庫存量,各設備用逗號隔開
AS
SET NOCOUNT ON
SET CURSOR_CLOSE_ON_COMMIT OFF --設置手動關閉遊標,使事務不會影響到遊標的打開和關閉
DECLARE
@Empty CHAR(1), --空串
@Split CHAR(1),--分隔符
@equipName VARCHAR(100)
SET @Empty = ''
SET @Split = ','
SET @Out_equipIdNotExists = @Empty --初始化爲空串
SET @Out_equipIdNotEnough = @Empty
SET @Out_equipNameNotExists = @Empty
SET @Out_equipNameNotEnough = @Empty
SET @Out_Stockpile = @Empty
DECLARE
@tb_EquipmentIds TABLE([Id] INT IDENTITY (1,1),EquipmentId INT)--表變量,設備編號表
DECLARE
@tb_EquipmentMount TABLE([Id] INT IDENTITY (1,1),EquipmentMount INT)--表變量,設備數量表
INSERT INTO @tb_EquipmentIds SELECT * FROM dbo.f_splitSTR(@EquipmentIds,@Split)
--拆分設備編號,並將結果插入到設備編號表(表變量)中
INSERT INTO @tb_EquipmentMount SELECT * FROM dbo.f_splitSTR(@EquipmentMount,@Split)
--拆分設備數量,並將結果插入到設備數量表(表變量)中
DECLARE @au_equipmentId VARCHAR(10), --設備編號
@au_equipmentMount INT,--設備數量
@var_Mount INT--庫存數量
--將設備編號表和設備數量表關聯,按設備編號分組統計出各設備的出庫數量
--注意遍歷了兩次該遊標,第一次用來檢查設備,第二次用來更新設備
--(若第一次遍歷設備通過後,才進行第二次,否則不進行)
DECLARE stockBill_cursor CURSOR LOCAL FAST_FORWARD FOR --聲明並定義快速只進的本地遊標
SELECT
EquipmentId,
SUM(EquipmentMount) AS Mount
FROM
@tb_EquipmentIds AS a
INNER JOIN
@tb_EquipmentMount AS b
ON
a.[ID] = b.[ID]
GROUP BY EquipmentId
OPEN stockBill_cursor
--第一次遍歷:檢查設備是否在庫房中存在,檢查設備的庫存是否不足。若存在且庫存夠,
--才進行第二次遍歷(更新庫存)
FETCH NEXT FROM stockBill_cursor
INTO @au_equipmentId, @au_equipmentMount
--將當前設備編號保存到@au_equipmentId中,將當前設備數量保存到@au_equipmentMount中
WHILE @@FETCH_STATUS = 0
BEGIN
SET @var_Mount = NULL
--根據庫房號和設備編號從庫存表中找出該設備的存庫數量,並保存到@var_Mount中
SELECT
@var_Mount = Mount
FROM
tb_Stock
WHERE
F_StoreroomId = @StoreroomId
AND
F_EquipmentId = @au_equipmentId
SELECT @equipName = EquipmentName FROM dbo.tb_Equipment WHERE P_EquipmentId = @au_equipmentId
IF(@var_Mount IS NULL) --若@var_Mount=NULL表明不存在該設備
BEGIN
SET @Out_equipIdNotExists = @Out_equipIdNotExists + @au_equipmentId + @Split
SET @Out_equipNameNotExists = @Out_equipNameNotExists + @equipName + @Split
END
ELSE
BEGIN --否則存在該設備
--所取數量與庫存數量比較,若大於庫存數量, 將該設備編號記錄下來。
IF (@au_equipmentMount > @var_Mount)
BEGIN
SET @Out_equipIdNotEnough = @Out_equipIdNotEnough + @au_equipmentId + @Split-
-記錄庫存不夠的設備,用逗號隔開
SET @Out_equipNameNotEnough = @Out_equipNameNotEnough + @equipName + @Split
SET @Out_Stockpile = @Out_Stockpile + LTRIM(STR(@var_Mount))+@Split
END
END -- IF(@var_Mount IS NULL)
FETCH NEXT FROM stockBill_cursor --取下一條
INTO @au_equipmentId, @au_equipmentMount
END -- WHILE
--若@Out_equipmentNotExists和@Out_equipmentNotEnough都是空串,表明
--即不存在庫存不夠的設備, 也沒有庫房中不存在的設備
IF(@Out_equipIdNotExists = @Empty AND @Out_equipIdNotEnough = @Empty)
BEGIN
CLOSE stockBill_cursor --關閉遊標
OPEN stockBill_cursor --再次打開遊標
FETCH NEXT FROM stockBill_cursor --第二次遍歷,更新庫存.
INTO @au_equipmentId, @au_equipmentMount
BEGIN TRANSACTION
WHILE @@FETCH_STATUS = 0
BEGIN
SET @var_Mount = NULL
--根據庫房號和設備編號從庫存表中找出該設備的存庫數量,並保存到@var_Mount中
SELECT
@var_Mount = Mount
FROM
tb_Stock
WHERE
F_StoreroomId = @StoreroomId
AND
F_EquipmentId = @au_equipmentId
UPDATE
tb_Stock
SET
Mount = Mount - @au_equipmentMount
WHERE
F_StoreroomId = @StoreroomId
AND
F_EquipmentId = @au_equipmentId
IF @@ERROR <> 0 --未知錯誤
BEGIN
ROLLBACK TRANSACTION --回滾
CLOSE stockBill_cursor --關閉遊標
DEALLOCATE stockBill_cursor
RETURN @@ERROR --返回錯誤代碼
END
FETCH NEXT FROM stockBill_cursor --取下一條
INTO @au_equipmentId, @au_equipmentMount
END -- WHILE
COMMIT TRANSACTION --提交事務
END --IF(@Out_equipmentNotExists = @Empty AND @Out_equipmentNotEnough = @Empty)
CLOSE stockBill_cursor --關閉遊標
DEALLOCATE stockBill_cursor
RETURN 0 --成功返回(執行該過程沒有系統出錯錯誤)
@StoreroomId INT = NULL,--庫房編號
@EquipmentIds VARCHAR(5000) = NULL,--設備編號,各設備編號間用逗號隔開,例如:1,2,3,4
@EquipmentMount VARCHAR(5000) = NULL,--設備數量,各設備數量間用逗號隔開,例如:11,15,20,5
@Out_equipIdNotExists VARCHAR(5000) OUTPUT, --不存在的設備ID,各設備用逗號隔開
@Out_equipNameNotExists VARCHAR(5000) OUTPUT, --不存在的設備名稱,各設備用逗號隔開
@Out_equipIdNotEnough VARCHAR(5000) OUTPUT, --庫存不夠的設備ID,各設備用逗號隔開
@Out_equipNameNotEnough VARCHAR(5000) OUTPUT, --庫存不夠的設備名稱,各設備用逗號隔開
@Out_Stockpile VARCHAR(5000) OUTPUT --設備ID的庫存量,各設備用逗號隔開
AS
SET NOCOUNT ON
SET CURSOR_CLOSE_ON_COMMIT OFF --設置手動關閉遊標,使事務不會影響到遊標的打開和關閉
DECLARE
@Empty CHAR(1), --空串
@Split CHAR(1),--分隔符
@equipName VARCHAR(100)
SET @Empty = ''
SET @Split = ','
SET @Out_equipIdNotExists = @Empty --初始化爲空串
SET @Out_equipIdNotEnough = @Empty
SET @Out_equipNameNotExists = @Empty
SET @Out_equipNameNotEnough = @Empty
SET @Out_Stockpile = @Empty
DECLARE
@tb_EquipmentIds TABLE([Id] INT IDENTITY (1,1),EquipmentId INT)--表變量,設備編號表
DECLARE
@tb_EquipmentMount TABLE([Id] INT IDENTITY (1,1),EquipmentMount INT)--表變量,設備數量表
INSERT INTO @tb_EquipmentIds SELECT * FROM dbo.f_splitSTR(@EquipmentIds,@Split)
--拆分設備編號,並將結果插入到設備編號表(表變量)中
INSERT INTO @tb_EquipmentMount SELECT * FROM dbo.f_splitSTR(@EquipmentMount,@Split)
--拆分設備數量,並將結果插入到設備數量表(表變量)中
DECLARE @au_equipmentId VARCHAR(10), --設備編號
@au_equipmentMount INT,--設備數量
@var_Mount INT--庫存數量
--將設備編號表和設備數量表關聯,按設備編號分組統計出各設備的出庫數量
--注意遍歷了兩次該遊標,第一次用來檢查設備,第二次用來更新設備
--(若第一次遍歷設備通過後,才進行第二次,否則不進行)
DECLARE stockBill_cursor CURSOR LOCAL FAST_FORWARD FOR --聲明並定義快速只進的本地遊標
SELECT
EquipmentId,
SUM(EquipmentMount) AS Mount
FROM
@tb_EquipmentIds AS a
INNER JOIN
@tb_EquipmentMount AS b
ON
a.[ID] = b.[ID]
GROUP BY EquipmentId
OPEN stockBill_cursor
--第一次遍歷:檢查設備是否在庫房中存在,檢查設備的庫存是否不足。若存在且庫存夠,
--才進行第二次遍歷(更新庫存)
FETCH NEXT FROM stockBill_cursor
INTO @au_equipmentId, @au_equipmentMount
--將當前設備編號保存到@au_equipmentId中,將當前設備數量保存到@au_equipmentMount中
WHILE @@FETCH_STATUS = 0
BEGIN
SET @var_Mount = NULL
--根據庫房號和設備編號從庫存表中找出該設備的存庫數量,並保存到@var_Mount中
SELECT
@var_Mount = Mount
FROM
tb_Stock
WHERE
F_StoreroomId = @StoreroomId
AND
F_EquipmentId = @au_equipmentId
SELECT @equipName = EquipmentName FROM dbo.tb_Equipment WHERE P_EquipmentId = @au_equipmentId
IF(@var_Mount IS NULL) --若@var_Mount=NULL表明不存在該設備
BEGIN
SET @Out_equipIdNotExists = @Out_equipIdNotExists + @au_equipmentId + @Split
SET @Out_equipNameNotExists = @Out_equipNameNotExists + @equipName + @Split
END
ELSE
BEGIN --否則存在該設備
--所取數量與庫存數量比較,若大於庫存數量, 將該設備編號記錄下來。
IF (@au_equipmentMount > @var_Mount)
BEGIN
SET @Out_equipIdNotEnough = @Out_equipIdNotEnough + @au_equipmentId + @Split-
-記錄庫存不夠的設備,用逗號隔開
SET @Out_equipNameNotEnough = @Out_equipNameNotEnough + @equipName + @Split
SET @Out_Stockpile = @Out_Stockpile + LTRIM(STR(@var_Mount))+@Split
END
END -- IF(@var_Mount IS NULL)
FETCH NEXT FROM stockBill_cursor --取下一條
INTO @au_equipmentId, @au_equipmentMount
END -- WHILE
--若@Out_equipmentNotExists和@Out_equipmentNotEnough都是空串,表明
--即不存在庫存不夠的設備, 也沒有庫房中不存在的設備
IF(@Out_equipIdNotExists = @Empty AND @Out_equipIdNotEnough = @Empty)
BEGIN
CLOSE stockBill_cursor --關閉遊標
OPEN stockBill_cursor --再次打開遊標
FETCH NEXT FROM stockBill_cursor --第二次遍歷,更新庫存.
INTO @au_equipmentId, @au_equipmentMount
BEGIN TRANSACTION
WHILE @@FETCH_STATUS = 0
BEGIN
SET @var_Mount = NULL
--根據庫房號和設備編號從庫存表中找出該設備的存庫數量,並保存到@var_Mount中
SELECT
@var_Mount = Mount
FROM
tb_Stock
WHERE
F_StoreroomId = @StoreroomId
AND
F_EquipmentId = @au_equipmentId
UPDATE
tb_Stock
SET
Mount = Mount - @au_equipmentMount
WHERE
F_StoreroomId = @StoreroomId
AND
F_EquipmentId = @au_equipmentId
IF @@ERROR <> 0 --未知錯誤
BEGIN
ROLLBACK TRANSACTION --回滾
CLOSE stockBill_cursor --關閉遊標
DEALLOCATE stockBill_cursor
RETURN @@ERROR --返回錯誤代碼
END
FETCH NEXT FROM stockBill_cursor --取下一條
INTO @au_equipmentId, @au_equipmentMount
END -- WHILE
COMMIT TRANSACTION --提交事務
END --IF(@Out_equipmentNotExists = @Empty AND @Out_equipmentNotEnough = @Empty)
CLOSE stockBill_cursor --關閉遊標
DEALLOCATE stockBill_cursor
RETURN 0 --成功返回(執行該過程沒有系統出錯錯誤)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.