MySQL 触发器(Trigger)使用详解:创建、语法与实战示例

山间有风
山间有风
发布时间:2026-10-16| 6人浏览过
原创

触发器是 MySQL 中与表关联的数据库对象,用于在特定数据操作(INSERT、UPDATE、DELETE)前后自动执行预设逻辑,从而保障数据的完整性与一致性。本文详解其六类触发时机、多语句编写的分隔符处理技巧,并通过用户数据插入自动记录日志的完整示例,展示如何在实际开发中应用。

什么是触发器

触发器是与表紧密关联的数据库对象。当对指定表执行定义好的事件(如插入、更新或删除)且满足特定条件时,MySQL 会自动触发并执行其中定义的 SQL 语句集合。这种机制允许应用在数据库层面确保数据完整性,避免在应用层编写繁杂的业务逻辑。

例如,在【用户表】和【日志表】之间,当向用户表插入新记录时,触发器可自动在日志表中生成一条对应的审计日志。这不仅简化了代码结构,还保证了数据操作的可追溯性。

创建触发器的核心语法

MySQL 支持在 BEFORE(之前)或 AFTER(之后)针对 INSERT、DELETE 和 UPDATE 三种事件创建触发器,共六种组合:

  • BEFORE INSERT, AFTER INSERT
  • BEFORE DELETE, AFTER DELETE
  • BEFORE UPDATE, AFTER UPDATE

基本语法如下:

CREATE TRIGGER trigger_name 
trigger_time trigger_event 
ON tb_name 
FOR EACH ROW 
trigger_stmt;

第1步:处理多语句冲突(DELIMITER)

当触发器仅含单条 SQL 时可直接创建;但如需执行多条语句或使用变量,必须使用 BEGIN ... END 块。由于 MySQL 客户端默认以分号 ; 作为语句结束标志,这会与块内语句的分号冲突。需临时修改结束符:

-- 将结束符临时改为 ||
mysql> DELIMITER ||

-- 创建触发器
mysql> CREATE TRIGGER demo BEFORE DELETE
-> ON users FOR EACH ROW
-> BEGIN
->   INSERT INTO logs VALUES(NOW());
->   INSERT INTO logs VALUES(NOW());
-> END
-> ||

-- 恢复默认结束符
mysql> DELIMITER ;

第2步:声明变量与赋值

在 BEGIN...END 内部可声明局部变量,需注意 DECLARE 必须位于块的顶部:
DECLARE var_name var_type [DEFAULT value];
赋值则使用 SET 命令:
SET var_name = value;

第3步:使用 NEW 与 OLD 伪表

触发器上下文提供两个特殊引用对象,用于访问受影响行的旧值和新值:

  • NEW.column_name:在 INSERT 中表示要插入的值,在 UPDATE 中表示更新后的新值。
  • OLD.column_name:在 DELETE 中表示被删除的原值,在 UPDATE 中表示更新前的旧值。

实战:实现用户插入自动记日志

假设存在以下两张表:users(存储用户信息)和 logs(存储操作日志)。需求是在每次向 users 插入新用户时,自动在 logs 中记录一条日志。

准备环境:建表语句

-- 用户表
CREATE TABLE `users` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL,
  `add_time` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM;

-- 日志表
CREATE TABLE `logs` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `log` varchar(255) DEFAULT NULL COMMENT '日志说明',
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB;

第4步:编写触发器逻辑

创建一个名为 user_log 的触发器,在 users 表插入数据后触发。注意处理中文字符编码及字符串拼接:

DELIMITER $
CREATE TRIGGER user_log AFTER INSERT ON users FOR EACH ROW
BEGIN
    DECLARE s1 VARCHAR(40) CHARACTER SET utf8;
    DECLARE s2 VARCHAR(20) CHARACTER SET utf8;
    
    SET s2 = " is created";
    -- 拼接姓名与固定文本
    SET s1 = CONCAT(NEW.name, s2);
    
    INSERT INTO logs(log) VALUES(s1);
END $
DELIMITER ;

如果使用 Navicat 等图形化工具,通常可直接在设计界面中配置,无需手动输入 DELIMITER。但在命令行或某些客户端(如 MySQL Front)中,需严格遵循分隔符规则。部分旧版客户端可能直接接受 # 作为 END 后的终止符,具体取决于版本:

第5步:验证触发器效果

向 users 表插入一条测试数据:

INSERT INTO users(name, add_time) VALUES('周伯通', NOW());

检查 logs 表,发现日志已自动生成:

查看与管理触发器

SHOW TRIGGERS 语句可以列出所有触发器,但无法通过名称过滤。建议通过系统表 information_schema.triggers 进行精确查询:

-- 查询特定触发器详情
SELECT * FROM information_schema.triggers 
WHERE TRIGGER_NAME = 'user_log';

若需删除触发器,请使用 DROP 语句(注意区分客户端工具差异,部分 GUI 工具可能内置删除按钮,脚本方式通用):

DROP TRIGGER IF EXISTS user_log;

限制与注意事项

在使用触发器时,需注意以下约束以保证稳定性:

  1. 事务限制:触发器内部不能使用 START TRANSACTION、COMMIT 或 ROLLBACK。若触发了错误,对于 InnoDB 等事务表会自动回滚;但对于 MyISAM 等非事务表,错误可能导致数据不一致。
  2. 返回数据限制:触发器不能调用直接向客户端返回数据的存储过程,只能通过参数(INOUT)间接传递数据。
  3. 性能影响:触发器基于“行”触发,数据量较大时(如批量导入),会显著增加锁竞争和 IO 开销,进而拖慢数据写入速度。
  4. 复杂度控制:避免在触发器中编写过于复杂的业务逻辑,以免影响维护和排查难度。

总结

MySQL 触发器是一种强大的自动化机制,适用于审计追踪、级联更新及非标准的数据完整性校验。合理利用 BEFORE/AFTER 时机并结合 NEW/OLD 对象,可实现高效的数据联动。建议在开发初期规划好触发器逻辑,避免过度依赖导致的性能瓶颈。

以上就是 MySQL 触发器 Trigger 使用的详细内容,更多关于 MySQL 触发器最佳实践的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。