觸發器是針對特定事件自動執行的 PL/SQL 區塊,分為行級、語句級、INSTEAD OF、Schema 級、Database 級五大類。本文詳細解析各類型語法、適用場景、特殊變數、啟用/停用與設計黃金法則。
五大觸發器類型對照
| 類型 | 觸發時機 | 執行頻率 | 典型用途 |
| 行級 | BEFORE/AFTER INSERT/UPDATE/DELETE | 每影響一行執行一次 | 自動填欄位、複雜檢核、審計日誌 |
| 語句級 | BEFORE/AFTER INSERT/UPDATE/DELETE | 每個 DML 語句執行一次 | 統計影響筆數、整體檢核 |
| INSTEAD OF | 針對 VIEW 的 DML | 每行/語句視定義而定 | 使不可更新視圖可更新 |
| Schema 級 | DDL 事件 | 每個 DDL 執行一次 | 記錄結構變更、防刪保護 |
| Database 級 | STARTUP/SHUTDOWN/LOGON/LOGOFF/SERVERERROR | 每個事件一次 | 啟動初始化、登入審計、錯誤通知 |
建立語法通用模板
CREATE [OR REPLACE] TRIGGER trigger_name
{BEFORE | AFTER | INSTEAD OF}
{INSERT | UPDATE [OF col] | DELETE} ON table_name
[FOR EACH ROW] -- 行級必加
[WHEN (condition)] -- 選擇性條件
DECLARE
-- 宣告區
BEGIN
-- 執行區
EXCEPTION
-- 異常處理
END;
關鍵特殊變數::NEW / :OLD
- 僅行級觸發器(
FOR EACH ROW)可用。
:NEW.col:新值(INSERT/UPDATE 有,DELETE 為 NULL)。
:OLD.col:舊值(UPDATE/DELETE 有,INSERT 為 NULL)。
- 可在
BEFORE 觸發器中修改 :NEW.col := ... 實現自動賦值。
實戰範例
範例 1:行級 - 自動產生序列主鍵、禁止更新 PK
CREATE OR REPLACE TRIGGER trg_test_bir
BEFORE INSERT OR UPDATE OF sid ON test
FOR EACH ROW
BEGIN
IF INSERTING THEN
SELECT seq_test.NEXTVAL INTO :NEW.sid FROM dual;
ELSIF UPDATING THEN
RAISE_APPLICATION_ERROR(-20020, '不允許更新主鍵 SID!');
END IF;
END;
範例 2:行級 - 自動轉大寫
CREATE OR REPLACE TRIGGER trg_emp_job
BEFORE INSERT OR UPDATE OF job ON emp
FOR EACH ROW
BEGIN
:NEW.job := UPPER(:NEW.job);
END;
範例 3:語句級 - 記錄操作類型
CREATE OR REPLACE TRIGGER trg_test_stmt
AFTER INSERT OR UPDATE OR DELETE ON test
BEGIN
IF INSERTING THEN DBMS_OUTPUT.PUT_LINE('INSERT');
ELSIF UPDATING THEN DBMS_OUTPUT.PUT_LINE('UPDATE');
ELSIF DELETING THEN DBMS_OUTPUT.PUT_LINE('DELETE');
END IF;
END;
範例 4:INSTEAD OF - 視圖更新
CREATE OR REPLACE TRIGGER trg_v_emp_iof
INSTEAD OF INSERT OR UPDATE ON v_emp
REFERENCING NEW AS n
FOR EACH ROW
BEGIN
INSERT INTO emp (empno, ename, job) VALUES (:n.empno, :n.ename, :n.job);
END;
範例 5:Schema 級 - 記錄 DDL
CREATE OR REPLACE TRIGGER trg_ddl_log
AFTER DROP ON SCHEMA
BEGIN
INSERT INTO ddl_log (obj_name, obj_type, user_name, op_time)
VALUES (ORA_DICT_OBJ_NAME, ORA_DICT_OBJ_TYPE, USER, SYSDATE);
END;
範例 6:Database 級 - 啟動初始化
CREATE OR REPLACE TRIGGER trg_startup
AFTER STARTUP ON DATABASE
BEGIN
EXECUTE IMMEDIATE 'ALTER SYSTEM SET ...'; -- 動態調整參數
END;
管理命令
| 操作 | 命令 |
| 停用單一觸發器 | ALTER TRIGGER trg_name DISABLE;
| 啟用單一觸發器 | ALTER TRIGGER trg_name ENABLE;
| 停用表上所有觸發器 | ALTER TABLE table_name DISABLE ALL TRIGGERS;
| 啟用表上所有觸發器 | ALTER TABLE table_name ENABLE ALL TRIGGERS;
| 刪除觸發器 | DROP TRIGGER trg_name;
設計黃金法則(必讀)
- 職責單一:一個觸發器只做一件事,避免巨大觸發器難以維護。
- 不重複資料庫內建功能:PK/FK/Not Null/Check 約束交給約束機制,觸發器處理無法用約束表達的複雜邏輯。
- 控制代碼行數:超過 50 行考慮拆分為存儲過程由觸發器呼叫。
- 嚴禁遞迴觸發:觸發器內執行 DML 再觸發同觸發器 → 無限迴圈。若必要,用套件變數旗標控制。
- 觸發器屬於 Schema 物件:表刪除時關聯觸發器自動刪除。
- 同一時機同一張表最多三個觸發器:各一個 INSERT/UPDATE/DELETE(舊版限制,新版可多個但需指定
FOLLOWS 排序)。
- SELECT 無觸發器:唯讀操作不觸發,改用 VPD/FGAC 或 View 控制。
刪除觸發器語法
DROP TRIGGER trigger_name;