概念
触发器和存储过程一样都是嵌入到数据库中的一段程序,与存储过程不同的是,触发器不需要显式的调用,而是依靠特定事件来触发执行,这些事件包括 INSERT
、UPDATE
和 DELETE
创建触发器
CREATE TRIGGER <触发器名称> <触发时机> <触发事件> ON <表名> FOR EACH ROW <执行语句>
触发器名称: 标识触发器的名称,用户自行指定
触发时机: 可以指定为
before
或after
触发事件: 包括
INSERT
、UPDATE
和DELETE
表名: 建立触发器的表
执行语句: 表示在指定的表上,发生指定的事件之前(或后),执行的语句(组)
在执行语句中可以使用
NEW.<字段名>
来引用建立触发器的表在发生事件时受影响的行的字段值
删除触发器
DROP TRIGGER [IF EXISTS] <触发器名称>
查看触发器
SHOW TRIGGERS [LIKE '<关键字>']
触发器的问题
重复执行
当数据从一个备份拷贝中加载,或者备份数据库的时候【触发器已经执行过了!!】;
遗忘
触发器是在主流程之外的动作,很容易被遗忘,造成维护问题
触发器链
一个触发器的执行,可能导致另一个触发器 …,如果出现因为触发器问题导致的性能问题,会很难定位问题位置和原因
批量操作
MySQL触发器基于行触发,而不是一组SQL语句。因此,如果需要变动整个数据集而数据集数据量又较大时,触发器效果会非常低。
每一个表的一个事件只能定义一个触发器,例如:不能在AFTER INSERT上定义一个以上的触发器。
死锁
在基于锁的操作中,触发器可能会导致锁等待或死锁。触发器执行失败,原来执行的SQL语名也会执行失败。而因为触发器导致的失败结果和失败原因,往往很难排查。
触发器的使用场景举例
与存储过程类似,在高并发的互联网类应用中,不建议使用,在企业级应用中可以适当使用。虽然有些场景不适合直接使用数据库的触发器,但是触发器的概念非常有用,可以在代码中实现更实用的触发器逻辑。
基于行数据变更的日志记录。
如:在用户订单系统中,我们可以基于用户订单数据状态的改变,使用触发器构建用户订单日志表数据。
基于行数据变更的关系数据的更新。
如:用户订单改变至付款或相关状态时,我们可以基于用户订单数据状态的改变,使用触发器改变用户会付款或相应状态信息。
基于行数据变更的数据汇总。
如:用户订单成交或失败,我们可以基于用户订单数据状态的改变,使用触发器构建用户总成交量或失败量汇总数据。