触发器是MySQL数据库中与表事件关联的存储程序,当表执行INSERT、UPDATE、DELETE操作时,触发器会自动触发执行预设的逻辑,不需要手动调用。它可以帮助开发者在不修改业务代码的前提下,实现数据的自动校验、操作日志记录等功能。

触发器的核心特性
触发器有以下几个核心特性需要开发者了解:
- 自动触发:不需要手动调用,当关联的表发生指定操作时自动执行
- 事件绑定:只能绑定INSERT、UPDATE、DELETE三种表操作事件
- 触发时机:支持操作执行前(BEFORE)和操作执行后(AFTER)两种触发时机
- 行级触发:默认是FOR EACH ROW,即每影响一行数据就触发一次,也可以通过参数调整全局触发行为
触发器的创建语法
创建触发器需要使用CREATE TRIGGER语句,基础语法如下:
-- 创建触发器基础语法
CREATE TRIGGER trigger_name
trigger_time trigger_event
ON table_name FOR EACH ROW
BEGIN
-- 触发器执行的逻辑语句
END;
语法参数说明:
- trigger_name:触发器的名称,同一个数据库内名称唯一
- trigger_time:触发时机,可选值为BEFORE或AFTER
- trigger_event:触发事件,可选值为INSERT、UPDATE、DELETE
- table_name:触发器绑定的表名
- BEGIN...END:包裹触发器执行的逻辑语句,如果只有一条语句可以省略
触发器中的新旧数据引用
在触发器的逻辑中,我们可以通过NEW和OLD关键字引用操作前后的数据:
| 关键字 | INSERT事件 | UPDATE事件 | DELETE事件 |
|---|---|---|---|
| NEW | 可引用插入的新数据 | 可引用更新后的新数据 | 不可用 |
| OLD | 不可用 | 可引用更新前的旧数据 | 可引用删除的旧数据 |
触发器使用示例
示例1:插入数据前校验
我们创建一个用户表,要求用户年龄不能小于18岁,插入数据前通过触发器校验:
-- 创建用户表
CREATE TABLE user (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
age INT NOT NULL
);
-- 创建插入前校验的触发器
DELIMITER //
CREATE TRIGGER check_user_age
BEFORE INSERT ON user FOR EACH ROW
BEGIN
-- 如果插入的年龄小于18,抛出错误
IF NEW.age < 18 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '用户年龄不能小于18岁';
END IF;
END //
DELIMITER ;
-- 测试插入合法数据
INSERT INTO user (name, age) VALUES ('张三', 20); -- 插入成功
-- 测试插入非法数据
INSERT INTO user (name, age) VALUES ('李四', 16); -- 触发错误,插入失败
示例2:操作后记录审计日志
创建一个操作日志表,当用户表发生UPDATE或DELETE操作时,自动记录操作日志:
-- 创建操作日志表
CREATE TABLE user_log (
log_id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
operate_type VARCHAR(10) NOT NULL,
operate_time DATETIME NOT NULL,
old_age INT,
new_age INT
);
-- 创建更新后记录日志的触发器
DELIMITER //
CREATE TRIGGER log_user_update
AFTER UPDATE ON user FOR EACH ROW
BEGIN
INSERT INTO user_log (user_id, operate_type, operate_time, old_age, new_age)
VALUES (OLD.id, 'UPDATE', NOW(), OLD.age, NEW.age);
END //
DELIMITER ;
-- 创建删除后记录日志的触发器
DELIMITER //
CREATE TRIGGER log_user_delete
AFTER DELETE ON user FOR EACH ROW
BEGIN
INSERT INTO user_log (user_id, operate_type, operate_time, old_age, new_age)
VALUES (OLD.id, 'DELETE', NOW(), OLD.age, NULL);
END //
DELIMITER ;
-- 测试更新操作
UPDATE user SET age = 22 WHERE name = '张三'; -- 会向user_log表插入一条更新日志
-- 测试删除操作
DELETE FROM user WHERE name = '张三'; -- 会向user_log表插入一条删除日志
触发器的查看与删除
如果需要查看已有的触发器,可以使用以下语句:
-- 查看当前数据库所有触发器 SHOW TRIGGERS; -- 查看指定触发器的定义 SHOW CREATE TRIGGER check_user_age;
如果不再需要某个触发器,可以使用DROP语句删除:
-- 删除指定触发器 DROP TRIGGER IF EXISTS check_user_age;
使用触发器的注意事项
- 触发器执行效率会影响原操作的性能,复杂的触发器逻辑可能导致原操作变慢,不建议在触发器中写复杂的业务逻辑
- 触发器不能直接返回结果给客户端,只能通过修改数据或抛出错误的方式影响操作结果
- 同一个表同一个事件同一个触发时机只能创建一个触发器,比如已经存在BEFORE INSERT的触发器,不能再创建同类型的触发器
- 触发器中不能执行动态SQL语句,也不能调用存储过程返回结果集