mariadb 10.6 创建触发器需用 delimiter 切换结束符,否则因分号提前终止导致语法错误;触发器中 new/old 依事件类型可用,before 可修改 new,after 不可;查触发器用 show triggers 或 information_schema.triggers;删除需先确认存在,因 10.6 不支持 drop trigger if exists。

直接说结论:MariaDB 10.6 创建触发器语法与 MySQL 兼容,但必须用 DELIMITER 切换语句结束符,否则 CREATE TRIGGER 会因分号提前终止而报错。
为什么执行 CREATE TRIGGER 总报语法错误?
这是最常见卡点:MariaDB 默认以分号 ; 为语句结束符,而触发器体(BEGIN ... END)内部有多条 SQL 语句,每条都以 ; 结尾。如果不改结束符,MySQL 解析器会在第一个分号就认为整个 CREATE TRIGGER 语句结束了,导致后续内容被当作独立语句解析,必然报错。
- 错误现象:
ERROR 1064 (42000): You have an error in your SQL syntax,通常指向BEGIN或END附近 - 必须在
CREATE TRIGGER前后显式使用DELIMITER切换结束符(比如改成$$) -
DELIMITER是客户端命令,不是 SQL 语句,不能加引号或写在CREATE TRIGGER内部
BEFORE INSERT 和 AFTER UPDATE 的 NEW/OLD 怎么用?
触发器里访问变更数据全靠 NEW 和 OLD 这两个伪记录——它们不是变量,是只读引用,用法严格绑定事件类型:
-
INSERT触发时只有NEW可用(因为没旧数据),NEW.column_name表示即将插入的值 -
DELETE触发时只有OLD可用(因为没新数据),OLD.column_name表示被删行的原始值 -
UPDATE触发时NEW和OLD都可用,OLD.column_name是更新前值,NEW.column_name是更新后值 -
BEFORE事件中可修改NEW字段(如校验、补默认值),AFTER中不可写NEW/OLD
示例(BEFORE INSERT 自动补时间戳):
DELIMITER $$
CREATE TRIGGER set_created_at_before_insert
BEFORE INSERT ON users
FOR EACH ROW
BEGIN
IF NEW.created_at IS NULL THEN
SET NEW.created_at = NOW();
END IF;
END$$
DELIMITER ;
触发器创建后查不到?用 SHOW TRIGGERS 还是查系统表?
SHOW TRIGGERS 最快,但只显示当前数据库的触发器;如果跨库或需要过滤,得查 information_schema.TRIGGERS:
- 当前库所有触发器:
SHOW TRIGGERS - 指定表的触发器:
SHOW TRIGGERS LIKE 'orders' - 查特定触发器定义:
SELECT TRIGGER_NAME, EVENT_OBJECT_TABLE, ACTION_TIMING, EVENT_MANIPULATION FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = 'mydb' AND EVENT_OBJECT_TABLE = 'logs'; -
information_schema.TRIGGERS里的ACTION_STATEMENT字段存的是原始 SQL,含换行和空格,复制出来可能需手动清理缩进
删除触发器一定要先确认作用范围
DROP TRIGGER 不支持 IF EXISTS 语法(MariaDB 10.6 仍不支持),直接删不存在的触发器会报错:
- 安全做法:先用
SHOW TRIGGERS确认触发器存在,再删;或用DROP TRIGGER IF EXISTS trigger_name—— 但注意:这是 MariaDB 10.10+ 才支持,10.6 不识别该语法,会报错 - 实际兼容写法只能分两步:先查
information_schema.TRIGGERS,再动态拼DROP语句(应用层处理) - 触发器名不带库名,
DROP TRIGGER my_trigger只删当前 USE 的数据库下的同名触发器
真正容易被忽略的是:触发器绑定的是具体表名,如果表被 DROP TABLE,对应触发器会自动消失,但不会通知你——下次重建同名表时,得重新创建触发器,否则逻辑就断了。











