mysql从5.7版本起支持同一表上多个同类触发器(如多个before insert),并可通过follows/precedes控制执行顺序;5.6及更早版本则严格限制每类事件时机仅允许一个触发器。

MySQL 触发器在同一个表上建立多个同类触发器(比如两个 BEFORE INSERT)是**支持的,但仅从 MySQL 5.7 开始**。如果你遇到“不能创建第二个 BEFORE UPDATE”这类报错,大概率是运行环境版本低于 5.7,或误用了旧版语法限制。
MySQL 5.6 及更早:一张表每类事件只允许一个触发器
在 5.6 及之前版本中,每张表对每个「时机 + 事件」组合(如 BEFORE INSERT、AFTER UPDATE)**严格限定只能有一个触发器**。这是硬性限制,不是配置问题。
- 试图重复创建会直接报错:
ERROR 1359 (HY000): Trigger already exists - 即使 DROP 后重建,也不能绕过该限制——系统内部只保留一个 slot
- 典型 workaround 是把所有逻辑塞进一个触发器里,用
IF ... THEN分支处理不同场景,可读性和维护性差
MySQL 5.7+:允许多个同类触发器,且支持执行顺序控制
5.7 引入了触发器排序机制,正式解除单触发器限制。你可以为同一张表定义多个 BEFORE INSERT,它们按创建顺序依次执行;还可显式指定依赖关系:
- 用
FOLLOWS让新触发器排在已有触发器之后:CREATE TRIGGER t2 BEFORE INSERT ON t1 FOLLOWS t1_trigger - 用
PRECEDES让新触发器排在前面:CREATE TRIGGER t0 BEFORE INSERT ON t1 PRECEDES t1_trigger - 注意:
FOLLOWS/PRECEDES只能引用**已存在**的同类型触发器名,否则报错ERROR 3814 (HY000): Unknown trigger 'xxx'
MySQL 8.0:排序功能保留,但权限和 SQL mode 更敏感
8.0 没有取消多触发器能力,反而强化了元数据管理(如新增 CREATED 字段),但实际部署中更容易因环境配置导致“看似不生效”:
-
sql_mode=STRICT_TRANS_TABLES默认启用 → 若某个触发器里给NEW.col = NULL而该列是NOT NULL,整个语句会回滚,看起来像“触发器没跑”,其实是被中断了 - 触发器内调用自定义函数时,8.0 要求显式授予
EXECUTE权限,否则静默失败(5.7 常靠TRIGGER权限隐式覆盖) - 跨版本迁移脚本若硬编码
information_schema.TRIGGERS.CREATED字段,在 5.7 上会直接报错Unknown column 'CREATED'
金仓等兼容数据库:语法支持 ≠ 行为一致
像金仓(Kingbase)这类标榜 MySQL 兼容的数据库,可能解析 CREATE TRIGGER ... AFTER INSERT OR UPDATE 成功,但实际只响应 INSERT —— 复合事件声明形同虚设。
- 不要依赖
OR UPDATE这种写法在非原生 MySQL 环境中正常工作 - 检查触发器是否真实触发,得靠日志表写入、
SELECT查询或SHOW TRIGGERS输出验证,不能只看创建成功与否 - 注释嵌套(如
/* ... /* inner */ ... */)在金仓中可能导致WHEN条件失效,且无错误提示,排查成本极高
真正容易被忽略的是:**触发器数量限制只是表层问题,底层行为漂移(SQL mode、权限、时间函数精度、元数据字段)才是跨版本/跨引擎出问题的主因。** 部署前务必用目标环境账号执行完整业务链路测试,而不是只验证单条 INSERT 是否触发。











