萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL、SQL Server、Oracle 觸發器語法對比與最佳實踐

場景

users 表發生 INSERT/UPDATE/DELETE 時,向 users_log 記錄變更的 id 與操作類型。

MySQL 觸發器


DELIMITER $
CREATE TRIGGER insert_user AFTER INSERT ON users FOR EACH ROW
BEGIN
    INSERT INTO users_log(user_id, action) VALUES(NEW.id, 'insert');
END$
DELIMITER ;

-- UPDATE 觸發器
CREATE TRIGGER update_user AFTER UPDATE ON users FOR EACH ROW
BEGIN
    INSERT INTO users_log(user_id, action) VALUES(NEW.id, 'update');
END;

-- DELETE 觸發器
CREATE TRIGGER delete_user AFTER DELETE ON users FOR EACH ROW
BEGIN
    INSERT INTO users_log(user_id, action) VALUES(OLD.id, 'delete');
END;

關鍵點

  • FOR EACH ROW:行級觸發(MySQL 僅支援行級)
  • NEW:新行(INSERT/UPDATE 可用)
  • OLD:舊行(UPDATE/DELETE 可用)
  • DELIMITER 臨時更改語句結束符,避免 BEGIN...END 內分號衝突

SQL Server 觸發器


-- 單觸發器處理 INSERT/UPDATE/DELETE
CREATE TRIGGER trg_users_audit ON users
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @action VARCHAR(10), @id INT;

    IF EXISTS(SELECT 1 FROM inserted) AND EXISTS(SELECT 1 FROM deleted)
        SET @action = 'update';
    ELSE IF EXISTS(SELECT 1 FROM inserted)
        SET @action = 'insert';
    ELSE
        SET @action = 'delete';

    -- inserted/deleted 為邏輯表(結果集),需游標或集合操作
    INSERT INTO users_log(user_id, action)
    SELECT id, @action FROM inserted
    UNION ALL
    SELECT id, @action FROM deleted WHERE @action='delete';
END;

關鍵差異

  • INSERTED/DELETED 為臨時表(結果集),非單行變量
  • 單觸發器處理多事件,需自行判斷操作類型
  • INSTEAD OF 可攔截並替換原操作(視圖常用)

Oracle 觸發器


CREATE OR REPLACE TRIGGER trg_users_audit
AFTER INSERT OR UPDATE OR DELETE ON users
FOR EACH ROW
DECLARE
    v_action VARCHAR2(10);
BEGIN
    IF INSERTING THEN
        v_action := 'insert';
        INSERT INTO users_log(user_id, action) VALUES(:NEW.id, v_action);
    ELSIF UPDATING THEN
        v_action := 'update';
        INSERT INTO users_log(user_id, action) VALUES(:NEW.id, v_action);
    ELSIF DELETING THEN
        v_action := 'delete';
        INSERT INTO users_log(user_id, action) VALUES(:OLD.id, v_action);
    END IF;
END;
/

關鍵點

  • :NEW/:OLD 為偽列,前綴冒號
  • INSERTING/UPDATING/DELETING 判斷操作類型
  • FOR EACH ROW 行級,無此子句為語句級
  • 以 / 結束創建

三大數據庫觸發器對比總結

維度MySQLSQL ServerOracle
行級觸發僅支援 FOR EACH ROW隱含行級(操作 inserted/deleted 表)FOR EACH ROW 可選
語句級觸發不支援不支援(但可用 INSTEAD OF 模擬)支援(省略 FOR EACH ROW)
新/舊值引用NEW / OLDINSERTED / DELETED 表:NEW / :OLD
多事件合一需建多個觸發器單觸發器 AFTER INSERT,UPDATE,DELETE單觸發器 AFTER INSERT OR UPDATE OR DELETE
事務整合同一事務,回滾連帶觸發器操作同一事務同一事務
性能影響較輕較重(邏輯表掃描)中等

最佳實踐建議

  1. 慎用觸發器:隱式邏輯難調試、擴展困難、鎖競爭放大。優先考慮應用層寫入日志或CDC 工具(Debezium/Canal)異步捕獲 Binlog。
  2. 若必須用:保持邏輯極簡、避免跨表複雜操作、嚴禁觸發器中發送郵件/HTTP 請求
  3. 命名規範:trg_{table}_{event}_{timing} 如 trg_users_ins_aft
  4. 文檔化:數據字典中註明觸發器存在、用途、影響範圍

總結

三大主流數據庫觸發器語法各有特色:MySQL 最簡潔(行級 ONLY)、SQL Server 集合式處理、Oracle 功能最全(行級/語句級、複合事件)。跨庫遷移時需注意語義映射差異。現代架構傾向將業務邏輯上移至應用層,數據庫層專注存儲與一致性,觸發器僅作輔助審計/同步兜底。

copyright © 萬盛學電腦網 all rights reserved