觸發器是響應特定表特定事件(INSERT/UPDATE/DELETE)自動執行的程式碼。MySQL 5.x 引入並持續完善,支援行級觸發(FOR EACH ROW)。
CREATE TABLE data (name VARCHAR(255));
CREATE TABLE chars (count INT);
INSERT INTO chars VALUES (0);
CREATE TRIGGER t1 AFTER INSERT ON data
FOR EACH ROW
UPDATE chars SET count = count + CHAR_LENGTH(NEW.name);
mysql> SHOW TRIGGERS\G
Trigger: t1
Event: INSERT
Table: data
Statement: UPDATE chars SET count = count + CHAR_LENGTH(NEW.name)
Timing: AFTER
INSERT INTO data VALUES ('Alice'), ('Bob'), ('Charlie');
SELECT * FROM chars; -- count = 15 (5+3+7)
CREATE TABLE audit_log (
id INT AUTO_INCREMENT PRIMARY KEY,
tbl VARCHAR(64), op ENUM('I','U','D'),
old_json JSON, new_json JSON,
usr VARCHAR(64), ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TRIGGER audit_ins AFTER INSERT ON users
FOR EACH ROW
INSERT INTO audit_log (tbl,op,new_json,usr) VALUES ('users','I',
JSON_OBJECT('id',NEW.id,'name',NEW.name), CURRENT_USER());
CREATE TRIGGER audit_upd AFTER UPDATE ON users
FOR EACH ROW
INSERT INTO audit_log (tbl,op,old_json,new_json,usr) VALUES ('users','U',
JSON_OBJECT('id',OLD.id,'name',OLD.name),
JSON_OBJECT('id',NEW.id,'name',NEW.name), CURRENT_USER());
CREATE TRIGGER calc_order_total BEFORE INSERT ON orders
FOR EACH ROW
SET NEW.amount = NEW.qty * NEW.unit_price * (1 - COALESCE(NEW.discount,0));
CREATE TRIGGER sync_email AFTER UPDATE ON users
FOR EACH ROW
IF NEW.email <> OLD.email THEN
UPDATE profiles SET email=NEW.email WHERE user_id=NEW.id;
END IF;
CREATE TRIGGER check_stock BEFORE INSERT ON order_items
FOR EACH ROW
BEGIN
DECLARE stock INT;
SELECT quantity INTO stock FROM products WHERE id=NEW.product_id;
IF stock < NEW.qty THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='庫存不足';
END IF;
END;
| 操作 | 指令 |
|---|---|
| 查看所有 | SHOW TRIGGERS; |
| 查看特定庫 | SHOW TRIGGERS FROM dbname; |
| 查看定義 | SHOW CREATE TRIGGER name; |
| 刪除 | DROP TRIGGER [IF EXISTS] name; |
FOR EACH ROW),不支援語句級COMMIT/ROLLBACK/LOCK TABLESSIGNAL 拋出自定義錯誤