MySQL - 触发器案例
1. 什么是触发器及触发器的核心作用和生产环境的使用场景
触发器简介
数据库触发器绑定在指定的数据表上,由特定的数据库事件进行触发执行触发器中预定义程序
以MySQL为例子,仅允许绑定在永久物理表上,不允许绑定在视图或临时表中
拥有三种触发条件:插入数据,删除数据和更新数据
拥有两种触发时机:执行前和执行后
触发粒度:仅支持行级触发,Oracle和PostgreSQL等额外支持语句级触发
数据访问:通过Old关键字可访问原始数据,通过New关键字可访问待写入数据
核心作用
对数据库数据做安全审计与合规追溯
数据安全与风险防控
确保业务数据完整性和一致性
生产环境高频场景
在数据敏感的场景下,触发器可实现数据安全审计,确保数据追溯
在普通业务场景下,触发器对数据库中的数据完整性做保障
在全行业场景下,触发器可对数据库做防误删与数据备份场景
在高并发场景下的风险防控和限流拦截
触发器核心红线
禁止在A表的触发器,对A表做增删改行为,将触发MySQL1442错误,仅允许在Before触发器中通过Set关键字修改待写入字段值
禁止在触发器中写复杂业务逻辑,将拖慢数据库性能拖慢
禁止在触发器做嵌套/递归行为,将导致业务锁死
禁止在高并发场景使用行级触发器
禁止使用触发器替代应用层做核心业务逻辑
2. 触发器的触发时机,触发事件和触发规则
触发时机:触发前和触发后
触发事件:增,删和改
触发规则:MySQL仅支持行级触发
3. 触发器的Old和New关键字代表意思,在Insert,Update和Delete三类触发事件中可用性
触发器关键字:Old代表旧数据,New代表新数据
Insert语句中不可用Old,可用New
Update语句中可用Old,可用New
Delete语句中可用Old,不可用New
4. 解释MySQL中1442错误的触发原因,以及生产环境中对应的解决方案
MySQL触发器禁止在A表的触发器上,对A表做增删改行为
在生产环境中使用Before关键字+Set New.字段的形式对A表字段值做修改
5. 外键级联和触发器的核心区别,在生产环境中做数据完整性校验如果使用
外键级联:依附于外键约束,属于InnoDB引擎内置的声明式引用完整性约束,核心设计目标为了保证跨表关联数据的绝对一致性,行为固不可以自定义
触发器:依附于数据表上,核心设计目标为了实现灵活的自定义业务规则与全场景数据控制
6. MySQL触发器是否支持事务?触发器的执行逻辑和原SQL语句的事务关系?当触发器报错,是否影响原SQL语句?
MySQL触发器不支持独立事务
触发器和触发SQL语句处于同一个事务中
一起成功提交
一起失败回滚
触发器内执行SQL报错,触发器和触发SQL均回滚
触发器内触发逻辑不支持事务关键字
在MySQL中仅InnoDB支持事务
7. 实现触发器,对用户表的Insert行为做审计功能,将插入的数据内容写入审计日志表中
建表语句
-- 创建用户表
CREATE TABLE USER (
ID INT,
NAME VARCHAR(50),
AGE INT
);
-- 创建审计日志表
CREATE TABLE AUDIT_LOG (
INSERT_ID INT,
INSERT_NAME VARCHAR(50),
INSERT_AGE INT,
INSERT_TIME DATETIME,
INSERT_TABLE VARCHAR(50)
);触发器语句
CREATE TRIGGER TRG_INSERT_AFTER AFTER INSERT ON USER FOR EACH ROW
BEGIN
INSERT INTO AUDIT_LOG ( INSERT_ID, INSERT_NAME, INSERT_AGE, INSERT_TIME, INSERT_TABLE )
VALUE
( NEW.ID, NEW.NAME, NEW.AGE, NOW(), 'USER' );
END;测试语句
INSERT INTO USER (ID,NAME,AGE) VALUES (1,'AAA',20),(2,'BBB',22),(3,'CCC',18);
COMMIT;8. 实现触发器,对订单表的Update行为做数据修改,当Status字段值发生修改时,修改订单时间为当前时间
建表语句
-- 创建订单表
CREATE TABLE LOCATION_ORDER (
ID INT,
LOCATION VARCHAR(100),
STATUS VARCHAR(30),
CREATE_TIME DATETIME
);触发器语句
DELIMITER //
CREATE TRIGGER TRG_UPDATE
BEFORE UPDATE ON LOCATION_ORDER
FOR EACH ROW
BEGIN
IF NEW.STATUS <> OLD.STATUS THEN
SET NEW.CREATE_TIME = NOW();
END IF;
END //
DELIMITER ;测试语句
-- 插入数据
INSERT INTO LOCATION_ORDER (ID,LOCATION,STATUS,CREATE_TIME) VALUES (1,'AAA','1',NOW()),(2,'BBB','0',NOW()),(3,'CCC','1',NOW());
-- 更新数据
UPDATE LOCATION_ORDER SET LOCATION = 'ABCDEFG' WHERE ID = 1;9. 实现触发器,对学生表的Delete行为做备份,将删除行内容写入学生备份表
建表语句
-- 创建学生表
CREATE TABLE STUDENT (
ID INT,
NAME VARCHAR(50),
AGE INT
);
-- 创建学生备用表
CREATE TABLE STUDENT_BAK (
ID INT,
NAME VARCHAR(50),
AGE INT
);触发器语句
CREATE TRIGGER TRG_DELETE AFTER DELETE ON STUDENT FOR EACH ROW
BEGIN
INSERT INTO STUDENT_BAK ( ID, NAME, AGE )
VALUE
( OLD.ID, OLD.NAME, OLD.AGE );
END;测试语句
-- 插入数据
INSERT INTO STUDENT (ID,NAME,AGE) VALUES (1,'AAA',18),(2,'BBB',20),(3,'CCC',22);
-- 删除数据
DELETE FROM STUDENT WHERE ID = 1;y
评论