MySQL触发器

触发器是一类特殊的事务,可以监视某种数据操作(insert,update,delete),并触发相关操作(insert,update,delete)

触发器创建之四要素:

  监视地点

  (table)

     监视事件

(insert,update,delete)

  触发时间

(after,before)

     触发事件

(insert,update,delete)

举个例子,有两张表,分别是商品表goods和订单表ord

当下一个订单的时候,对应的商品要相应减少(买几个商品就少几个库存)

分析:

监视谁:ord

监视动作:insert

触发时间:after

触发事件:update

那么就来写创建触发器的语法:

delimiter $     (这是指定程序碰见$才结束,而不是以分号结束)

create trigger 触发器名称

after/before(触发时间)

insert/update/delete(监视事件)

on 表名(监视地址)

for each row

begin

sql1;

...

sqlN;

end $

---------------------

我们可以看到我们的商品表已经创建好了:

然后我们下订单:

我想买3只猫,那么我们用触发器来实现这个操作:

create trigger t2
after
insert
on ord
for each row
begin
update goods set num=num-new.much where gid=new.gid;
end$

我们可以看到订单表是空的,然后我们给里面插入数据:

然后我们去看看商品表里面的库存变了没:

我们可以看到猫的库存确实减少了三只

那我们想删除一个订单,退货,那么库存就应该再加回去,应该怎么做?

我们新建一个触发器,监视删除订单的操作:

create trigger t3
after
delete
on ord
for each row
begin
update goods set num=num+old.much where gid=old.gid;
end$

上面是原来的订单和库存,下面是我们执行删除订单后的数据,没有任何问题:

---------------------

那我们想修改订单,我们想把上面的订单买的猫数量改一下:我想买1只猫,三只猫太多了养不过来。

那我们建立一个新的触发器来监视订单的修改:

create trigger t4
before
update
on ord 
for each row
begin
update goods set num=num+old.much-new.much where gid=new.gid;
end$

这是改订单之前我们的库存。

然后我们来改订单:

update ord set much=1 where oid=1$

我们可以看到猫的数量变成了33,这证明我们写的触发器没有问题。

---------------------------------

那么我们再思考,如果购买的数量超过库存应该怎么办?能不能预防?

 假设我们有个大客户他下了一个订单想买25头猪:

我们增加一个订单:

insert into ord values(2,3,25)$

我们看到这个订单确实被增加进去了,但是库存呢?

我们看到这个猪的库存变成了-4,这种情况叫爆仓,这是不允许发生的,那么我们怎么预防它?

我们建立一个判断,如果new.much的值>num,那么我们把new.much=num

我们把原来的t2触发器删掉,新建一个t5触发器:

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$

注意一定要用before,否则会报下面的错误:

这是我们的库存,接下来我们生成一个订单,买25头猪:

我们可以看到库存已经为0;

订单表也显示只买了21头猪。

 这证明我们的触发器确实发挥了作用。

然后我们看到我们的触发器语句里面有for each row,那么它是干啥的?

举个例子:

我们建立一个新表:

我们创建一个触发器:每当ord的数据被修改,我们就往tmp表插入一个5

create trigger t9
after
update
on
ord
for each row
begin
insert into tmp values(5);
end$

我们看到我们的tmp现在是空的,我们接下来修改ord表中的值:

然后我们去看看tmp表有何变化:

我们可以看到tmp表一次被增加了两条数据。

这就是for each row的作用:它是声明 每一行受影响,触发器都触发一次,这种触发器也叫行级触发器。mysql暂时不支持语句级触发器

原文地址:https://www.cnblogs.com/wanghaoyu666/p/11309832.html