觸發器是資料庫內建的業務規則執行點。本文系統整理 AFTER 與 INSTEAD OF 觸發器建立語法、INSERTED/DELETED 邏輯表行為、三種 DML 操作下的資料分佈、視圖上 INSTEAD OF 觸發器的欄位對應規則,並提供實戰範例與最佳實務。
CREATE TRIGGER TG_ProjectName
ON Table1
AFTER UPDATE
AS
BEGIN
UPDATE T2
SET ProjectName = I.ProjectName
FROM Table2 T2
INNER JOIN INSERTED I ON T2.ProjID = I.ID;
END;
| DML 操作 | INSERTED 表 | DELETED 表 | 說明 |
|---|---|---|---|
| INSERT | 新資料列 | 空 | 新列同時寫入 INSERTED 與基底表 |
| DELETE | 空 | 舊資料列 | 舊列從基底表移至 DELETED |
| UPDATE | 新資料列 | 舊資料列 | 相當於 DELETE + INSERT:舊→DELETED,新→INSERTED+基底表 |
INSERTED/DELETED 中的 TEXT/NTEXT/IMAGE 欄位 (SQL 2000/2005)。INSTEAD OF 觸發器可參考上述大型物件欄位。@@ROWCOUNT 或 IF UPDATE(Col) 判斷影響範圍。CREATE VIEW V_EmpName (EmpID, LName, FName)
AS SELECT EmployeeID, LastName, FirstName FROM Northwind.dbo.Employees;
-- 觸發器接收的 INSERTED/DELETED 結構與視圖 SELECT 清單一致:
-- EmpID (INT), LName (NVARCHAR), FName (NVARCHAR)
-- 複雜運算式 (函數、常數) 會被忽略,觸發器需自行處理。
CREATE TRIGGER TR_SoftDelete_Orders
ON Orders
INSTEAD OF DELETE
AS
BEGIN
SET NOCOUNT ON;
UPDATE O
SET IsDeleted = 1, DeletedAt = SYSDATETIME(), DeletedBy = SUSER_SNAME()
FROM Orders O
INNER JOIN DELETED D ON O.OrderID = D.OrderID;
END;
應用層執行 DELETE FROM Orders WHERE OrderID=100 實際執行 UPDATE,資料保留可供稽核/復原。
SET NOCOUNT ON 減少網路往返。INNER JOIN INSERTED/DELETED 替代游標,集合式操作效能佳。BEGIN TRAN。TEST 環境負測,驗證鎖定鏈與死結風險。MAX(INSERTED.Col) 等聚合可直接用於大型欄位 (VARCHAR(MAX)/VARBINARY(MAX))。MERGE 陳述式可觸發觸發器,INSERTED/DELETED 包含合併結果。SESSION_CONTEXT 可在觸發器間傳遞資訊。