Mysql -- 触发器
触发器定义
触发器是一类特殊的事务,可以监视某种数据操作(insert、update、delete),并触发相关操作。
触发器简单一点解释就是,当一张表中的数据发生改变时,关联的另外一张表中的数据也会发生改变。触发事件的操作和触发器里的SQL语句是一个事务操作,具有原子性,要么全部执行,要么都不执行,可以保证数据的完整性。
应用场合
1、当一个订单产生时,订单所购的商品的库存量相应减少。
2、当某客户进行欠款消费,可以再生成订单时通过设计触发器判断该客户的累计欠款是否超出了最大限度。
3、当有新订单产生时,需要及时通知相关人员进行处理,此时可以在订单表上设计添加触发器加以实现。
创建语法4要素
1、监视地点:table
2、监视事件:insert、update、delete
3、触发时间:after、before
4、触发事件:insert、update、delete
创建一个触发器
1.创建两张表,一张是商品库存表,一张是订单表,sql如下:
create table goods (
gid int,
name varchar(20),
num smallint
);
create table ord (
oid int,
gid int,
much smallint
);
insert into goods values
(1,'cat',34),
(2,'dog',65),
(3,'pig',21);
2.创建一个简单触发器
create trigger t1
after
insert
on ord
for each row
begin
update goods set num=num-new.much where gid=new.gid;
end;
通过show triggers查看
3.测试一下
select * from goods;
insert into ord values(100,1,2);
select * from ord;
select * from goods;
4.模仿insert创建一个delete触发器
create trigger t2
after
delete
on ord
for each row
begin
update goods set num=num+old.much where gid=old.gid;
end;
5.新增和删除已经做完了,修改订单呢?
create trigger t3
before
update
on ord
for each row
begin
update goods set num=num+old.much-new.much where gid=old.gid;
end;
测试下:
select * from goods;
select * from ord;
update ord set much=3 where oid=100;
select * from ord;
6.after和before的区别
目前为止after和before似乎并没有任何不同。想一下,如果库存只有3只猫了,但客户买了5只,会发生什么?
库存中猫的数量变成-2只,这就是传说中的爆仓。怎么办?如何预防这种情况发生?
可以再购买量much>库存量num时,把much自动改为num。
create trigger t5
after
insert
on ord
for each row
begin
declare
rnum int;
select num into rnum from goods where gid=new.gid;
if new.much > rnum then
set new.much = rnum;
end if;
update goods set num=num-new.much where gid=new.gid;
end;
创建时报错如下:
[Err] 1362 - Updating of NEW row is not allowed in after trigger
after trigger为数据已经插入磁盘之后触发,上面的触发器在数据插入数据库之后再set,已经没有意义了。因此需要改为before
create trigger t5
before
insert
on ord
for each row
begin
declare
rnum int;
select num into rnum from goods where gid=new.gid;
if new.much > rnum then
set new.much = rnum;
end if;
update goods set num=num-new.much where gid=new.gid;
end;
测试如下:
select * from goods;
insert into ord values(100,3,23);
select * from ord;
select * from goods;