觸發器是資料庫內建的自動化回應機制,無需呼叫、由事件驅動、不接受參數。本文對照 Oracle PL/SQL 與 MySQL 觸發器語法差異,透過「發文自動通知好友」、「論壇貼文同步更新版面統計」兩大經典場景,展示跨平台實作差異。
:NEW/:OLD 存取資料CREATE [OR REPLACE] TRIGGER trigger_name
{BEFORE | AFTER} {INSERT | DELETE | UPDATE [OF column...]}
ON table_name
[FOR EACH ROW]
[WHEN condition]
BEGIN
-- trigger_body
END;
-- 1. Hello World 級:更新 employees 印 ok
CREATE OR REPLACE TRIGGER tri_update
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
DBMS_OUTPUT.PUT_LINE('ok');
END;
-- 2. 插入 emp 印 hello
CREATE OR REPLACE TRIGGER tri_insert
AFTER INSERT ON emp
BEGIN
DBMS_OUTPUT.PUT_LINE('hello');
END;
-- 3. 使用 :OLD/:NEW 顯示薪資變動
CREATE OR REPLACE TRIGGER tri_salary
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
DBMS_OUTPUT.PUT_LINE('更新前:' || :OLD.salary || ' 更新後:' || :NEW.salary);
END;
-- 測試
UPDATE employees SET salary = salary + 1 WHERE department_id = 80;
-- 建立測試表 CREATE TABLE board ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50), articleCount INT ); CREATE TABLE article ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(50), bid INT REFERENCES board(id) ); -- 建立觸發器:文章新增時同步更新版面計數 DELIMITER $$ CREATE TRIGGER insertArticle_trigger AFTER INSERT ON article FOR EACH ROW BEGIN UPDATE board SET articleCount = articleCount + 1 WHERE id = NEW.bid; END $$ DELIMITER ; -- 測試 INSERT INTO board VALUES (NULL, 'test_boardname', 0); INSERT INTO article VALUES (NULL, 'test_title', 1); -- board.articleCount 自動變為 1
| 特性 | Oracle | MySQL |
|---|---|---|
| 分隔符號處理 | 標準 ; 結尾 | 需 DELIMITER $$ 臨時變更 |
| 行級觸發器 | FOR EACH ROW | FOR EACH ROW |
| 新/舊值存取 | :NEW.col / :OLD.col | NEW.col / OLD.col(無冒號) |
| 多陳述式 | BEGIN ... END; | BEGIN ... END(無分號) |
| 條件觸發 | WHEN condition | 觸發器內部 IF 判斷 |
ALTER TABLE ... DISABLE TRIGGER)DBMS_ALERT、AQ 實現非同步通知掌握兩大平台觸發器語法差異,能在異構遷移、混合雲架構中遊刃有餘。