語法結構
CREATE TRIGGER trigger_name
trigger_time trigger_event
ON tbl_name
FOR EACH ROW
trigger_stmt
關鍵字解析
| 元素 | 選項 | 說明 |
| trigger_time | BEFORE / AFTER | 相對觸發語句執行前/後 |
| trigger_event | INSERT / UPDATE / DELETE | 激活操作類型 (含 LOAD DATA、REPLACE) |
| tbl_name | 永久表 | 不可關聯 TEMPORARY TABLE / VIEW |
| FOR EACH ROW | 強制 | 逐列觸發 (MySQL 僅支援行級) |
| trigger_stmt | 單句 / BEGIN...END | 多句需用複合語句 |
權限要求
- 建立需
TRIGGER 權限 (5.1.6 前需 SUPER)。
- 執行時需
SELECT (讀 OLD/NEW) 與 UPDATE (寫 NEW) 權限。
OLD / NEW 伪列存取規則
| 事件 | OLD | NEW |
| INSERT | 不可用 | 新列值 (可寫,BEFORE 可修改) |
| UPDATE | 舊列值 (唯讀) | 新列值 (可寫,BEFORE 可修改) |
| DELETE | 舊列值 (唯讀) | 不可用 |
實戰範例:發文時自動累加分類計數
CREATE TRIGGER trg_blogs_after_insert
AFTER INSERT ON blogs
FOR EACH ROW
BEGIN
UPDATE blog_category
SET article_count = article_count + 1
WHERE cid = NEW.category_id;
END;
複雜邏輯:INSERT ... ON DUPLICATE KEY UPDATE 觸發順序
-- 若無重複鍵
BEFORE INSERT → AFTER INSERT
-- 若有重複鍵
BEFORE INSERT → BEFORE UPDATE → AFTER UPDATE → AFTER INSERT
限制與注意事項
- 同一表、同一時間、同一事件**只能有一個觸發器** (5.7+ 已放寬,可多個並指定
FOLLOWS/PRECEDES)。
- 不支援外鍵級聯動作觸發 (8.0 仍未完全支援)。
- 觸發器內不可使用
CALL 預存程序 (可用函數)、不可啟動事務、不可鎖表。
- 避免在觸發器中做重 I/O 操作,影響寫入延遲。
管理指令
SHOW TRIGGERS;
SHOW CREATE TRIGGER trg_name;
DROP TRIGGER [IF EXISTS] [schema.]trg_name;
除錯技巧
- 在觸發器中寫入審計表:
INSERT INTO trigger_log (msg) VALUES (CONCAT('NEW.id=', NEW.id));
- 使用
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '...'; 拋出自訂錯誤 (5.5+)。
觸發器是資料庫層面的「事件驅動」,善用可解耦應用邏輯,濫用則成效能殺手,請謹慎評估每個寫入路徑的額外開銷。