当前位置:首页 > 技术 > 正文内容

MySQL触发器机制详解与实战

访客 技术 2026年7月6日 1

触发器(Trigger)是数据库中一种自动执行的程序单元,当对表执行INSERT、UPDATE或DELETE操作时,数据库引擎会自动调用相应的触发器逻辑。这种机制使得业务规则能够在数据层得到强制执行,无需依赖应用程序代码。

触发器的核心价值

触发器在数据治理中扮演着关键角色,主要优势体现在:

  • 数据完整性保障:在持久化之前执行校验逻辑,拦截不符合规则的数据
  • 操作原子性:触发器执行失败时,整个事务回滚,确保数据一致性
  • 审计追踪:自动记录数据变更历史,满足合规要求
  • 级联计算:跨表同步更新,维护派生数据
  • 指令重写:通过INSTEAD OF触发器替换原始操作逻辑

环境准备

首先建立演示所需的库表结构:

mysql> CREATE DATABASE demo_db;
Query OK, 1 row affected (0.01 sec)

mysql> USE demo_db;
Database changed

mysql> CREATE TABLE staff (
    ->     staff_id INT PRIMARY KEY AUTO_INCREMENT,
    ->     staff_name VARCHAR(30) NOT NULL,
    ->     department VARCHAR(20),
    ->     hire_date DATE
    -> );
Query OK, 0 rows affected (0.04 sec)

mysql> CREATE TABLE staff_archive (
    ->     archive_id INT PRIMARY KEY AUTO_INCREMENT,
    ->     ref_staff_id INT,
    ->     archive_content VARCHAR(100),
    ->     created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    -> );
Query OK, 0 rows affected (0.03 sec)

触发器语法结构

CREATE TRIGGER 触发器名称
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON 目标表名
FOR EACH ROW
[触发器主体:单条SQL或BEGIN...END块]

关键要素说明:

  • 触发时机:BEFORE(操作前)或 AFTER(操作后)
  • 监听事件:INSERT、UPDATE、DELETE三种数据操作
  • 行级触发:FOR EACH ROW表示每行受影响记录都会激活触发器

创建触发器实例

以下示例实现:员工表新增记录后,自动向归档表写入一条日志。

mysql> DELIMITER //

mysql> CREATE TRIGGER trg_staff_insert_log
    -> AFTER INSERT ON staff
    -> FOR EACH ROW
    -> BEGIN
    ->     INSERT INTO staff_archive (ref_staff_id, archive_content)
    ->     VALUES (NEW.staff_id, CONCAT('新员工入职: ', NEW.staff_name));
    -> END //
Query OK, 0 rows affected (0.02 sec)

mysql> DELIMITER ;

执行数据插入验证触发效果:

mysql> INSERT INTO staff (staff_name, department, hire_date)
    -> VALUES ('李明', '研发部', '2024-03-15');
Query OK, 1 row affected (0.01 sec)

mysql> SELECT * FROM staff;
+----------+------------+------------+------------+
| staff_id | staff_name | department | hire_date  |
+----------+------------+------------+------------+
|        1 | 李明       | 研发部     | 2024-03-15 |
+----------+------------+------------+------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM staff_archive;
+------------+--------------+-------------------------+---------------------+
| archive_id | ref_staff_id | archive_content         | created_at          |
+------------+--------------+-------------------------+---------------------+
|          1 |            1 | 新员工入职: 李明         | 2024-03-15 09:30:22 |
+------------+--------------+-------------------------+---------------------+
1 row in set (0.00 sec)

重要提示:触发器不能对自身所在的表进行递归操作,否则会触发错误码1442。

NEW与OLD伪记录

在触发器体内,可通过NEW和OLD引用正在处理的记录:

触发事件可用引用含义说明
INSERTNEW即将插入的新记录值
UPDATENEW、OLDNEW为更新后值,OLD为更新前值
DELETEOLD即将被删除的旧记录值

触发器信息查询

获取特定触发器的定义语句:

mysql> SHOW CREATE TRIGGER trg_staff_insert_log\G
*************************** 1. row ***************************
               Trigger: trg_staff_insert_log
              sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,...
SQL Original Statement: CREATE DEFINER=`root`@`localhost` TRIGGER trg_staff_insert_log
AFTER INSERT ON staff
FOR EACH ROW
BEGIN
    INSERT INTO staff_archive (ref_staff_id, archive_content)
    VALUES (NEW.staff_id, CONCAT('新员工入职: ', NEW.staff_name));
END
  character_set_client: utf8mb4
  collation_connection: utf8mb4_general_ci
    Database Collation: utf8mb4_general_ci
               Created: 2024-03-15 09:28:17.45
1 row in set (0.00 sec)

查看当前库所有触发器清单:

mysql> SHOW TRIGGERS\G
*************************** 1. row ***************************
             Trigger: trg_staff_insert_log
               Event: INSERT
               Table: staff
           Statement: BEGIN
    INSERT INTO staff_archive (ref_staff_id, archive_content)
    VALUES (NEW.staff_id, CONCAT('新员工入职: ', NEW.staff_name));
END
              Timing: AFTER
             Created: 2024-03-15 09:28:17.45
            sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,...
             Definer: root@localhost
character_set_client: utf8mb4
collation_connection: utf8mb4_general_ci
  Database Collation: utf8mb4_general_ci
1 row in set (0.01 sec)

移除触发器

mysql> DROP TRIGGER IF EXISTS trg_staff_insert_log;
Query OK, 0 rows affected (0.01 sec)

mysql> SHOW TRIGGERS;
Empty set (0.00 sec)

复杂场景:BEFORE触发器实现数据校验

利用BEFORE INSERT触发器在数据入库前进行拦截校验:

mysql> DELIMITER //

mysql> CREATE TRIGGER trg_validate_staff
    -> BEFORE INSERT ON staff
    -> FOR EACH ROW
    -> BEGIN
    ->     IF NEW.hire_date > CURDATE() THEN
    ->         SIGNAL SQLSTATE '45000'
    ->         SET MESSAGE_TEXT = '错误:入职日期不能晚于今天';
    ->     END IF;
    ->     IF LENGTH(NEW.staff_name) < 2 THEN
    ->         SIGNAL SQLSTATE '45000'
    ->         SET MESSAGE_TEXT = '错误:员工姓名至少2个字符';
    ->     END IF;
    -> END //
Query OK, 0 rows affected (0.02 sec)

mysql> DELIMITER ;

测试校验逻辑:

mysql> INSERT INTO staff (staff_name, department, hire_date)
    -> VALUES ('王', '市场部', '2025-01-01');
ERROR 1644 (45000): 错误:员工姓名至少2个字符

mysql> INSERT INTO staff (staff_name, department, hire_date)
    -> VALUES ('王强', '市场部', '2025-01-01');
ERROR 1644 (45000): 错误:入职日期不能晚于今天
标签: MySQL

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。