触发器
约 817 字大约 3 分钟
布欧-Lewyon
2026-05-15
首页 › MySQL › 高级特性(在新窗口打开) › 触发器
触发器(Trigger)是自动执行的存储程序——在某个表上发生 INSERT、UPDATE 或 DELETE 操作时,MySQL 自动调用触发器中的 SQL。
触发器语法
CREATE TRIGGER trigger_name
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON table_name FOR EACH ROW
BEGIN
-- 触发器逻辑
END;BEFORE INSERT:数据校验
-- 在插入前校验 email 格式
DELIMITER $$
CREATE TRIGGER validate_email_before_insert
BEFORE INSERT ON employee
FOR EACH ROW
BEGIN
IF NEW.email IS NOT NULL AND NEW.email NOT LIKE '%@%.%' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '邮箱格式不正确';
END IF;
END$$
DELIMITER ;
INSERT INTO employee (name, email) VALUES ('测试', 'invalid-email');
-- ERROR: 邮箱格式不正确BEFORE UPDATE:字段变更跟踪
-- 自动更新修改时间
CREATE TRIGGER update_timestamp_before_update
BEFORE UPDATE ON employee
FOR EACH ROW
SET NEW.updated_at = NOW();AFTER INSERT:日志记录
-- 员工入职后自动写入日志
DELIMITER $$
CREATE TRIGGER log_employee_insert
AFTER INSERT ON employee
FOR EACH ROW
BEGIN
INSERT INTO employee_log (employee_id, action, old_value, new_value)
VALUES (NEW.id, 'INSERT', NULL, CONCAT(NEW.name, ',', NEW.salary));
END$$
DELIMITER ;访问新旧值
在触发器中使用 OLD 和 NEW 关键字:
| 操作 | OLD | NEW |
|---|---|---|
| INSERT | 无(所有列 NULL) | 新插入的行 |
| UPDATE | 更新前的行 | 更新后的行 |
| DELETE | 被删除的行 | 无(所有列 NULL) |
-- 记录薪资变更历史
DELIMITER $$
CREATE TRIGGER salary_change_log
BEFORE UPDATE ON employee
FOR EACH ROW
BEGIN
IF OLD.salary <> NEW.salary THEN
INSERT INTO salary_history (employee_id, old_salary, new_salary, changed_at)
VALUES (OLD.id, OLD.salary, NEW.salary, NOW());
END IF;
END$$
DELIMITER ;管理触发器
-- 查看触发器
SHOW TRIGGERS;
-- 查看特定表的触发器
SHOW TRIGGERS WHERE `Table` = 'employee';
-- 查看触发器定义
SHOW CREATE TRIGGER log_employee_insert;
-- 删除触发器
DROP TRIGGER IF EXISTS log_employee_insert;触发器的问题
| 问题 | 说明 |
|---|---|
| 隐式行为 | 一条 INSERT 可能触发多层触发器,但应用层完全不知情 |
| 调试困难 | 触发器执行失败时,外层 SQL 报错信息不明确 |
| 性能影响 | 每次 DML 都额外执行触发器逻辑,批量操作时显著变慢 |
| 级联问题 | 触发器 A 更新表 B,表 B 的触发器再更新表 A,可能形成循环 |
| 迁移成本 | 从 MySQL 迁移到其他数据库,触发器语法各不同 |
使用建议
| 推荐 | 不推荐 |
|---|---|
| 关键字段的变更审计日志 | 代替应用层的校验逻辑 |
| 简单的数据同步(如从表缓存更新) | 复杂的业务流程编排 |
| 自动维护冗余/派生字段 | 涉及外部系统的调用 |
| 约束性校验(替代 CHECK 的预 8.0.16 方案) | 大批量 ETL 中的逐行处理 |
生产环境使用触发器前,务必在文档中明确记录每个触发器的存在、行为和业务目的,并考虑其对批量 DML 的性能影响。
小结
- 触发器在
BEFORE/AFTER和INSERT/UPDATE/DELETE时自动执行。 OLD访问修改前的值,NEW访问修改后的值。- 触发器可做校验、审计日志、自动维护派生字段等。
- 触发器的隐式行为可能导致调试困难和性能问题,使用前需权衡利弊。
