2014-01-24 74 views
0

那麼,在SQL Server 2012中,我有跟蹤的......嗯,項目容量表...SQL Server 2012的多個觸發

基本上,Storage表有CapacityFilled列,Filled列需要在每次Item表發生任何變化時更新,但不能高於Capacity值或者低於「0」。我試圖把所有這一切都放在一個觸發器中......我希望我目前有任何意義......這是我試圖做的,我認爲觸發器只有在INSERT發生時纔會激活......

ALTER TRIGGER [dbo].[CapCheck] 
ON [dbo].[Item] 
AFTER INSERT, DELETE, UPDATE 
AS 
BEGIN 
DECLARE @Amount int 
DECLARE @S_ID int 

SELECT @Amount = Amount, @S_ID = S_ID 
FROM inserted 

IF @Amount = NULL 
BEGIN 
    SELECT @Amount = -(Amount), @S_ID = S_ID 
    FROM deleted 
END 

DECLARE @Filled int 
DECLARE @Capacity int 

SELECT @Filled = Filled, @Capacity = Capacity 
FROM Storage 
WHERE S_ID = @S_ID 

SET @Filled = @Filled + @Amount 

IF @Capcaity < @Filled OR @Filled < 0 
BEGIN 
    ROLLBACK TRANSACTION 
END 
ELSE 
BEGIN 
    UPDATE Storage 
    SET Filled = @Filled 
    WHERE S_ID = @S_ID 
END 
END 

任何意見非常感謝,你們是最棒的:d

回答

0

你根本缺陷是,你似乎期望觸發被解僱行一次 - 這是的在SQL Server中的情況。相反,觸發器會根據語句觸發一次,而僞表Inserted可能包含多行

鑑於該表可能包含多行 - 您期望在此處選擇哪一個?

SELECT @Amount = Amount, @S_ID = S_ID 
FROM inserted  

它是不確定的 - 你可以從任意行中Inserted得到的值。

您需要用知識重寫您的整個觸發器Inserted包含多行!您需要使用基於集合的操作 - 不要指望Inserted中只有一行!

另外:我會強烈建議寫單獨觸發每個操作 - 有一個觸發INSERT,另一個用於DELETE和第三個用於UPDATE。這會使觸發器代碼變得更加容易(因爲您不必多次檢查正在處理的操作類型)。

+0

謝謝你的回答,似乎我必須重新考慮這個問題...... –