Oracle 資料庫內建數個系統級觸發器,展示了 AFTER STARTUP、AFTER DROP ON DATABASE、BEFORE DELETE FOR EACH ROW 等核心觸發時機與實作模式。本文解析四大經典範例,並提煉可直接套用的觸發器模板。
CREATE OR REPLACE TRIGGER mdsys.sdo_drop_user
AFTER DROP ON DATABASE
DECLARE
stmt VARCHAR2(200);
BEGIN
IF ora_dict_obj_type = 'USER' THEN
stmt := 'DELETE FROM sdo_geom_metadata_table WHERE sdo_owner = ''' || ora_dict_obj_name || '''';
EXECUTE IMMEDIATE stmt;
END IF;
END;
/
模式:AFTER DROP ON DATABASE + ora_dict_obj_type/name 判斷被刪除物件類型與名稱,動態執行清理 SQL。適用於:自動清理被刪除使用者的空間中繼資料、審計表、自訂快取表等。
CREATE OR REPLACE TRIGGER sys.aurora$server$startup
AFTER STARTUP ON DATABASE
CALL dbms_java.server_startup;
模式:AFTER STARTUP ON DATABASE + CALL 直接呼叫封裝好的初始化程序。適用於:JVM 初始化、排程作業啟動、快取預熱、外部服務註冊。
CREATE OR REPLACE TRIGGER sys.jis$role_trigger$
AFTER DROP ON DATABASE
WHEN (ora_dict_obj_type = 'ROLE')
BEGIN
sns_context.role_dropped(ora_dict_obj_name);
http_security_cascade.principal_dropped(ora_dict_obj_name);
END;
/
模式:WHEN 子句過濾事件類型,減少觸發器本體執行開銷。適用於:角色/使用者/配置檔刪除時的跨系統級聯清理(SSO、權限快取、審計日誌)。
CREATE OR REPLACE TRIGGER yspj.t_bill_remain_del
BEFORE DELETE ON bill_remain
FOR EACH ROW
BEGIN
INSERT INTO bill_remain_tiger
VALUES (
:old.bill_remainid, :old.bill_typeid, :old.remain_num,
:old.add_time, :old.org_id, :old.state,
:old.bill_id, '刪除記錄', SYSDATE, USER
);
END;
/
模式:BEFORE DELETE FOR EACH ROW + :OLD 伪記錄捕獲完整舊值,寫入審計/備份表。適用於:關鍵業務表刪除審計、軟刪除實作、異動追蹤。
| 原則 | 說明 |
|---|---|
| 盡量用 BEFORE | 可修改 :NEW 值、阻止操作(RAISE_APPLICATION_ERROR),效能優於 AFTER。 |
| 避免觸發器鏈 | 觸發器中再觸發其他觸發器,極難除錯;改用封裝程序統一協調。 |
| FOR EACH ROW 慎用 | 逐列觸發,大量 DML 時開銷巨大;改用 STATEMENT 級 + 臨時表/複合觸發器 (11g+)。 |
| 不在觸發器中 COMMIT | 觸發器屬於觸發交易一部分,COMMIT 會導致 ORA-04092;交易控制留給呼叫端。 |
| 使用複合觸發器 | 11g+ COMPOUND TRIGGER 可在同一觸發器中處理 BEFORE STATEMENT / BEFORE EACH ROW / AFTER EACH ROW / AFTER STATEMENT,解決「需彙總後再處理」場景。 |
| 命名規範 | trg_ |