MySQL触发器
- 触发器的触发事件有:
update
,insert
,delete
,触发时机分为事件前,事件后;- 触发器是存在每张表中,2张表中触发器名称可重复,同张表中触发器不允许重名
- 触发器的调用是被动的,换句话说:SQL执行,触发对应触发器
创建触发器
create trigger 触发器名 before/after insert/update/delete on 表名 for each row
begin
具体执行内容
end
删除触发器
drop trigger 表名.触发器名
attention!
如果你希望动手自己试试,请按照我提供的这张表👇,我下面的实例代码的试验对象就是这张表
/*建表语句*/
create table bill (
title varchar(20) default ' ' comment '品名',
pay int default 0 comment '售价',
price int default 0 comment '价格',
repertory int default 0 comment '库存',
create_time datetime default null comment '创建时间'
);
/*历史表*/
create table bill_copy (
title varchar(20) default ' ' comment '品名',
pay int default 0 comment '售价',
price int default 0 comment '价格',
repertory int default 0 comment '库存'
);
INSERT INTO bill (title, pay, price, repertory, create_time) VALUES ('k1', 1, 8, 5, null);
INSERT INTO bill (title, pay, price, repertory, create_time) VALUES ('k2', 2, 7, 5, null);
INSERT INTO bill (title, pay, price, repertory, create_time) VALUES ('k3', 3, 6, 5, null);
INSERT INTO bill (title, pay, price, repertory, create_time) VALUES ('k4', 4, 5, 5, null);
INSERT INTO bill (title, pay, price, repertory, create_time) VALUES ('k5', 5, 4, 6, null);
新增前
注意:可以操作本表中当前行
/*创建触发器:在新增每条记录前对create_time字段赋值*/
create trigger insert_trigger_before before insert on bill for each row
begin
set NEW.create_time = now();
end;
调用
insert into bill(title,pay,price,repertory) values ('k7',6,3,6);
结果
title | pay | price | repertory | create_time |
---|---|---|---|---|
k7 | 6 | 3 | 6 | 2022-12-29 13:39:51 |
新增的时候不能使用操作目标表中数据!比如这种👇,就是错误的!!!
create trigger insert_trigger_before before insert on bill for each row begin update bill set create_time = now() where title = NEW.title; end;
操作其他表中的数据,是没有问题的,比如
create trigger insert_trigger_before_2 before insert on bill for each row begin insert into bill_copy(title, pay, price, repertory) VALUES (NEW.title,NEW.pay,NEW.price,NEW.repertory); end;
bill中插入一条数据时会调用☝️触发器,bill_copy中也会新增一条数据。
新增后
注意:不能操作表中数据
create trigger insert_trigger after insert on bill
for each row SELECT NEW.title into @newTitle;
调用
insert into bill(title,pay,price,repertory) values ('k8',7,2,6);
select @newTitle; -- 返回 k8
更新前
注意:可以操作本表中当前行数据
/*每次更新,把title转小写*/
create trigger update_trigger_before before update on bill for each row
begin
set NEW.title = lower(NEW.title);
end;
调用
update bill set title = 'K8' where title = 'k8';
执行☝️后,表中k8的大小写不会发生改变!
更新后
注意:无法操作本表中数据
/*更新bill表中数据后,按title索引备份表,并更新对应数据的创建时间*/
create trigger update_trigger_after after update on bill for each row
begin
update bill_copy set create_time = now() where title = NEW.title;
end;
如果update的对象不是备份表,而是bill表,那么当你创建好触发器,执行update语句时会发现,无论如何执行都会报错!这是因为更新后,不能操作本表,操作其他表中数据是没有问题的。
删除前
/*删除前把数据写入备份表中*/
create trigger delete_trigger_before before delete on bill for each row
begin
insert into bill_copy(title, pay, price, repertory)
values(old.title, old.pay, old.price, old.repertory);
end;
删除后
/*删除后把数据写入备份表中*/
create trigger delete_trigger_after after delete on bill for each row
begin
insert into bill_copy(title, pay, price, repertory) values(old.title, old.pay, old.price, old.repertory);
end;
调用
delete from bill where title = 'k1';
执行SQL,打开bill_copy表,发现bill_copy表中多了一条记录,证明触发器执行,且成功!
扩展知识点
触发器中有2个变量:new,old,使用最多!分别代表新值和旧值
- update时,可用new,old
- insert时,用new
- delete时,用old
触发器支持存储过程,却不支持调用存储过程,如果要用到存储过程,只有重新手写,不能使用call 存储过程名
样的代码。
本文来自博客园,作者:勤匠,转载请注明原文链接:https://www.cnblogs.com/JarryShu/p/17012600.html