4.触发器(trigger)简单实例

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的判断:

如下图:

触发器引用行变量

 

posted on 2021-04-11 12:55  太白金星有点烦  阅读(539)  评论(0编辑  收藏  举报

导航