触发器是数据库中自动执行的存储程序,当关联表发生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.ID -
audit.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