createdatabaseifnotexists trigger_test;use trigger_test;createtable `goods` ( id intprimary key auto_increment,namevarchar(20) comment '商品名称', stock int comment '商品库存') charset utf8 engine myisam;createtable `order` ( id intprimary key auto_increment, g_id int comment '订单购买的商品id', num int comment '订单购买的商品数量') charset utf8 engine myisam;
编写触发器:
-- 编写触发器delimiter //-- 添加订单droptriggerifexists order_create//createtriggerorder_createafterinserton`order`for each rowbeginupdate goods set stock = stock - new.num where id = new.g_id;end//-- 撤销订单droptriggerifexists order_cancel//createtriggerorder_cancelafterdeleteon`order`for each rowbeginupdate goods set stock = stock + old.num where id = old.g_id;end//-- 修改订单数量delimiter ;-- 测试买两只小猫insert into`order`values (1, 1, 2);select*from goods where id =1; # 发现小猫的库存减少了2-- 取消订单deletefrom`order`where id =1;select*from goods where id =1; # 发现小猫的库存增加了2
注意:
要获取插入/修改的新行,需要引用行变量new
要获取删除/修改的旧行,需要引用行变量old
限制购买数量:
# 上面的触发器触发时间全部为after,当我们需要监控商品的库存量的时候,比如当超过库存后,只能购买最大库存量,此时就需要before# before可以在记录插入之前修改记录的值,从而限制购买数量delimiter //droptriggerifexists order_create//createtriggerorder_createbeforeinserton`order`for each rowbegindeclare g_stock int;# 获取库存量, 使用into将查询结果复制给变量中select stock into g_stock from goods where id = new.g_id;# 如果库存不够,就将购买数量设置位最大的库存if g_stock < new.num thenset new.num = g_stock ;endif ;update goods set stock = stock - new.num where id = new.g_id;end;delimiter ;-- 测试,购买100只猫select*from goods;insert into`order`values (3, 1, 100);select*from`order`; # 最后只买了最大的库存量
for each row:
mysql触发器中的for each row是做什么的?
在oracle触发器中,分为
语句级触发器
行级触发器
如果是行级触发器,update语句如果更新了100行记录,触发器将会被触发100次
如果是语句级触发器,update语句如果更新了100行记录,触发器仍然只会触发1次
mysql目前没有语句级别的触发器,在oracle中如果for each row 不写,则是语句级触发器