不過, 假如在 TableA 中加入了一個 AFTER UPDATE 的 trigger(TableA_UptTrigger) 去修改 TableA 的資料, 很顯然地可能會導致迴圈的產生. 此時, 有以下兩種選擇:
- 將 trigger 的遞迴功能關閉:
ALTER DATABASE databasename SET RECURSIVE_TRIGGERS OFF
這個設定是針對整個資料庫做的設定, 所以如果本身寫 trigger 的經驗不多, 先關掉也許也保險一點. - 在 RECURSIVE_TRIGGERS 是 ON 的狀態下, 透過 TRIGGER_NESTLEVEL() 這個函式來避免無窮迴圈. 例如以下的例子:
IF TRIGGER_NESTLEVEL()<2 BEGIN UPDATE TableA SET UpdateTime=getdate() FROM INSERTED I WHERE I.Seq=TableA.Seq END
Declare @uptTime datetime Set @uptTime=getdate() UPDATE TableA SET UpdateTime=@uptTime FROM INSERTED I WHERE I.Seq=TableA.Seq -- 這邊的 Log 表紀錄的是新資料(INSERTED) INSERT INTO TableA_Log(Seq, Status, UpdateTime) SELECT I.Seq, I.Status, @uptTime FROM INSERTED I若是你不止要修改 UpdateTime, 還有一些 Status 要改(ex: Status 的修改規則為舊的值若為 C 則改成 U, 其餘照新值設定), 可以參考以下的例子:
Declare @uptTime datetime Set @uptTime=getdate() UPDATE TableA SET UpdateTime=@uptTime , Status=CASE WHEN D.Seq='C' THEN 'U' ELSE I.Status END FROM INSERTED I INNER JOIN DELETED D ON I.Seq=D.Seq WHERE I.Seq=TableA.Seq -- 這邊的 Log 表紀錄的是新資料(INSERTED) INSERT INTO TableA_Log(Seq, Status, UpdateTime) SELECT I.Seq, CASE WHEN D.Seq='C' THEN 'U' ELSE I.Status END, @uptTime FROM INSERTED I INNER JOIN DELETED D ON I.Seq=D.Seq原則上還是建議不要讓 trigger 做太複雜或危險的事(ex:迴圈), 以避免將來開發上多了一塊工程師常遺漏的黑色地帶.
沒有留言:
張貼留言