触发器:trigger
监控某数据操作(insert/update/delete)并触发相应的操作(insert/update/delete)
触发器几个概念
监视地点 table
监视事件 insert/update/delete
触发时间 after/before
触发事件 insert/update/delete
例子: 商品表goods,订单表goodsorder
表结构如下
goods
id name(商品名)num(数量)
goodsorder
id gid(商品id)much(数量)
当下一个订单时,对应的商品数量相应减少
分析:
监视地点: goodsorder
监视事件:insert
触发时间:after
触发事件:update
先修改下结束符 delimiter $
create trigger trigger1
after
insert
on goodsorder
for each row
began
update goods set num=num-1 where id=1; (进行sql语句)
end$
这里怎么传值呢?
所以要引入行变量的概念
参数传值
分析:我们监视的是goodsorder表的insert语句,那么insert语句产生的数据能否在触发器中引用呢?
使用new/old表示表名
操作 行为 表名表示方式
insert 语句中 新产生的 new
delete语句中 删除的old
update语句中 修改前old
修改后 new
例:删除订单表中的订单,使之商品表的数量自动更新
修改上述中的触发器
delimiter $
create trigger trigger2
after insert on goodsorder
for each row
begin
update goods set num=num-new.much where id=new.gid;
end$
例如:修改订单表中的数据,使之商品表中的数量自动更新
create trigger trigger3
before update on goodsorder
for each row
begin
update goods set num = num - old.much + new.much where id=old.gid;
end$
在上面两个触发器中可以看到有before/after ,这就是在检测点之前还是检测点滞后进行触发
声明变量
declare
变量名 类型;
赋值 into 变量名
例子:假如目前a物品剩余2件,但是一用户购买了5件,怎么防止爆仓
思路:先查询商品仓库数量有没有大于购买数量
若 大于 购买数量=商品仓库里数量
否则 正常购买
create trigger trigger4
after insert on goodsorder
for each row
begin
declare rnum int;
select num into rnum from goods where id=new.gid;
if rnum<new.much then
set new.much=rnum;
end if;
update goods set num=num-new.much where id=new.gid;
end$
若使用after 则会报错 ERROR 1362 (HY000): Updating of NEW row is not allowed in after trigger
这就是说只有在触发器之前才能进行变量操作
所以要把after换成before
for each row 是行级触发器,影响多少行触发多少次
不加此句则为语句级触发器,只触发一次
oracle 支持行级和语句级触发器
mysql 只支持行级能触发器
本文是抄自燕十三老师的教学视频