首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 5.0 觸發器完整參考:語法、權限、NEW/OLD 操作與實戰範例

     編輯:MySQL 資料庫相關知識

前言

MySQL 5.0 引入觸發器支援,滿足 ANSI SQL 標準並回應社群長期需求。觸發器可在資料異動(INSERT/UPDATE/DELETE)前後自動執行定義邏輯,常用於資料驗證、審計日誌、衍生欄位維護等場景。本文系統整理觸發器語法規則、權限模型、NEW/OLD 過渡變數操作、建立與測試範例、CHECK 約束替代方案、已知 Bug 與版本升級注意事項,為開發與 DBA 提供完整參考手冊。

一、觸發器語法完整結構

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

六大語法要素解析

要素關鍵字說明
命名最長 64 字元,建議採用 表名_時機_事件 慣例(如 orders_bu = orders 表 BEFORE UPDATE)
時機BEFORE / AFTER事件發生前或後執行;BEFORE 可修改 NEW 值,AFTER 僅能讀取
事件INSERT / UPDATE / DELETE觸發的 DML 操作類型
所屬表ON 觸發器綁定單一表,同一表同一事件同一時機僅能建立一個觸發器
粒度FOR EACH ROW逐列觸發(行級觸發),MySQL 僅支援行級,不支援陳述式級
執行體合法 SQL 陳述式,可含複合陳述式 BEGIN...END、流程控制、變數宣告、例外處理

二、權限模型

  • 建立觸發器需 CREATE TRIGGER 權限(MySQL 5.1.6+ 獨立權限;舊版需 SUPER 權限)
  • Root 帳號預設具備
  • 授權範例:GRANT CREATE TRIGGER ON db.tbl TO 'dev'@'%';
  • 移除授權:REVOKE CREATE TRIGGER ON db.tbl FROM 'dev'@'%';

三、NEW / OLD 過渡變數詳細規則

觸發器主體中引用表欄位必須透過 NEW.col_name 或 OLD.col_name,避免欄位名稱衝突:

事件可用變數說明
INSERTNEW新列資料;可在 BEFORE 中修改
UPDATEOLD, NEW舊值與新值;BEFORE 可修改 NEW
DELETEOLD被刪除的舊列資料

範例:記錄 UPDATE 變更前後值

CREATE TRIGGER t21_au
BEFORE UPDATE ON t22
FOR EACH ROW
BEGIN
  SET @old_val = OLD.s1;
  SET @new_val = NEW.s1;
END;//

若 s1 原值 55,執行 UPDATE t21 SET s1 = s1 + 1 後,@old_val=55、@new_val=56。

四、完整建立與測試範例

1. 建立表與 BEFORE INSERT 觸發器

DELIMITER //
CREATE TABLE t22 (s1 INT)//
CREATE TRIGGER t22_bi
BEFORE INSERT ON t22
FOR EACH ROW
BEGIN
  SET @x = 'Trigger was activated!';
  SET NEW.s1 = 55;  -- 強制覆寫插入值
END;//
DELIMITER ;

2. 測試插入與驗證

INSERT INTO t22 VALUES (1);
SELECT @x, t22.* FROM t22;
-- 結果:
-- @x: 'Trigger was activated!'
-- s1: 55 (非原始插入的 1)

五、實戰應用:以觸發器實現 CHECK 約束

MySQL 不支援標準 SQL CHECK 約束,可用觸發器模擬:

CREATE TABLE t25 (
  s1 INT,
  s2 CHAR(5),
  PRIMARY KEY (s1)
) ENGINE=INNODB//

CREATE TRIGGER t25_bi
BEFORE INSERT ON t25
FOR EACH ROW
BEGIN
  IF LEFT(NEW.s2,1) <> 'A' THEN
    SET NEW.s1 = 0;  -- 觸發主鍵衝突或業務邏輯攔截
  END IF;
END;//

CREATE TRIGGER t25_bu
BEFORE UPDATE ON t25
FOR EACH ROW
BEGIN
  IF LEFT(NEW.s2,1) <> 'A' THEN
    SET NEW.s1 = 0;
  END IF;
END;//

關鍵點:

  • 僅用 BEFORE 觸發器,因 AFTER 無法修改 NEW
  • 透過設定違規值導致錯誤(如主鍵重複、外鍵失效)達到攔截效果
  • 需先插入一筆「引導資料」避免空表狀態下邏輯異常

六、觸發器限制與函數相同的禁止操作

觸發器主體不能執行以下操作(同函數限制):

ALTER, CACHE INDEX, CALL, COMMIT, CREATE, DELETE,
DROP, FLUSH PRIVILEGES, GRANT, INSERT, KILL,
LOCK, OPTIMIZE, REPAIR, REPLACE, REVOKE,
ROLLBACK, SAVEPOINT, SELECT FROM table,
SET system variable, SET TRANSACTION,
SHOW, START TRANSACTION, TRUNCATE, UPDATE

例外:SELECT 可用於變數賦值(SELECT ... INTO @var),但不可直接查表返回結果集。

七、已知 Bug 與規避方案 (MySQL 5.0.3 測試版基準)

Bug 編號現象規避方案
#5859DROP TABLE 不會自動刪除關聯觸發器手動先 DROP TRIGGER 再 DROP TABLE
#5892觸發器命名空間錯誤,刪除需加表名前綴使用 DROP TRIGGER tbl_name.trigger_name
#5894對有觸發器的表執行 ALTER TABLE 可能導致資料損毀避免在有觸發器的表上執行 ALTER,待修復版本釋出

八、常見誤區澄清

  1. 觸發器 ≠ 儲存程序:舊版手冊誤稱觸發器為儲存程序,兩者為獨立物件
  2. 不支援跨表觸發:舊文檔稱可從其他表刪除/觸發,MySQL 未實現
  3. 不影響查詢效能:觸發器僅在 DML 時執行,對 SELECT 無任何負面影響

九、升級與遷移建議

  • MySQL 5.7/8.0 已修復上述 Bug,支援 DROP TRIGGER IF EXISTS、INFORMATION_SCHEMA.TRIGGERS 標準查詢
  • 遷移時檢查 SHOW TRIGGERS 匯出定義,注意 DEFINER 權限映射
  • 新版可用 CREATE OR REPLACE TRIGGER 簡化部署腳本

結語

觸發器是資料庫層面業務邏輯封裝的利器,善用可集中資料完整性規則、減少應用層重複驗證碼。但需謹記:觸發器隱藏邏輯增加除錯難度、影響寫入效能、複雜觸發器鏈易造成死鎖。建立嚴格的命名規範、文件化所有觸發器用途、在測試環境完整驗證後再部署生產,並隨版本升級及時修復已知缺陷。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved