觸發器語法
CREATE TRIGGER
{ BEFORE | AFTER }
{ INSERT | UPDATE | DELETE }
ON
FOR EACH ROW
命名規範建議
__,例如:
orders_bu_ins (Before Update Insert)
users_au_upd (After Update)
logs_bd_del (Before Delete)
名稱長度 ≤ 64 字元,建議小寫 + 底線。
觸發時機與事件對照
| 時機 | 事件 | 典型用途 | NEW/OLD 可用性 |
| BEFORE | INSERT | 資料驗證、自動填充欄位、轉換格式 | NEW 可寫 |
| BEFORE | UPDATE | 防止非法修改、記錄變更前值 | OLD 唯讀、NEW 可寫 |
| BEFORE | DELETE | 檢查關聯完整性、軟刪除標記 | OLD 唯讀 |
| AFTER | INSERT | 同步冗餘表、發送通知、寫入稽核日誌 | NEW 唯讀 |
| AFTER | UPDATE | 更新統計表、觸發工作流 | OLD/NEW 唯讀 |
| AFTER | DELETE | 清理關聯資料、歸檔 | OLD 唯讀 |
NEW / OLD 擬似列使用範例
-- BEFORE INSERT:自動設定建立時間、UUID
CREATE TRIGGER users_bi_ins BEFORE INSERT ON users
FOR EACH ROW
BEGIN
SET NEW.created_at = NOW();
SET NEW.uuid = UUID();
IF NEW.email NOT LIKE '%@%' THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Invalid email';
END IF;
END;
-- AFTER UPDATE:記錄變更歷程
CREATE TRIGGER orders_au_upd AFTER UPDATE ON orders
FOR EACH ROW
BEGIN
IF OLD.status <> NEW.status THEN
INSERT INTO order_status_log (order_id, old_status, new_status, changed_at)
VALUES (OLD.id, OLD.status, NEW.status, NOW());
END IF;
END;
觸發器內限制 (同函數/預存程序)
- 不可執行:DDL (
CREATE/ALTER/DROP)、TCL (COMMIT/ROLLBACK)、鎖表、備份/還原、權限變更、SELECT ... FROM table (但可用 SELECT ... INTO 變數)、動態 SQL (PREPARE)。
- 可執行:DML (
INSERT/UPDATE/DELETE)、流程控制 (IF/CASE/LOOP)、變數宣告 (DECLARE/SET)、條件/異常處理 (DECLARE HANDLER)。
管理指令
SHOW TRIGGERS;
SHOW CREATE TRIGGER trigger_name;
DROP TRIGGER [schema.]trigger_name;
遷移與除錯提醒
- MySQL 5.0 觸發器支援尚屬早期,**生產環境嚴禁用於核心業務**,建議升級至 5.7/8.0 並充分測試。
- 除錯:
SELECT * FROM information_schema.TRIGGERS 檢查定義;錯誤日誌查看 SIGNAL 拋出訊息。
- 效能:觸發器同步執行,複雜邏輯會增加寫入延遲,評估是否改為應用層非同步處理。
- 上一篇文章: MySQL 入門快速上手:Windows 安裝、服務啟動、Root 密碼設定與基礎連線測試
- 下一篇文章: MySQL 隨機抽樣查詢優化:ORDER BY RAND() 效能陷阱與 JOIN 子查詢高效替代方案
Copyright ©
程式碼之家 All Rights Reserved