| 事件類型 | 觸發時機 | 支援 FOR EACH ROW | 典型用途 |
| DML (INSERT/UPDATE/DELETE) | BEFORE / AFTER / INSTEAD OF | 是(行級) | 稽核、衍生欄維護、跨表同步 |
| DDL (CREATE/ALTER/DROP) | BEFORE / AFTER | 否(陳述式級) | 結構變更稽核、防誤刪 |
| Database (STARTUP/SHUTDOWN/LOGON/LOGOFF/SERVERERROR) | AFTER (STARTUP/LOGON) / BEFORE (SHUTDOWN/LOGOFF) | 否 | 登入審計、啟動初始化、錯誤通知 |
建立語法
CREATE [OR REPLACE] TRIGGER [schema.]trigger_name
{BEFORE | AFTER | INSTEAD OF} event
ON {table_name | view_name | DATABASE}
[FOR EACH ROW [WHEN (condition)]]
[FOLLOWS | PRECEDES other_trigger] -- 11g+ 指定觸發順序
[ENABLE | DISABLE]
DECLARE
-- 區域變數
BEGIN
-- PL/SQL 區塊
-- 行級可用 :OLD、:NEW 偽記錄
END;
/
關鍵概念
- 行級 vs 陳述式級:
FOR EACH ROW 表示受影響每行觸發一次;省略則整個 DML 陳述式只觸發一次。
- :OLD / :NEW:行級觸發器專用偽記錄。
:OLD.col = 修改前值(INSERT 為 NULL),
:NEW.col = 修改後值(DELETE 為 NULL)。
- INSTEAD OF:僅用於 View,取代 DML 操作,實現不可更新 View 的更新邏輯。
- WHEN 條件:行級觸發器可加
WHEN (condition) 過濾,減少不必要觸發開銷。
實用範例
1. 稽核記錄(行級 AFTER)
CREATE OR REPLACE TRIGGER trg_emp_audit
AFTER INSERT OR UPDATE OR DELETE ON emp
FOR EACH ROW
BEGIN
INSERT INTO emp_audit (empno, oper_type, oper_time, old_sal, new_sal)
VALUES (
NVL(:NEW.empno, :OLD.empno),
CASE WHEN INSERTING THEN 'INS' WHEN UPDATING THEN 'UPD' ELSE 'DEL' END,
SYSDATE,
:OLD.sal,
:NEW.sal
);
END;
/
2. 自動維護衍生欄(BEFORE)
CREATE OR REPLACE TRIGGER trg_emp_upd_chg
BEFORE UPDATE ON emp
FOR EACH ROW
WHEN (OLD.sal != NEW.sal) -- 僅薪資變動時觸發
BEGIN
:NEW.last_sal_chg := SYSDATE;
:NEW.sal_chg_count := NVL(:OLD.sal_chg_count, 0) + 1;
END;
/
3. 防止誤刪重要表(DDL BEFORE)
CREATE OR REPLACE TRIGGER trg_prevent_drop
BEFORE DROP ON DATABASE
WHEN (ora_dict_obj_name IN ('EMP', 'DEPT') AND ora_dict_obj_type = 'TABLE')
BEGIN
RAISE_APPLICATION_ERROR(-20001, '禁止刪除核心業務表!');
END;
/
管理命令
| 操作 | 語法 |
| 啟用單一觸發器 | ALTER TRIGGER trg_name ENABLE; |
| 停用單一觸發器 | ALTER TRIGGER trg_name DISABLE; |
| 啟用表上所有觸發器 | ALTER TABLE tbl_name ENABLE ALL TRIGGERS; |
| 停用表上所有觸發器 | ALTER TABLE tbl_name DISABLE ALL TRIGGERS; |
| 刪除觸發器 | DROP TRIGGER trg_name; |
最佳實踐與避坑指南
- 避免觸發器鏈式反應:觸發器中執行 DML 可能再觸發其他觸發器,導致遞歸或效能雪崩。必要時用
DBMS_UTILITY.FORMAT_CALL_STACK 檢測深度。
- 謹慎使用 BEFORE 修改 :NEW:邏輯錯誤可能導致資料不一致;複雜驗證建議放在 Application 層或 CHECK CONSTRAINT。
- 大量資料操作時暫停觸發器:
ALTER TABLE ... DISABLE ALL TRIGGERS → 執行批次 → ENABLE ALL TRIGGERS。
- 命名規範:
trg_