Jw
首页
技术
英语
首页
技术
英语
  • MySQL

    • MySQL 基础
    • 环境变量配置(PATH)
    • SQL 语法与分类
    • MySQL 数据类型
    • SQL - DDL 数据定义语言
    • SQL - DML 数据操作语言
    • SQL - DQL 数据查询语言
    • SQL - DCL 数据控制语言
    • MySQL 函数
    • SQL 约束
    • SQL 外键约束
    • 多表关系
    • 多表查询(连接查询)
    • 隐式内连接 vs 显式内连接
    • 子查询
    • 多表查询案例
    • 事务
    • 并发事务问题与隔离级别
    • MySQL 体系结构与存储引擎
    • 索引概述
    • 索引结构
    • 索引分类
    • 索引语法
    • SQL 性能分析
    • 索引使用
    • 索引设计原则
    • SQL 优化 - 插入数据与主键优化
    • SQL 优化 - order by 与 group by
    • SQL 优化 - limit / count / update
    • 视图
    • 存储过程
    • 存储过程 - 变量
    • 存储过程 - 流程控制、游标与条件处理
    • 存储函数
    • 触发器
    • 锁概述与全局锁
    • 表级锁
    • 行级锁
    • InnoDB 逻辑存储结构
    • InnoDB 架构
    • 事务原理(redo / undo log)
    • MVCC
    • MySQL 系统数据库
    • MySQL 常用工具
    • 数据备份与导入导出
    • 错误日志与二进制日志
    • 查询日志与慢查询日志
    • 主从复制 - 概述与原理
    • 主从复制 - 搭建
    • Mycat 配置
    • Mycat 垂直拆分与水平拆分
    • Mycat 分片规则
    • Mycat 管理与监控
    • Mycat 读写分离 - 一主一从
    • Mycat 读写分离 - 双主双从

触发器

触发器是与表相关的数据库对象:在 INSERT / UPDATE / DELETE 之前或之后,自动执行其中定义的 SQL 语句集合,常用于保证数据完整性、记录日志、数据校验。

一、介绍

  • 通过别名 OLD 和 NEW 引用触发器中发生变化的记录内容。
  • 触发器只支持行级触发(FOR EACH ROW),不支持语句级触发。
触发器类型NEW 与 OLD
INSERT 型NEW 表示将要或已经新增的数据
UPDATE 型OLD 表示修改之前的数据,NEW 表示将要或已经修改后的数据
DELETE 型OLD 表示将要或已经删除的数据

INSERT 型没有 OLD,DELETE 型没有 NEW,引用不存在的一侧会报错。

二、语法

操作语法
创建CREATE TRIGGER trigger_name BEFORE/AFTER INSERT/UPDATE/DELETE ON tbl_name FOR EACH ROW BEGIN ... END;
查看SHOW TRIGGERS;
删除DROP TRIGGER [schema_name.]trigger_name;(不写 schema_name 时默认当前数据库)

命令行中创建触发器需先用 DELIMITER 临时改结束符,否则 BEGIN ... END 内的 ; 会被提前结束;图形化工具无需处理。

三、案例:记录 tb_user 的数据变更日志

需求:把 tb_user 的增加、修改、删除操作记录到日志表 user_logs。

准备日志表

