CREATE TRIGGER TG_ProjectName
ON Table1
AFTER UPDATE
AS
BEGIN
UPDATE Table2
SET [工程名] = i.工程名
FROM Table2 t
INNER JOIN inserted i ON t.ProjID = i.ID;
END
| 操作 | INSERTED | DELETED | 說明 |
|---|---|---|---|
| INSERT | 新列 (完整) | 空 | 新資料同時寫入表與 INSERTED |
| DELETE | 空 | 舊列 (完整) | 舊資料從表移至 DELETED |
| UPDATE | 新列 (更新後) | 舊列 (更新前) | 相當於 DELETE + INSERT |
| 類型 | 觸發時機 | 典型用途 | INSERTED/DELETED 可用性 |
|---|---|---|---|
| AFTER (FOR) | 動作完成、約束檢查後 | 稽核日誌、跨表同步、衍生資料維護、郵件通知 | 完整可用 |
| INSTEAD OF | **取代** 原動作執行 | 視圖更新、複雜業務規則攔截、跨表原子操作、軟刪除實作 | 完整可用 |
| DDL | CREATE/ALTER/DROP/DISABLE/ENABLE | 結構變更稽核、防止誤刪、自動同步結構 | **不可用** (使用 EVENTDATA()) |
視圖含衍生欄位、多表 JOIN、聚合時**不可直接更新**。INSTEAD OF 觸發器接管更新邏輯:
CREATE VIEW EmployeeNames (EmployeeID, LName, FName)
AS SELECT EmployeeID, LastName, FirstName FROM Employees;
CREATE TRIGGER TR_EmployeeNames_Update
ON EmployeeNames
INSTEAD OF UPDATE
AS
BEGIN
UPDATE Employees
SET LastName = i.LName, FirstName = i.FName
FROM Employees e
INNER JOIN inserted i ON e.EmployeeID = i.EmployeeID;
END
INSERTED/DELETED 結構** 與視圖 SELECT 清單一致,而非基表結構。衍生運算式 (常數、函數) 會被忽略,複雜運算式需觸發器自行處理。
-- 資料庫級:防止誤刪表
CREATE TRIGGER TR_Prevent_Drop_Table
ON DATABASE
FOR DROP_TABLE
AS
BEGIN
PRINT '資料庫禁止直接 DROP TABLE,請使用受控部署流程。';
ROLLBACK;
-- 可用 EVENTDATA() 取得登入名、物件名、SQL 文本、時間
END
-- 伺服器級:稽核所有 CREATE_LOGIN
CREATE TRIGGER TR_Audit_Create_Login
ON ALL SERVER
FOR CREATE_LOGIN
AS
BEGIN
INSERT INTO AuditDB.dbo.LoginAudit (EventXML, EventTime)
VALUES (EVENTDATA(), GETDATE());
END
觸發器是資料庫端業務邏輯的「最後一道防線」與「自動化執行器」。掌握 `INSERTED`/`DELETED` 語義、AFTER vs INSTEAD OF 選型、DDL 觸發器稽核範圍、視圖更新代理、效能與交易陷阱,**善用觸發器簡化應用層、濫用觸發器拖垮資料庫**。原則:**能用約束/預設值/計算欄位解決的,絕不寫觸發器;必須寫時,儘量簡單、集合化、非同步化**。