觸發器是綁定於資料表/檢視表的特殊預存程序,於 INSERT、UPDATE、DELETE 事件發生時自動執行。
觸發器類型
- AFTER (FOR) 觸發器:動作完成後執行 (預設)。僅限資料表,不支援檢視表。
- INSTEAD OF 觸發器:取代 原動作執行。支援資料表與檢視表 (檢視表唯一可建立的觸發器類型)。
建立語法
CREATE TRIGGER trigger_name
ON table_or_view
[FOR | AFTER | INSTEAD OF] [INSERT] [,] [UPDATE] [,] [DELETE]
[WITH ENCRYPTION] [NOT FOR REPLICATION]
AS
BEGIN
-- T-SQL 陳述式
END
關鍵限制
- 不可在觸發器中使用:
CREATE/ALTER/DROP DATABASE/TABLE/INDEX、DISK、LOAD/RESTORE、RECONFIGURE。(TRUNCATE TABLE 可用)
- 觸發器內部發生執行錯誤 → 整個觸發動作回滾 (原 INSERT/UPDATE/DELETE 無效)。
TRUNCATE TABLE、WRITETEXT、UPDATETEXT、SELECT 不會觸發 觸發器。
虛擬表:inserted / deleted
| 虛擬表 | 內容 | 適用事件 |
| inserted | 新資料列 (INSERT) / 更新後資料列 (UPDATE) | INSERT, UPDATE |
| deleted | 刪除資料列 (DELETE) / 更新前資料列 (UPDATE) | DELETE, UPDATE |
注意:text/image/MAX 型別欄位在虛擬表中讀取為 NULL,需用 OUTPUT 子句或變更追蹤。
常用函數
IF UPDATE(column_name):檢查欄位是否被 INSERT/UPDATE 修改。
COLUMNS_UPDATED():位元遮罩表示所有被更新欄位。
TRIGGER_NESTLEVEL():目前巢狀層級。
遞歸與巢狀觸發器
- 直接遞歸:觸發器操作同一資料表再次觸發自己。預設 關閉。啟用:
EXEC sp_dboption 'dbname', 'recursive triggers', true。
- 間接遞歸:觸發器 A → 觸發器 B → 觸發器 A 形成環。預設 開啟 (受巢狀設定控制)。
- 巢狀觸發器:觸發器鏈 A → B → C... 最大 32 層。控制:
EXEC sp_configure 'nested triggers', 0/1 (需 RECONFIGURE)。
管理指令
-- 檢視觸發器內容
EXEC sp_helptext 'trigger_name';
-- 查詢資料庫所有觸發器
SELECT name FROM sys.objects WHERE type = 'TR';
-- 刪除觸發器
DROP TRIGGER trigger_name;
-- 重新命名
EXEC sp_rename 'old_name', 'new_name';
-- 檢視觸發器屬性
EXEC sp_helptrigger 'table_name' [, 'INSERT|UPDATE|DELETE'];
最佳實務建議
- 能用條件約束 (CHECK、FK、DEFAULT、UNIQUE) 解決的完整性規則,優先用條件約束 (驗證發生在資料修改前,效能較好)。
- 級聯刪除/更新用外來鍵 CASCADE 選項,而非觸發器。
- 避免同一事件建立多個觸發器 (執行順序不確定,維護困難)。
- 觸發器邏輯保持簡單,複雜業務移至預存程序/應用層。
- 謹慎使用遞歸/巢狀觸發器,易造成效能問題與無限迴圈。
- 上一篇文章: SQL Server 2000 排序規則衝突解決:跨資料庫/跨欄位 JOIN 錯誤處理
- 下一篇文章: SQL Server 安全性強化清單:服務帳戶、防火牆、NTFS、安裝檔清理
Copyright ©
程式碼之家 All Rights Reserved