mysql中的触发器(Triggers)的基本概念与作用

来源:这里教程网 时间:2026-02-28 20:38:08 作者:

触发器是什么:数据库层的自动响应机制

触发器是 MySQL 中一种特殊的存储程序,它在特定表上发生

INSERT
UPDATE
DELETE
操作时自动执行,无需应用层调用。它不是函数也不是存储过程,而是一段与表强绑定的、事件驱动的逻辑。

常见错误现象:执行

INSERT
后发现数据“莫名”被改了,或日志表没写入——大概率是触发器在后台生效但未被察觉。

触发器必须关联到具体表,且一个表同一事件(如
BEFORE INSERT
)只能有一个同类型触发器
不能显式调用,也不能传参;它的输入来自当前操作的行(
NEW
/
OLD
不支持事务控制语句(如
START TRANSACTION
),但会参与外层语句的事务

BEFORE 和 AFTER 触发器的关键区别

BEFORE
触发器在语句实际执行前运行,可修改
NEW
行值;
AFTER
在语句成功提交后运行,适合记录日志或同步更新其他表。

典型误用:在

AFTER UPDATE
里试图修改本表数据,会报错
Can't update table 't' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.

BEFORE INSERT
:可用于设置默认值、校验字段(如把空邮箱转为
'unknown@example.com'
BEFORE UPDATE
:适合自动更新
updated_at
字段,或阻止非法状态变更(如
status
'done'
改回
'pending'
AFTER DELETE
:常用于归档删除记录到历史表,或清理关联缓存键

触发器中 NEW 和 OLD 的使用限制

NEW
代表新行数据(
INSERT
UPDATE
可用),
OLD
代表旧行数据(
UPDATE
DELETE
可用)。它们是只读别名,不能赋值给变量再修改——必须直接赋值给
NEW.column_name

容易踩的坑:在

BEFORE INSERT
中写
SET @tmp = NEW.id;
SET NEW.id = @tmp + 1;
是无效的;必须写成
SET NEW.id = NEW.id + 1;

INSERT
:只有
NEW
OLD
NULL
DELETE
:只有
OLD
NEW
NULL
UPDATE
NEW
OLD
都存在,
OLD
是更新前值,
NEW
是待写入值

创建和查看触发器的实操要点

创建触发器需有

TRIGGER
权限,且不能跨库引用表(除非用
db_name.table_name
显式指定)。MySQL 8.0+ 支持多语句触发器,但必须用
BEGIN ... END
包裹,并临时修改分隔符。

DELIMITER $$
CREATE TRIGGER users_update_updated_at
BEFORE UPDATE ON users
FOR EACH ROW
BEGIN
  SET NEW.updated_at = NOW();
END$$
DELIMITER ;

查看已建触发器:

查当前库所有触发器:
SHOW TRIGGERS;
查某张表的触发器:
SHOW TRIGGERS LIKE 'users';
查定义语句:
SELECT TRIGGER_NAME, ACTION_TIMING, EVENT_MANIPULATION, ACTION_STATEMENT FROM information_schema.TRIGGERS WHERE EVENT_OBJECT_TABLE = 'users';

性能影响容易被低估:每个触发器都会增加 DML 延迟,尤其是涉及复杂查询或跨表更新时。高并发写入场景下,应优先考虑应用层处理或异步方案。

相关推荐