觸發器是針對表的 INSERT/UPDATE/DELETE 事件,在 BEFORE/AFTER 時機自動執行的存儲程序。本文系統講解語法、四大要素、NEW/OLD 伪表用法,並以「商品-訂單」經典模型實戰四大高頻場景。
CREATE TRIGGER trigger_name
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON table_name
FOR EACH ROW
BEGIN
-- SQL 語句 (可用 NEW.col / OLD.col)
END;
DROP TRIGGER [schema.]trigger_name;
SHOW TRIGGERS;
| 要素 | 說明 |
|---|---|
| 監視地點 | 永久表 (不支援視圖/臨時表) |
| 監視事件 | INSERT / UPDATE / DELETE |
| 觸發時機 | BEFORE (可修改 NEW 值) / AFTER (不可修改) |
| 執行程序 | 單條或多條 SQL (BEGIN...END) |
FOLLOWS/PRECEDES)。COMMIT/ROLLBACK);MyISAM 下觸發器失敗不回滾主表操作,InnoDB 下觸發器與主操作在同一事務 (原子)。| 事件 | OLD | NEW |
|---|---|---|
| INSERT | 無 | 新插入行 (可修改 BEFORE 中) |
| UPDATE | 修改前舊值 | 修改後新值 (可修改 BEFORE 中) |
| DELETE | 被刪除行 | 無 |
DELIMITER $$
CREATE TRIGGER trg_order_after_insert
AFTER INSERT ON orders
FOR EACH ROW
BEGIN
UPDATE goods SET num = num - NEW.much WHERE id = NEW.gid;
END $$
DELIMITER ;
CREATE TRIGGER trg_order_after_delete
AFTER DELETE ON orders
FOR EACH ROW
BEGIN
UPDATE goods SET num = num + OLD.much WHERE id = OLD.gid;
END;
CREATE TRIGGER trg_order_after_update
AFTER UPDATE ON orders
FOR EACH ROW
BEGIN
UPDATE goods SET num = num + OLD.much - NEW.much WHERE id = OLD.gid;
END;
CREATE TRIGGER trg_goods_low_stock
BEFORE UPDATE ON goods
FOR EACH ROW
BEGIN
IF NEW.num < 10 AND OLD.num >= 10 THEN
INSERT INTO warn_log (goods_id, msg, created_at)
VALUES (NEW.id, CONCAT('商品 ', NEW.name, ' 庫存不足 10'), NOW());
END IF;
END;
CREATE TABLE audit_log (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
table_name VARCHAR(64), operation ENUM('INSERT','UPDATE','DELETE'),
old_data JSON, new_data JSON,
operator VARCHAR(64), op_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 以 orders 表為例
CREATE TRIGGER trg_orders_audit
AFTER INSERT ON orders FOR EACH ROW
INSERT INTO audit_log (table_name, operation, new_data, operator)
VALUES ('orders', 'INSERT', JSON_OBJECT('id', NEW.id, 'gid', NEW.gid, 'much', NEW.much), CURRENT_USER());
CREATE TRIGGER trg_orders_audit_upd
AFTER UPDATE ON orders FOR EACH ROW
INSERT INTO audit_log (table_name, operation, old_data, new_data, operator)
VALUES ('orders', 'UPDATE',
JSON_OBJECT('id', OLD.id, 'gid', OLD.gid, 'much', OLD.much),
JSON_OBJECT('id', NEW.id, 'gid', NEW.gid, 'much', NEW.much),
CURRENT_USER());
CREATE TRIGGER trg_orders_audit_del
AFTER DELETE ON orders FOR EACH ROW
INSERT INTO audit_log (table_name, operation, old_data, operator)
VALUES ('orders', 'DELETE', JSON_OBJECT('id', OLD.id, 'gid', OLD.gid, 'much', OLD.much), CURRENT_USER());
SHOW TRIGGERS,清理廢棄觸發器。結語: 觸發器是「資料庫層面的 AOP」,用得好能消除重複代碼、保證數據一致性;用不好會變成「隱形效能殺手」與「除錯噩夢」。**克制使用、職責單一、充分測試** 是鐵律。