1.已经介绍了触发器的定义以及适用场景,此时我们这里要实战一下:
1.首先我们设计一个触发器的场景
这里我们有两张表,一个goods表:里面对应的是商品的各种信息(gid,gname,gmuch)
一个订单表order:里面是用户下的订单(oid,gid,omuch)
设计原理:每当用户下订单后,商品表中的对应的商品数量会随着订单表的数量改变而变
2. 建表
create table goods(gid int not null,gname varchar(20),gmuch int)engine=innodb;
create table orders(oid int not null,gid int,omuch int ) engine=innodb;
3.插入数据
insert into goods values(1,'cat',100),(2,'dog',200),(3,'pig'300);
2.创建触发器
语法:
create trigger 触发器名称
after/before(触发时间)
insert /update/delete(监视事件)
on 表名(监视地址)
for each row
begin
sql1;
..
sql2;
end
这里的逻辑是:当用户下订单时,买了几个商品后,goods的总商品数量就会减少几个,因此这里用的是关键字new,且用总商品数量-new.用户下的商品数量
create trigger t1
after
insert
on orders
for each row
begin
update goods set gmuch=gmuch-new.omuch where gid=new.gid;
end $
如果这里逻辑是:当用户取消订单时,这里是要用关键字old, 具体操作是用总商品的数量+old.用户取消的商品的数量
delimiter $
create trigger t2
after
delete
on orders
for each row
begin
update goods set gmuch=gmuch+old.omuch where gid=old.gid;
end $
#以上都是对数量进行插入和删除操作,如果可以对数量进行修改操作,那么该如何?
delimiter $
creater trigger t3
before
update
on orders
for each row
begin
update goods set gmuch=gmuch+old.omuch -new.omuch where gid=old.gid; ##这里的逻辑是先把旧行数据给返回去,然后再减掉新行的数据,这时就是此时商品中还剩的数量
end $
这里有几个问题?
1.首先before与after到底有什么区别?
2.如果用户购买的数量超过了商品库存总数,会发生什么情况?
mysql> select * from goods;
+-----+-------+-------+
| gid | gname | gmuch |
+-----+-------+-------+
| 1 | cat | 90 |
| 2 | dog | 299 |
| 3 | pig | 300 |
+-----+-------+-------+
3 rows in set (0.00 sec)
mysql> select * from orders;
+-----+------+-------+
| oid | gid | omuch |
+-----+------+-------+
| 121 | 1 | 2 |
| 122 | 1 | 9 |
+-----+------+-------+
2 rows in set (0.00 sec) ###这里我们可以发现cat的数量还剩90只,如果此时另外有个用户想买100只猫,此时会发生什么情况?
mysql> insert into orders values(123,1,100);
Query OK, 1 row affected (0.00 sec)
mysql> select * from goods;
+-----+-------+-------+
| gid | gname | gmuch |
+-----+-------+-------+
| 1 | cat | -10 | ###这里看到商品库存中猫的数量变成了-10只,这样的情况在现实的数据库中是不允许的
| 2 | dog | 299 |
| 3 | pig | 300 |
+-----+-------+-------+
3 rows in set (0.00 sec)
mysql> select * from orders;
+-----+------+-------+
| oid | gid | omuch |
+-----+------+-------+
| 121 | 1 | 2 |
| 122 | 1 | 9 |
| 123 | 1 | 100 |
+-----+------+-------+
3 rows in set (0.00 sec)
此时,我们可以再创建一个触发器进行如下操作
delimiter $
create trigger t4
before
insert
on orders
for each row
begin
declare rnum int; ##声明变量
select gmuch into rnum from goods where gid=new.gid; ##into也是另一种赋值操作
if new.omuch > rnum then
set new.omuch = rnum;
end if;
update goods set gmuch=gmuch - new.omuch where gid=new.gid;
end $
我们查看结果:
mysql> select * from goods;
+-----+-------+-------+
| gid | gname | gmuch |
+-----+-------+-------+
| 1 | cat | 90 |
| 2 | dog | 299 |
| 3 | pig | 300 |
+-----+-------+-------+
3 rows in set (0.00 sec)
mysql> select * from orders;
+-----+------+-------+
| oid | gid | omuch |
+-----+------+-------+
| 121 | 1 | 2 |
| 122 | 1 | 9 |
+-----+------+-------+
2 rows in set (0.00 sec)
mysql> insert into orders values(123,1,100);
Query OK, 1 row affected (0.01 sec)
mysql> select * from goods;
+-----+-------+-------+
| gid | gname | gmuch |
+-----+-------+-------+
| 1 | cat | 0 | ####此时这里的库存就是0,而不是负数了!
| 2 | dog | 299 |
| 3 | pig | 300 |
+-----+-------+-------+
3 rows in set (0.00 sec)
mysql> select * from orders;
+-----+------+-------+
| oid | gid | omuch |
+-----+------+-------+
| 121 | 1 | 2 |
| 122 | 1 | 9 |
| 123 | 1 | 90 |
+-----+------+-------+
3 rows in set (0.00 sec)
补充:new和old的判断:
如下图:
触发器引用行变量