SQL Server Trigger 觸發器
阿新 • • 發佈:2021-07-28
參考:
SQL Server Triggers and Transactions
介紹
觸發器適合用在維護冗餘. 它可以監聽指定 table 的 insert, update, delete.
監聽時機分 2 種, after 和 instead of
after 就是在資料變化之後觸發. 在 trigger 中通過訪問 inserted 和 deleted 就可以獲取改動前後的資料.
inserted 和 deleted 是表結構哦, 有多個 row.
instead of 是替代原來的執行 (原來的執行就沒有了哦, trigger 裡面要自己實現), 它在資料還沒有執行前觸發.
關於事務
Trigger 在執行時是自帶事務的, 哪怕原先的執行並沒有開啟事務.
而 Isolation 級別預設是依據原先執行的事務, 但如果內部修改了 Isolation 當返回外部的時候, Isolation 會自動被調回去.
關於遞迴
一個 trigger 裡面執行了另一些 insert, update, delete 會繼續觸發其它 trigger.
所以 trigger 是支援遞迴的, 需要自行控制避免死迴圈哦.
例子
監聽 after insert, 更新冗餘 (要記得 inserted 是表裡面有多條資料, 要批量處理)
DROP TRIGGER TR_InvoiceItem_AfterInsert_ForRedundancy_Invoice_TotalAmount;GO CREATE TRIGGER TR_InvoiceItem_AfterInsert_ForRedundancy_Invoice_TotalAmount ON InvoiceItem AFTER INSERT AS IF (ROWCOUNT_BIG() = 0) RETURN; SET NOCOUNT ON; UPDATE Invoice SET TotalAmount = (SELECT SUM(Subtotal) FROM InvoiceItem WHERE InvoiceId = Invoice.InvoiceId) FROM InvoiceINNER JOIN inserted ON Invoice.InvoiceId = inserted.InvoiceId; GO
判斷 ROWCOUNT_BIG 是有必要的, 因為即便是沒有 row 修改 trigger 也會被觸發. 如果沒有 return 就有可能出現遞迴死迴圈.
監聽 instead of, 做級聯刪除
DROP TRIGGER TR_Invoice_InsteadOfDelete_ForCascade_InvoiceItem; GO CREATE TRIGGER TR_Invoice_InsteadOfDelete_ForCascade_InvoiceItem ON Invoice INSTEAD OF DELETE AS IF (ROWCOUNT_BIG() = 0) RETURN; SET NOCOUNT ON; DELETE InvoiceItem FROM InvoiceItem INNER JOIN deleted ON InvoiceItem.InvoiceId = deleted.InvoiceId; DELETE Invoice FROM Invoice INNER JOIN deleted ON Invoice.InvoiceId = deleted.InvoiceId; GO