Mysql 13: 触发器全解——创建、查看、使用与注意事项

触发器(Trigger)是与表相关联的特殊存储过程 ,它不能手动调用 ,而是在执行 INSERT/UPDATE/DELETE 操作时自动触发。常用于数据审计、日志记录、数据校验、级联操作。


一、触发器核心概念

1. 触发时机与事件

  • 触发事件INSERTUPDATEDELETE
  • 触发时机
    • BEFORE:操作执行触发(常用于数据校验、预处理)。
    • AFTER:操作执行触发(常用于日志记录、级联更新)。
  • 触发对象FOR EACH ROW(行级触发,每影响一行执行一次)。

2. 核心限制

  • 不支持 SELECT 语句(直接返回结果)。
  • 不支持事务回滚(InnoDB 中,触发器执行失败会导致主事务回滚)。
  • 一个表同一事件同一时机只能有一个触发器。

二、创建触发器(核心代码)

1. 基础语法

sql 复制代码
DELIMITER //  -- 修改结束符,避免与内部;冲突
CREATE TRIGGER 触发器名
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON 表名 FOR EACH ROW
BEGIN
    -- 触发器体:SQL 语句集合
    -- 引用旧数据: OLD (修改前的值)
    -- 引用新数据: NEW (修改后的值)
END //
DELIMITER ;  -- 恢复结束符

2. 场景一:创建只有一个执行语句的触发器

需求:在学生表插入数据时,自动记录操作日志到日志表。

sql 复制代码
-- 1. 准备测试表
CREATE TABLE student (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    age INT NOT NULL
);

CREATE TABLE log (
    id INT PRIMARY KEY AUTO_INCREMENT,
    operation VARCHAR(20) NOT NULL,
    operate_time DATETIME NOT NULL,
    table_name VARCHAR(20) NOT NULL,
    record_id INT NOT NULL
);

-- 2. 创建触发器
DELIMITER //
CREATE TRIGGER tr_student_insert
AFTER INSERT  -- 插入操作后触发
ON student FOR EACH ROW
BEGIN
    -- 记录日志:NEW.id 是刚插入的学生ID
    INSERT INTO log(operation, operate_time, table_name, record_id)
    VALUES ('INSERT', NOW(), 'student', NEW.id);
END //
DELIMITER ;

-- 3. 测试:插入一条学生数据
INSERT INTO student (name, age) VALUES ('张三', 18);

-- 4. 查看日志表:触发器自动插入了一条日志
SELECT * FROM log;

3. 场景二:创建有多个执行语句的触发器

需求:更新学生年龄时,记录新旧年龄对比日志。

sql 复制代码
DELIMITER //
CREATE TRIGGER tr_student_update
AFTER UPDATE  -- 更新操作后触发
ON student FOR EACH ROW
BEGIN
    -- 多个执行语句用 ; 分隔
    INSERT INTO log(operation, operate_time, table_name, record_id)
    VALUES ('UPDATE', NOW(), 'student', OLD.id);
    
    -- 记录新旧值差异
    IF OLD.age != NEW.age THEN
        INSERT INTO log(operation, operate_time, table_name, record_id)
        VALUES (CONCAT('AGE_CHANGE:', OLD.age, '->', NEW.age), NOW(), 'student', NEW.id);
    END IF;
END //
DELIMITER ;

-- 测试:修改年龄
UPDATE student SET age = 20 WHERE id = 1;

三、查看触发器

1. 利用 SHOW TRIGGERS 查看

sql 复制代码
SHOW TRIGGERS;
-- 查看特定数据库的触发器
SHOW TRIGGERS FROM 数据库名;

说明:列出所有触发器的详细信息(名称、表、事件、时机)。

2. 在 triggers 表中查看详细信息

从系统数据库 information_schema 中查询,支持更精准的筛选:

sql 复制代码
SELECT * FROM information_schema.TRIGGERS
WHERE TRIGGER_NAME = 'tr_student_insert' AND TRIGGER_SCHEMA = DATABASE();

关键字段

  • EVENT_MANIPULATION:触发事件 (INSERT/UPDATE/DELETE)。
  • ACTION_TIMING:触发时机 (BEFORE/AFTER)。
  • ROUTINE_BODY:执行体语言 (SQL)。

四、触发器的使用(自动触发)

触发器无需手动调用,当触发事件发生时自动执行。

  • INSERT :插入数据时,NEW 字段有效。
  • UPDATE :更新数据时,OLDNEW 字段有效。
  • DELETE :删除数据时,OLD 字段有效。

五、删除触发器

sql 复制代码
DROP TRIGGER [IF EXISTS] 触发器名;
-- 示例
DROP TRIGGER IF EXISTS tr_student_insert;

注意:删除触发器需具有 SUPER 权限或相关权限。


六、触发器的注意事项(避坑核心)

1. 性能与维护

  • 慎用触发器:触发器是隐式执行的,调试困难,会增加数据库开销。
  • 避免级联循环:触发器内操作同一张表,可能导致死循环。
  • 索引优化:触发器内的 SQL 语句必须优化,避免全表扫描。

2. 数据一致性

  • InnoDB 事务 :在 InnoDB 中,触发器执行失败会导致主事务(如 INSERT)回滚
    • 例:INSERT 学生成功,触发器 INSERT 日志失败 → 学生数据也会被回滚。
  • MyISAM 不支持事务:触发器执行失败,主操作可能已完成,数据不一致。

3. 数据迁移与备份

  • 迁移数据库时,触发器不会自动复制,需要手动导出创建语句。
  • 使用 mysqldump --triggers 导出触发器。

4. 常见错误陷阱

  • 在触发器中使用 SELECT ... INTO
相关推荐
阿里加多4 小时前
第 1 章:Go 并发编程概述
java·开发语言·数据库·spring·golang
ShiJiuD6668889994 小时前
Mysql 进阶
数据库·mysql
一 乐4 小时前
物流信息管理|基于springboot + vue物流信息管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·物流信息管理系统
l1o3v1e4ding4 小时前
排查linux CentOS7.6的mysql磁盘 I/O 延迟过高问题
linux·运维·mysql
Rick19935 小时前
Redis 分布式锁:核心使用场景
数据库·redis·分布式
身如柳絮随风扬6 小时前
Redis如何实现高效插入大量数据
数据库·redis·缓存
Dream of maid6 小时前
Mysql(3)运算符
数据库·mysql·adb
絆人心6 小时前
Windows 下 MySQL sys 数据库误删恢复教程(mysql_upgrade 已废弃,新版适用)
mysql·数据库误删恢复·sys数据库恢复·mysql_upgrade