MySQL数据库(32):触发器 trigger

瑞星  金牌会员 | 2022-6-26 04:22:42 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 637|帖子 637|积分 1911

触发器 trigger

一、基本概念

触发器是一种特殊类型的存储过程,触发器通过事件进行触发而被执行
触发器 trigger 和js事件类似
1、作用:

  • 写入数据表前,强制检验或转换数据(保证数据安全)
  • 触发器发生错误时,异动的结果会被撤销(事务安全)
  • 部分数据库管理系统可以针对数据定义语言DDL使用触发器,称为DDL触发器
  • 可以依照特定的情况,替换异动的指令 instead of(mysql不支持)
2、触发器的优缺点
2.1、优点

  • 触发器可通过数据库中的相关表实现级联更改(如果一张表的数据改变,可以利用触发器实现对其他表的操作,用户不知道)
  • 保证数据安全,进行安全校验
2.2、缺点

  • 对触发器过分依赖,势必影响数据库的结构,同时增加了维护的复杂度
  • 造成数据在程序层面不可控
二、创建触发器

1、基本语法
  1. create trigger 触发器名字 触发时机 触发事件 on 表 for each row
  2. begin
  3. end
复制代码
2、触发对象
on 表 for each row 触发器绑定表中所有行,没一行发生指定改变的时候,就会触发触发器
3、触发时机
每张表对应的行都有不同的状态,当SQL指令发生的时候,都会令行中数据发生改变,每一行总会有两种状态:数据操作前和数据操作后


  • before: 数据发生改变前的状态
  • after: 数据已经发生改变后的状态
4、触发事件
mysql中触发器针对的目标是数据发生改变,对应的操作只有写操作(增删改)


  • inert 插入操作
  • update 更新操作
  • delete 删除操作
5、注意事项
一张表中,每一个触发时机绑定的触发事件对应的触发器类型只能有一个
一张表表中只能有一个对应的after insert 触发器
最多只能有6个触发器
  1. before insert
  2. after insert
  3. before update
  4. after update
  5. before delete
  6. after delete
复制代码
1.1 需求

下单减库存
有两张表,一张是商品表,一张是订单表(保留商品ID)每次订单生成,商品表中对应的库存就应该发生变化
1、创建两张表
  1. create table my_item(
  2.     id int primary key auto_increment,
  3.     name varchar(20) not null,
  4.     count int not null default 0
  5. ) comment '商品表';
  6. create table my_order(
  7.     id int primary key auto_increment,
  8.     item_id int not null,
  9.     count int not null default 1
  10. ) comment '订单表';
  11. insert my_item (name, count) values ('手机', 100),('电脑', 100), ('包包', 100);
  12. mysql> select * from my_item;
  13. +----+--------+-------+
  14. | id | name   | count |
  15. +----+--------+-------+
  16. |  1 | 手机   |   100 |
  17. |  2 | 电脑   |   100 |
  18. |  3 | 包包   |   100 |
  19. +----+--------+-------+
  20. 3 rows in set (0.00 sec)
  21. mysql> select * from my_order;
  22. Empty set (0.02 sec)
复制代码
2、创建触发器
如果订单表发生数据插入,对应的商品就应该减少库存
  1. delimiter $$
  2. create trigger after_insert_order_trigger after insert on my_order for each row
  3. begin
  4.     -- 更新商品库存
  5.     update my_item set count = count - 1 where id = 1;
  6. end
  7. $$
  8. delimiter ;
复制代码
三、查看触发器

  1. -- 查看所有触发器
  2. show triggers\G
  3. *************************** 1. row ***************************
  4.              Trigger: after_insert_order_trigger
  5.                Event: INSERT
  6.                Table: my_order
  7.            Statement: begin
  8.     update my_item set count = count - 1 where id = 1;
  9. end
  10.               Timing: AFTER
  11.              Created: 2022-04-16 10:00:19.09
  12.             sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
  13.              Definer: root@localhost
  14. character_set_client: utf8mb4
  15. collation_connection: utf8mb4_general_ci
  16.   Database Collation: utf8mb4_general_ci
  17. 1 row in set (0.00 sec)
  18. -- 查看创建语句
  19. show crate trigger 触发器名字;
  20. -- eg:
  21. show create trigger after_insert_order_trigger;
复制代码
四、触发触发器

