详细可以查看mysql8.0官方文档:https://dev.mysql.com/doc/refman/8.0/en/triggers.html,这里只是简单做个笔记。

什么是触发器,复制网上的一段解释:

触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性。
举个例子,比如你现在有两个表【用户表】和【日志表】,当一个用户被创建的时候,就需要在日志表中插入创建的log日志,如果在不使用触发器的情况下,你需要编写程序语言逻辑才能实现,但是如果你定义了一个触发器,触发器的作用就是当你在用户表中插入一条数据的之后帮你在日志表中插入一条日志信息。当然触发器并不是只能进行插入操作,还能执行修改,删除。

定义触发器的语法格式

CREATE TRIGGER trigger_name trigger_time trigger_event ON tb_name FOR EACH ROW trigger_stmt

1.trigger_name:触发器的名称
2.tirgger_time:触发时机,为BEFORE或者AFTER
3.trigger_event:触发事件,为INSERT、DELETE或者UPDATE
4.tb_name:表示建立触发器的表名,就是在哪张表上建立触发器
5.trigger_stmt:触发器的程序体,可以是一条SQL语句或者是用BEGIN和END包含的多条语句

所以可以说MySQL创建以下六种触发器:
BEFORE INSERT,BEFORE DELETE,BEFORE UPDATE
AFTER INSERT,AFTER DELETE,AFTER UPDATE

Demo

创建两张测试表:

-- 创建用户信息名
create table users(
	id int,
	name varchar(20)
);

-- 创建用户信息日志表
create table users_log(
	uid int,
	uname varchar(20),
	oper_time timestamp,
	info varchar(100)
);

1.定义insert型触发器trig_insert_users,作用是当向users表中插入一条用户信息时users_log表中同步记录该用户的创建信息:

create trigger trig_insert_users after insert on users for each row 
insert into users_log(uid, uname, oper_time, info) values (new.id, new.name, now(), "created");

当执行这条插入语句insert into users(id, name) values(1, "user01");后,users_log表中的信息:
在这里插入图片描述

2.定义update型触发器trig_update_users,作用是对users表中的某条用户信息修改时users_log表中记录相关修改信息:

create trigger trig_update_users after update on users for each row
insert into users_log(uid, uname, oper_time, info) values (old.id, old.name, now(), concat("modified: name -> ", new.name));

对name进行修改,update users set name = "user02" where id = 1;,users_log表:
在这里插入图片描述

3.定义delete型触发器trig_delete_users,当对用户信息进行删除时users_log表记录删除日志:

create trigger trig_delete_users after delete on users for each row
insert into users_log(uid, uname, oper_time, info) values (old.id, old.name, now(), "deleted");

执行delete from users where id = 1;删除id为1的用户,users_log表:
在这里插入图片描述
上面都为after触发,after触发一般可以用来记录日志、多表数据联动修改等。下面写个before触发,before触发可以用来做数据的合法性校验,执行语句的安全控制等,

create trigger trig_check_id before insert on users for each row
begin
	if new.id is null then 
		set new.id = (select max(id) from users) + 1;
	elseif new.id < 0 then 
		set new.id = abs(new.id);
	end if;
end;

这个触发器的目的是当插入的id值为null时,将id赋值为表中最大id+1,当id为负值时赋值为它的绝对值。

清空一下表truncate users;
插入三条测试数据:insert into users(id, name) values (1, "user01"), (null, "user02"), (-3, "user03");
在这里插入图片描述

关键字new&old

简单的概括:new可以理解为将要或已经插入的记录,old可以理解为将要或已经删除的记录,可以通过new.列名获取新增行的某列数据,或者old.列名的方式获取删除行的某列数据。update过程可以理解为先delete再insert。

下图是摘自文档里的一部分:
在这里插入图片描述
4段,对照着大致翻译为:
(1)在触发器内部可以通过new和old关键字获取被触发器影响的行,关键字不区分大小写。
(2)insert触发器只有new操作,指代插入的值;delete触发器只有old操作,指代删除的值;update触发器即有new也有old,old指代修改之前的值,new指代修改之后的值。
(3)old指代的列只能读不能改,new指代的列可改,但在after触发时无意义。(after触发时新值已经写入表,再修改已经不会影响表了)
(4)before触发器对于设为AUTO_INCREMENT自动增长的列c1,通过new.c1拿到的并不是每次插入时生成的值,而是0。(after触发器拿到的是每次插入时生成的值)

触发器的查看&删除

查看
方式1:show triggers;
方式2:select * from information_schema.triggers;(所有触发器信息都在information_schema库下的triggers表中)

删除
可以drop trigger 触发器名;,也可以drop trigger 库名.触发器名;,但不能drop trigger 表名.触发器名;

触发器依附表而存在,当删除表时所有与之相关的触发器也会随之删除。

注意事项

MySQL的触发器是按照BEFORE触发器、行操作、AFTER触发器的顺序执行的,其中任何一步发生错误都不会继续执行剩下的操作。如果对事务表进行的操作,如果出现错误,那么将会被回滚。如果是对非事务表进行操作,那么就无法回滚了,数据可能会出错。

Logo

本社区面向用户介绍CSDN开发云部门内部产品使用和产品迭代功能,产品功能迭代和产品建议更透明和便捷

更多推荐