首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 觸發器實戰與遞歸陷阱:單表單事件限制、NEW/OLD、循環觸發驗證

     編輯:MySQL 綜合教學

觸發器基礎語法

CREATE TRIGGER trigger_name
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON tbl_name FOR EACH ROW
trigger_body

核心限制

  • 單表單事件唯一:一張表上同一事件(如 AFTER INSERT)只能建一個觸發器
  • 需變更結束符:DELIMITER // ... DELIMITER ;
  • 存取變更行:NEW.col(新值)、OLD.col(舊值)
  • 執行順序:BEFORE → 行操作 → AFTER,任一失敗整體回滾(事務表)

基礎範例:跨表同步

DROP TRIGGER IF EXISTS tr_testTri;
DELIMITER //
CREATE TRIGGER tr_testTri
AFTER INSERT ON testTri
FOR EACH ROW
BEGIN
  INSERT INTO test (Col1, Col2, Col3, Col4) VALUES (1, 2, 3, 5);
END//
DELIMITER ;

-- 驗證
INSERT INTO testTri (Col1, Col2, Col3, Col4) VALUES (1, 2, 3, 4);
-- test 表自動新增一行

遞歸與循環觸發實測(均被阻擋)

場景一:自我遞歸

DROP TRIGGER IF EXISTS tr_testTri;
DELIMITER //
CREATE TRIGGER tr_testTri
AFTER INSERT ON testTri
FOR EACH ROW
BEGIN
  INSERT INTO testTri (Col1, Col2, Col3, Col4) VALUES (1, 2, 3, 5);
END//
DELIMITER ;

-- 測試
INSERT INTO testTri (Col1, Col2, Col3, Col4) VALUES (1, 2, 3, 4);
-- Error 1442: Can't update table 'testtri' in stored function/trigger
-- because it is already used by statement which invoked this stored function/trigger.

場景二:雙表相互觸發

-- testTri 觸發器寫 test
CREATE TRIGGER tr_testTri AFTER INSERT ON testTri ...
  INSERT INTO test ...;

-- test 觸發器寫 testTri
CREATE TRIGGER tr_test AFTER INSERT ON test ...
  INSERT INTO testTri ...;

-- 測試
INSERT INTO testTri ...;
-- Error 1442: 同樣報錯,循環引用被檢測並阻擋

觸發器效能與最佳實踐

版本差異提示

  • MySQL 5.7+:支援同一表同一事件**多個觸發器**(FOLLOWS/PRECEDES 控制順序)
  • 本文測試基於 5.6,單觸發器限制在 8.0 已放寬

總結

  • 觸發器威力大但雙刃劍,**業務核心鏈路禁用**
  • 資料庫層**原生阻擋遞歸與循環觸發**(Error 1442)
  • 適用:審計日誌、冗余表同步、非關鍵統計
  • 調試難:無斷點、錯誤堆棧不明確、事務邊界模糊
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
建議理由
謹慎使用,核心業務避免隱式邏輯、難調試、效能損耗
避免複雜邏輯/外部呼叫阻塞主操作、擴大事務範圍
統計/審計/同步等非核心場景可接受最終一致性、邊緣業務
Row 格式主從:從庫不執行觸發器需主庫寫 binlog,從庫重放 SQL
防止遞歸:業務層控制或標記欄位資料庫層無法可靠防禦