让触发器执行,让触发器指定的表中,对应的时机发生对应的操作
  1. insert into my_order (item_id, count) values(1, 1);
  2. mysql> select * from my_order;
  3. +----+---------+-------+
  4. | id | item_id | count |
  5. +----+---------+-------+
  6. |  1 |       1 |     1 |
  7. +----+---------+-------+
  8. 1 row in set (0.00 sec)
  9. mysql> select * from my_item;
  10. +----+--------+-------+
  11. | id | name   | count |
  12. +----+--------+-------+
  13. |  1 | 手机   |    99 |
  14. |  2 | 电脑   |   100 |
  15. |  3 | 包包   |   100 |
  16. +----+--------+-------+
  17. 3 rows in set (0.00 sec)
复制代码
五、删除触发器

  1. drop trigger 触发器名字;
  2. -- eg
  3. drop trigger after_insert_order_trigger;
复制代码
六、触发器的应用

记录关键字 new old
6.1 完善

商品自动扣除库存
触发器针对的是数据表中的每条记录,每行数据再操作前后都有一个对应的状态
触发器在执行之前就将对应的数据状态获取到了:


  • 将没有操作之前的数据状态都保存到old关键字中
  • 操作后的状态都放在new中
触发器中,可以通过old和new来获取绑定表中对应的记录数据
基本语法
  1. 关键字.字段名
复制代码
old和new并不是所有触发器都有


  • insert 插入前为空,没有old
  • delete 清除数据,没有new
商品自动扣减库存
  1. delimiter $$
  2. create trigger after_insert_order_trigger after insert on my_order for each row
  3. begin
  4.     -- 通过new关键字获取新数据的id 和数量
  5.     update my_item set count = count - new.count where id = new.item_id;
  6. end
  7. $$
  8. delimiter ;
复制代码
触发触发器
  1. mysql> select * from my_order;
  2. +----+---------+-------+
  3. | id | item_id | count |
  4. +----+---------+-------+
  5. |  1 |       1 |     1 |
  6. +----+---------+-------+
  7. mysql> select * from my_item;
  8. +----+--------+-------+
  9. | id | name   | count |
  10. +----+--------+-------+
  11. |  1 | 手机   |    99 |
  12. |  2 | 电脑   |   100 |
  13. |  3 | 包包   |   100 |
  14. +----+--------+-------+
  15. insert into my_order (item_id, count) values(2, 3);
  16. mysql> select * from my_order;
  17. +----+---------+-------+
  18. | id | item_id | count |
  19. +----+---------+-------+
  20. |  1 |       1 |     1 |
  21. |  2 |       2 |     3 |
  22. +----+---------+-------+
  23. mysql> select * from my_item;
  24. +----+--------+-------+
  25. | id | name   | count |
  26. +----+--------+-------+
  27. |  1 | 手机   |    99 |
  28. |  2 | 电脑   |    97 |
  29. |  3 | 包包   |   100 |
  30. +----+--------+-------+
复制代码
6.2 优化

如果库存数量没有商品订单多怎么办?
  1. -- 删除原有触发器
  2. drop trigger after_insert_order_trigger;
  3. -- 新增判断库存触发器
  4. delimiter $$
  5. create trigger after_insert_order_trigger after insert on my_order for each row
  6. begin
  7.     -- 查询库存
  8.     select count from my_item where id = new.item_id into @count;
  9.     -- 判断
  10.     if new.count > @count then
  11.         -- 中断操作,暴力抛出异常
  12.         insert into xxx values ('xxx');
  13.     end if;
  14.    
  15.     -- 通过new关键字获取新数据的id 和数量
  16.     update my_item set count = count - new.count where id = new.item_id;
  17. end
  18. $$
  19. delimiter ;
复制代码
结果验证
  1. mysql> insert into my_order (item_id, count) values(3, 101);
  2. ERROR 1146 (42S02): Table 'mydatabase2.xxx' doesn't exist
  3. mysql> select * from my_order;
  4. +----+---------+-------+
  5. | id | item_id | count |
  6. +----+---------+-------+
  7. |  1 |       1 |     1 |
  8. |  2 |       2 |     3 |
  9. +----+---------+-------+
  10. 2 rows in set (0.00 sec)
  11. mysql> select * from my_item;
  12. +----+--------+-------+
  13. | id | name   | count |
  14. +----+--------+-------+
  15. |  1 | 手机   |    99 |
  16. |  2 | 电脑   |    97 |
  17. |  3 | 包包   |   100 |
  18. +----+--------+-------+
  19. 3 rows in set (0.00 sec)
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

瑞星

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表