CREATE TABLE user_logs(
    id INT(11) NOT NULL AUTO_INCREMENT,
    operation VARCHAR(20) NOT NULL COMMENT '操作类型, insert/update/delete',
    operate_time DATETIME NOT NULL COMMENT '操作时间',
    operate_id INT(11) NOT NULL COMMENT '操作的ID',
    operate_params VARCHAR(500) COMMENT '操作参数',
    PRIMARY KEY(id)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

插入触发器(AFTER INSERT,用 NEW 取新增数据)

CREATE TRIGGER tb_user_insert_trigger
    AFTER INSERT ON tb_user FOR EACH ROW
BEGIN
    INSERT INTO user_logs(id, operation, operate_time, operate_id, operate_params)
    VALUES (NULL, 'insert', NOW(), NEW.id,
            CONCAT('插入数据内容: id=', NEW.id, ',name=', NEW.name, ',phone=', NEW.phone,
                   ',email=', NEW.email, ',profession=', NEW.profession));
END;

修改触发器(AFTER UPDATE,同时记录 OLD 修改前与 NEW 修改后)

CREATE TRIGGER tb_user_update_trigger
    AFTER UPDATE ON tb_user FOR EACH ROW
BEGIN
    INSERT INTO user_logs(id, operation, operate_time, operate_id, operate_params)
    VALUES (NULL, 'update', NOW(), NEW.id,
            CONCAT('更新之前的数据: id=', OLD.id, ',name=', OLD.name, ',phone=', OLD.phone,
                   ',email=', OLD.email, ',profession=', OLD.profession,
                   ' | 更新之后的数据: id=', NEW.id, ',name=', NEW.name, ',phone=', NEW.phone,
                   ',email=', NEW.email, ',profession=', NEW.profession));
END;

删除触发器(AFTER DELETE,用 OLD 取被删除数据)

CREATE TRIGGER tb_user_delete_trigger
    AFTER DELETE ON tb_user FOR EACH ROW
BEGIN
    INSERT INTO user_logs(id, operation, operate_time, operate_id, operate_params)
    VALUES (NULL, 'delete', NOW(), OLD.id,
            CONCAT('删除之前的数据: id=', OLD.id, ',name=', OLD.name, ',phone=', OLD.phone,
                   ',email=', OLD.email, ',profession=', OLD.profession));
END;

触发测试

INSERT INTO tb_user(id, name, phone, email, profession, age, gender, status, createtime)
VALUES (25, '二皇子', '18809091212', 'erhuangzi@163.com', '软件工程', 23, '1', '1', NOW());

UPDATE tb_user SET profession = '会计' WHERE id = 23;
DELETE FROM tb_user WHERE id = 25;

SELECT * FROM user_logs;     -- 三条记录:insert / update / delete

易错:UPDATE 的触发器要同时引用 OLD 和 NEW 才能对比修改前后的值。

速查

-- 查看当前库的全部触发器
SHOW TRIGGERS;

-- 删除触发器(存在才删)
DROP TRIGGER IF EXISTS tb_user_insert_trigger;

-- 插入后记录日志:NEW 为新增数据
CREATE TRIGGER tb_user_insert_trigger AFTER INSERT ON tb_user FOR EACH ROW
BEGIN
    INSERT INTO user_logs(id, operation, operate_time, operate_id, operate_params)
    VALUES (NULL, 'insert', NOW(), NEW.id, CONCAT('name=', NEW.name));
END;

-- 修改后记录日志:OLD 为修改前,NEW 为修改后
CREATE TRIGGER tb_user_update_trigger AFTER UPDATE ON tb_user FOR EACH ROW
BEGIN
    INSERT INTO user_logs(id, operation, operate_time, operate_id, operate_params)
    VALUES (NULL, 'update', NOW(), NEW.id,
            CONCAT('before=', OLD.profession, ' after=', NEW.profession));
END;

-- 删除前记录日志:OLD 为被删除数据
CREATE TRIGGER tb_user_delete_trigger AFTER DELETE ON tb_user FOR EACH ROW
BEGIN
    INSERT INTO user_logs(id, operation, operate_time, operate_id, operate_params)
    VALUES (NULL, 'delete', NOW(), OLD.id, CONCAT('name=', OLD.name));
END;
触发时机能引用的数据
INSERTNEW
UPDATEOLD(修改前)、NEW(修改后)
DELETEOLD

相关

  • 存储过程:触发器体内同样使用 BEGIN ... END 和 SQL 语句
  • 视图:同属数据库对象
  • SQL DML 数据操作语言:触发器作用于 INSERT / UPDATE / DELETE
最近更新: 2026/10/14 22:48
Contributors: liujw
Prev
存储函数
Next
锁概述与全局锁