MySQL触发器是依附于表的一种数据库对象,当表上发生INSERT、UPDATE、DELETE等指定事件时,触发器会自动执行预设的逻辑,不需要手动调用,常用于实现数据校验、操作日志、级联更新等业务需求。

MySQL触发器的基本语法
创建触发器的标准语法如下:
-- 创建触发器语法
CREATE TRIGGER 触发器名称
触发时机 触发事件
ON 表名
FOR EACH ROW
BEGIN
-- 触发器执行的逻辑语句
END;
语法中各部分的含义如下:
- 触发器名称:自定义的唯一标识,建议命名时包含表名、触发事件、触发时机的信息,方便后续维护
- 触发时机:可选值为BEFORE或AFTER,BEFORE表示在触发事件执行前触发,AFTER表示在触发事件执行后触发
- 触发事件:可选值为INSERT、UPDATE、DELETE,对应表的数据插入、更新、删除操作
- 表名:触发器依附的表,触发器只能作用于指定的一张表
- FOR EACH ROW:表示触发器是行级触发器,每影响一行数据就会执行一次触发器逻辑
OLD和NEW关键字的使用
触发器中可以通过OLD和NEW关键字引用受影响的行数据,不同触发事件下的可用性不同:
| 触发事件 | NEW关键字 | OLD关键字 |
|---|---|---|
| INSERT | 可用,代表新插入的行数据 | 不可用 |
| UPDATE | 可用,代表更新后的行数据 | 可用,代表更新前的行数据 |
| DELETE | 不可用 | 可用,代表被删除的行数据 |
引用具体字段时格式为NEW.字段名或OLD.字段名,例如NEW.user_id表示新行的user_id字段值。
触发器使用示例
示例1:INSERT后自动记录操作日志
假设有两张表,user表存储用户信息,user_log表存储用户操作日志,需求是每次新增用户后,自动往user_log表插入一条新增日志。
先创建两张表:
-- 创建用户表
CREATE TABLE user (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
age INT,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 创建用户操作日志表
CREATE TABLE user_log (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
action VARCHAR(20),
action_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
创建AFTER INSERT触发器:
-- 切换分隔符,避免和触发器内的分号冲突
DELIMITER //
CREATE TRIGGER tr_user_after_insert
AFTER INSERT
ON user
FOR EACH ROW
BEGIN
-- 插入新增日志,NEW.id就是新插入用户的id
INSERT INTO user_log (user_id, action) VALUES (NEW.id, 'insert');
END //
-- 恢复默认分隔符
DELIMITER ;
测试触发器效果:
-- 插入用户数据
INSERT INTO user (username, age) VALUES ('张三', 25);
-- 查询日志表,会自动生成一条记录
SELECT * FROM user_log;
示例2:UPDATE前校验数据合法性
需求是更新user表的age字段时,不允许将年龄修改为小于18的值,如果修改的值小于18则自动调整为18。
创建BEFORE UPDATE触发器:
DELIMITER //
CREATE TRIGGER tr_user_before_update
BEFORE UPDATE
ON user
FOR EACH ROW
BEGIN
-- 判断新年龄是否小于18
IF NEW.age < 18 THEN
-- 调整为18
SET NEW.age = 18;
END IF;
END //
DELIMITER ;
测试触发器效果:
-- 尝试将张三的年龄更新为15 UPDATE user SET age = 15 WHERE username = '张三'; -- 查询用户表,年龄会被自动调整为18 SELECT username, age FROM user WHERE username = '张三';
示例3:DELETE后级联删除关联数据
需求是删除user表的用户时,自动删除user_log表中对应该用户的所有日志。
创建AFTER DELETE触发器:
DELIMITER //
CREATE TRIGGER tr_user_after_delete
AFTER DELETE
ON user
FOR EACH ROW
BEGIN
-- 删除关联日志,OLD.id是被删除用户的id
DELETE FROM user_log WHERE user_id = OLD.id;
END //
DELIMITER ;
测试触发器效果:
-- 删除张三用户 DELETE FROM user WHERE username = '张三'; -- 查询日志表,张三的日志会被自动删除 SELECT * FROM user_log;
触发器的查看和删除
查看当前数据库的所有触发器:
-- 查看所有触发器 SHOW TRIGGERS; -- 查看指定触发器的定义 SHOW CREATE TRIGGER tr_user_after_insert;
删除触发器的语法:
DROP TRIGGER 触发器名称;
使用触发器的注意事项
- 触发器不能返回结果集,只能执行数据操作逻辑
- 同一个表同一个触发时机同一个触发事件只能创建一个触发器,例如user表已经存在AFTER INSERT触发器,就不能再创建同类型的触发器
- 触发器内不能操作临时表,也不能调用存储过程返回结果
- 触发器逻辑过于复杂会影响数据操作的性能,建议只在轻量逻辑场景下使用
- 修改表结构时需要注意触发器是否会受影响,例如删除字段后触发器中引用该字段的逻辑会报错