| 參數 | 說明 |
| schema_name | DML 觸發器所屬結構描述 (表/檢視所在結構描述) |
| trigger_name | 觸發器名稱,遵循識別碼規則,不可用 #/## 開頭 |
| table | view | 目標物件。檢視只能建立 INSTEAD OF 觸發器 |
| FOR | AFTER | AFTER:所有動作成功 (含約束、級聯) 後觸發。FOR 為預設別名。檢視不可用 AFTER |
| INSTEAD OF | 取代 原觸發動作。每表每事件類型 (I/U/D) 只能有一個。不可用於 WITH CHECK OPTION 的可更新檢視 |
| WITH APPEND | 相容性選項 (相容層級 ≤ 65),現代版本預設即允許同類型多觸發器 |
| NOT FOR REPLICATION | 複寫代理執行時不觸發 |
| ENCRYPTION | 模糊化定義文本,防止發布為複寫品。CLR 觸發器不可用 |
| EXECUTE AS | 指定執行安全內容 (CALLER/SELF/OWNER/'user') |
魔術資料表:inserted / deleted
- 結構與觸發表相同,儲存變更前/後的列映像
INSERT:inserted 有新列,deleted 空
DELETE:deleted 有舊列,inserted 空
UPDATE:deleted 舊值,inserted 新值
- 相容層級 ≥ 80 時,INSTEAD OF 觸發器可透過聯接
inserted 更新 text/ntext/image 欄位
二、DDL Trigger (結構定義觸發器)
CREATE TRIGGER trigger_name
ON { ALL SERVER | DATABASE }
[ WITH [ ,...n ] ]
{ FOR | AFTER } { event_type | event_group } [ ,...n ]
AS { sql_statement [ ; ] [ ,...n ] | EXTERNAL NAME [ ; ] }
::= [ ENCRYPTION ] [ EXECUTE AS Clause ]
範圍與事件
ON DATABASE:目前資料庫範圍,捕獲 CREATE_TABLE, ALTER_PROCEDURE, DROP_VIEW 等
ON ALL SERVER:實例範圍,捕獲 CREATE_DATABASE, ALTER_LOGIN, CREATE_LOGIN 等
event_group:預定義事件群組,如 DDL_TABLE_EVENTS (含 CREATE/ALTER/DROP TABLE)、DDL_PROCEDURE_EVENTS 等
- 事件資訊透過
EVENTDATA() XML 函數取得 (見文章 72345)
三、Logon Trigger (登入觸發器)
CREATE TRIGGER trigger_name
ON ALL SERVER
[ WITH [ ,...n ] ]
{ FOR | AFTER } LOGON
AS { sql_statement [ ; ] [ ,...n ] | EXTERNAL NAME [ ; ] }
::= [ ENCRYPTION ] [ EXECUTE AS Clause ]
應用場景
- 限制特定登入的並發連線數
- 記錄登入稽核 (IP、時間、應用程式)
- 阻擋非授權 IP/時段登入
- 注意:Logon Trigger 失敗會導致登入失敗,邏輯必須極度健壯,建議用
TRY...CATCH 吞掉錯誤
四、CLR 觸發器 (EXTERNAL NAME)
- 組件必須已在資料庫註冊 (
CREATE ASSEMBLY)
- 方法簽名:
public static void MethodName(),無參數、無回傳值
- 類別名稱若含命名空間需用
[Namespace.ClassName] 或 "Namespace.ClassName" 括起
- 不支援巢狀類別
五、管理與除錯指令
-- 檢視觸發器定義
EXEC sp_helptext 'trigger_name';
SELECT definition FROM sys.sql_modules WHERE object_id = OBJECT_ID('trigger_name');
-- 啟用/停用
ENABLE TRIGGER trigger_name ON TABLE; -- 或 DATABASE / ALL SERVER
DISABLE TRIGGER trigger_name ON TABLE;
-- 刪除
DROP TRIGGER [schema_name.]trigger_name; -- DML
DROP TRIGGER trigger_name ON DATABASE; -- DDL Database
DROP TRIGGER trigger_name ON ALL SERVER; -- DDL Server / Logon
-- 查看觸發器中繼資料
SELECT * FROM sys.triggers WHERE name = 'trigger_name'; -- DML
SELECT * FROM sys.server_triggers WHERE name = 'trigger_name'; -- DDL Server / Logon
六、最佳實務提醒
- 避免巢狀觸發:
sp_configure 'nested triggers', 0 或觸發器內 IF TRIGGER_NESTLEVEL() > 1 RETURN
- 避免遞歸觸發:
sp_configure 'recursive triggers', 0 或資料庫屬性關閉
- 保持輕量:觸發器執行時間直接影響 DDL/DML 回應延遲,複雜邏輯改非同步 (Service Broker / 佇列表 + Agent 作業)
- 權限最小化:使用
EXECUTE AS CALLER 或明確低權限帳號
- 文件化:擴充屬性記錄用途、作者、建立日期、相依表
- 上一篇文章: SQL Server 刪除資料庫使用者受阻:「主體擁有結構描述無法刪除」完整解決方案
- 下一篇文章: SQL Server 批次授權儲存程序與函數:動態腳本自動化 GRANT EXECUTE/SELECT 權限
Copyright ©
程式碼之家 All Rights Reserved