SQL Server 的 DML 觸發器依觸發時機與實作語言可分為 AFTER 觸發器、INSTEAD OF 觸發器 以及 CLR 觸發器。本文聚焦於最常用的 AFTER 觸發器,詳細說明其特性、建立語法、實戰範例與注意事項。
| 類型 | 觸發時機 | 典型用途 |
|---|---|---|
| AFTER | INSERT/UPDATE/DELETE 執行完成後、約束檢查通過後 | 稽核記錄、衍生資料維護、跨表同步 |
| INSTEAD OF | 約束檢查之前,可取代原 DML 動作 | 視圖更新、複雜驗證邏輯、攔截並轉向操作 |
| CLR | 可實作為 AFTER 或 INSTEAD OF,也可作為 DDL 觸發器 | 需 .NET 程式庫支援的複雜運算 |
在觸發器本文中不可使用下列陳述式:
ALTER DATABASE、CREATE DATABASE、DROP DATABASEBACKUP、RESTORE、LOAD DATABASE、LOAD LOGRECONFIGUREINSERT、UPDATE、DELETE 三種操作。inserted(新資料)與 deleted(舊資料),結構與基底表相同。情境:刪除主表 PriTable 訂單時,自動清除明細表 DetailTable 對應資料。
USE AdventureWorks;
GO
CREATE TABLE PriTable (
OrderID int IDENTITY(1,1),
OrderTotal money
);
GO
CREATE TABLE DetailTable (
OrderID int,
ProductID int,
ProductCount int NOT NULL,
Price money
);
GO
-- 範例資料
INSERT INTO PriTable VALUES (2100.00), (1000.00);
INSERT INTO DetailTable VALUES (1,1,10,110.00), (1,2,10,100.00), (2,2,10,100.00);
GO
CREATE TRIGGER PriTrigger
ON PriTable
AFTER DELETE
AS
BEGIN
DELETE FROM DetailTable
WHERE OrderID IN (SELECT OrderID FROM deleted);
-- 示範用 PRINT,實務上建議移除或改用 RAISERROR/LOG
PRINT N'已刪除 DetailTable 相關明細資料';
END;
GO
-- 刪除主表 OrderID=1 的訂單
DELETE FROM PriTable WHERE OrderID = 1;
-- 檢查結果
SELECT * FROM PriTable;
SELECT * FROM DetailTable;
觸發器會自動刪除 DetailTable 中 OrderID=1 的三筆明細。
inserted。deleted。deleted,新值進 inserted 與基底表。這兩個虛擬表由 SQL Server 自動建立與管理,僅存在於觸發器執行期間。
若執行 DELETE FROM PriTable WHERE OrderID = 3(該筆不存在),觸發器依然會啟動,此時 deleted 為空表。此特性需注意,避免在觸發器中執行高成本操作導致效能浪費。
PRINT、SELECT * 等回傳結果的陳述式,以免干擾呼叫端應用程式。SET NOCOUNT ON 減少網路傳輸。sp_configure 'nested triggers', 0 關閉。AFTER 觸發器是資料完整性與稽核的利器,善用虛擬表 inserted/deleted 即可實作靈活的資料同步邏輯。