觸發器是隱式執行的 PL/SQL 塊,針對特定數據庫事件(DML、DDL、系統事件)自動觸發,是實現複雜業務規則、審計追蹤、數據完整性輔助的關鍵手段。本文系統梳理觸發器語法結構、分類體系與核心伪列機制。
CREATE [OR REPLACE] TRIGGER trigger_name
{BEFORE | AFTER | INSTEAD OF}
{INSERT | UPDATE [OF column] | DELETE}
ON {table_name | view_name | DATABASE | SCHEMA}
[REFERENCING [OLD AS old_alias] [NEW AS new_alias] [PARENT AS parent_alias]]
[FOR EACH ROW]
[FOLLOWS trigger_name]
[DISABLE]
[WHEN (condition)]
[DECLARE
-- 聲明區
PRAGMA AUTONOMOUS_TRANSACTION; -- 自治事務
]
BEGIN
-- 執行區
EXCEPTION
-- 異常處理
END [trigger_name];
| 子句 | 說明 |
|---|---|
| BEFORE / AFTER | 觸發時機:操作前或操作後 |
| INSTEAD OF | 替代觸發器,僅用於視圖,將 DML 轉發到底表 |
| INSERT / UPDATE / DELETE | 觸發事件,可組合;UPDATE 可限定列(UPDATE OF col) |
| ON table/view/DATABASE/SCHEMA | 觸發對象:表、視圖、數據庫級、模式級 |
| REFERENCING | 為 :OLD、:NEW、:PARENT 定義別名,提升可讀性 |
| FOR EACH ROW | 行級觸發器(缺省為語句級) |
| FOLLOWS | 指定觸發順序(11g+),解決同類觸發器執行序列不確定問題 |
| DISABLE | 創建時禁用,需 ALTER TRIGGER ... ENABLE 啟用 |
| WHEN | 行級觸發器的額外過濾條件,減少不必要觸發 |
| PRAGMA AUTONOMOUS_TRANSACTION | 聲明自治事務,允許觸發器內獨立提交/回滾 |
| 維度 | 類型 | 特點 |
|---|---|---|
| 觸發時機 | BEFORE | 可修改 :NEW 值,常用於驗證、自動填充 |
| AFTER | 不可修改 :NEW,常用於日志、級聯操作 | |
| 觸發粒度 | 語句級 | 無 FOR EACH ROW,每條觸發語句僅觸發一次 |
| 行級 | FOR EACH ROW,每受影響行觸發一次,可訪問 :OLD/:NEW | |
| 觸發事件 | DML 觸發器 | INSERT/UPDATE/DELETE,最常用 |
| DDL 觸發器 | CREATE/ALTER/DROP,審計結構變更 | |
| 系統事件觸發器 | STARTUP/SHUTDOWN/LOGON/LOGOFF/SERVERERROR | |
| 特殊類型 | INSTEAD OF | 視圖專用,使不可更新視圖變為可更新 |
觸發器內需記錄操作日志,但主事務可能回滾,日志不應丟失:
CREATE OR REPLACE TRIGGER audit_trg
AFTER INSERT OR UPDATE OR DELETE ON sensitive_table
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO audit_log(...) VALUES (...);
COMMIT; -- 僅提交自治事務
END;
設計原則: 能用約束解決的不用觸發器;能用應用層解決的盡量不下沉到數據庫;觸發器邏輯必須極簡、極快,避免複雜查詢或遠程調用,否則嚴重拖慢 DML 性能。