触发器是数据库中自动执行的存储程序,当关联表发生INSERT、UPDATE或DELETE操作时触发。
本文介绍了触发器的核心特点(自动触发、事件驱动)、语法结构(CREATE TRIGGER语句)以及BEFORE/AFTER两种触发时机的应用场景。
通过一个审计日志示例(在employees_test表插入数据后自动记录到audit表),演示了AFTER INSERT触发器的实现方法,包括使用NEW伪记录获取新数据。
文章还列举了触发器的常见应用场景(数据验证、同步、汇总等)及使用注意事项(性能影响、调试难度等)。
触发器(Trigger)
触发器是数据库中一种特殊的存储程序,它会在指定的表上发生特定事件(如INSERT、UPDATE、DELETE)时自动执行。
核心特点
| 特点 | 说明 |
|---|---|
| 自动触发 | 不需要手动调用,满足条件时自动执行 |
| 绑定表 | 必须关联到某个具体的数据表 |
| 事件驱动 | 由INSERT、UPDATE、DELETE操作触发 |
| 时机可选 | 可在事件之前(BEFORE)或之后(AFTER)执行 |
语法结构
sql
CREATE TRIGGER 触发器名称 {BEFORE | AFTER} {INSERT | UPDATE | DELETE} ON 表名 FOR EACH ROW BEGIN -- 要执行的SQL语句 END;触发时机说明
| 时机 | 说明 | 常见用途 |
|---|---|---|
BEFORE | 在数据修改之前执行 | 数据验证、数据清洗、默认值填充 |
AFTER | 在数据修改之后执行 | 日志记录、数据同步、审计追踪 |
可访问的伪记录
在触发器内部可以访问特殊的伪记录:
| 伪记录 | 说明 | 可用操作 |
|---|---|---|
NEW | 操作后的新数据 | INSERT、UPDATE |
OLD | 操作前的旧数据 | UPDATE、DELETE |
简单示例
sql
-- 创建触发器:在插入员工后自动记录审计日志 CREATE TRIGGER audit_log AFTER INSERT ON employees_test FOR EACH ROW INSERT INTO audit (EMP_no, NAME) VALUES (NEW.ID, NEW.NAME);
执行过程:
用户执行
INSERT INTO employees_test ...数据插入成功后,触发器自动向
audit表插入记录用户无需单独操作
audit表
常见应用场景
📝审计日志:记录谁在什么时间修改了什么数据
🔒数据验证:在插入/更新前检查数据合法性
🔄数据同步:主表变化时自动更新关联表
📊数据汇总:增删改时自动更新统计表
🔗级联操作:删除主表记录时自动删除子表关联记录
优点与注意事项
优点
自动化业务逻辑,减少应用程序代码
保证数据一致性和完整性
强制实施数据规则
注意事项
过度使用会影响性能
调试相对困难(自动执行,不易追踪)
嵌套触发器可能导致复杂度爆炸
某些在线评测系统可能限制触发器语法
触发器和存储过程对比
| 对比维度 | 触发器 (Trigger) | 存储过程 (Stored Procedure) |
|---|---|---|
| 调用方式 | 自动触发(由DML事件触发) | 手动调用(使用CALL命令) |
| 参数 | 不支持参数 | 支持输入、输出参数 |
| 返回值 | 不返回值 | 可返回值或结果集 |
| 事务处理 | 与触发事务绑定 | 可独立控制 |
| 主要场景 | 审计、数据验证、级联更新 | 复杂业务逻辑封装 |
| 调试难度 | 较难调试 | 相对容易调试 |
| 性能影响 | 隐式执行,难以控制 | 显式调用,可优化 |
触发器在 MySQL 和 Oracle 中的异同
| 对比维度 | MySQL 触发器 | Oracle 触发器 |
|---|---|---|
| 语法结构 | FOR EACH ROW必须,不支持FOR EACH STATEMENT | 支持FOR EACH ROW和FOR EACH STATEMENT |
| 触发时机 | BEFORE/AFTER | BEFORE/AFTER/INSTEAD OF(视图) |
| 触发器内事务 | 不能包含事务语句(COMMIT/ROLLBACK) | 可以包含事务语句(需谨慎使用) |
| 错误处理 | 使用SIGNAL/RESIGNAL | 使用RAISE_APPLICATION_ERROR |
| 新旧数据访问 | NEW/OLD(不加冒号) | :NEW/:OLD(需加冒号) |
| 行级限制 | 每个表每个事件最多6个触发器 | 无明确数量限制 |
| 存储过程调用 | 可调用 | 可调用 |
触发器示例
题目描述
构造一个触发器audit_log,在向employees_test表中插入一条数据的时候,触发插入相关的数据到audit中。
CREATE TABLE employees_test( ID INT PRIMARY KEY NOT NULL, NAME TEXT NOT NULL, AGE INT NOT NULL, ADDRESS CHAR(50), SALARY REAL ); CREATE TABLE audit( EMP_no INT NOT NULL, NAME TEXT NOT NULL );后台会往employees_test插入一条数据:
INSERT INTO employees_test (ID,NAME,AGE,ADDRESS,SALARY)VALUES (1, 'Paul', 32, 'California', 20000.00 );然后从audit里面使用查询语句:
select * from audit;
按照题目要求,构造一个INSERT触发器audit_log,实现在employees_test插入数据后,把对应的ID和NAME写入audit表中。
sql
DROP TRIGGER IF EXISTS audit_log; DELIMITER $$ CREATE TRIGGER audit_log AFTER INSERT ON employees_test FOR EACH ROW BEGIN INSERT INTO audit (EMP_no, NAME) VALUES (NEW.ID, NEW.NAME); END $$ DELIMITER ;
说明:
触发器名称:
audit_log触发时间:
AFTER INSERT— 在插入操作完成后触发触发事件:在
employees_test表上执行INSERT时触发操作:使用
NEW.ID和NEW.NAME获取刚刚插入的新数据,并插入到audit表中字段对应:
audit.EMP_no←employees_test.IDaudit.NAME←employees_test.NAME
测试过程:
sql
-- 清空数据(方便重复测试) DELETE FROM audit; DELETE FROM employees_test; -- 插入员工数据 INSERT INTO employees_test (ID,NAME,AGE,ADDRESS,SALARY) VALUES (1, 'Paul', 32, 'California', 20000.00); -- 查询 audit 表 SELECT * FROM audit;
输出结果:
text
1|Paul