Mysql 温故知新系列「触发器详解」
本文内容基于 mysql 的 官方文档,如果内容存在错误,欢迎指正
触发器
用途
可以把触发器当成是 java 中的 aop 切面,一样的思路。不过,mysql 的切入层面是数据库。通过触发器,我们可以定义哪些表,在执行了如 增删改 的操作,以及操作的时间节点,并且在操作触发后,需要有什么样的动作
一些比较经典的案例:
我们可以用触发对相关的数据录入做数据库层面的校验
当数据记录删除时,我们需要将他转移到数据备份表,保证当前活动表的数据量在相对较少的层面
我最近经历过的,数据库表记录变更留痕。以触发器的方式实现,可以避免代码层面的改动 (① 是改了代码需要重新发布;② 是改了,万一涉及的地方太多,没改到位)
删除触发器
[if exists]
是可选的,表示会删除指定的并且存在的触发器;要是不存在,也不会报错
[schema_name.]
触发器所在的 DB 库,如果不指定,就会删除当前库下的这个触发器
查看触发器
我们最习惯的写法就是,第一步先删除目标触发器,第二步就是创建自己需要的触发器,sql
如下:
这种操作习惯是出于,在触发器刚创建的那段时间,我们会非常频繁的 删除 - 创建
,重复创建会提示命名被占用,因此就有了上述代码的雏形
但是,如果我们上来就这么操作,或许会不小心删除已经在运行的同名触发器!!
因此,在触发器创建之前,我们需要确认命名是否被占用,有两个方法:
一、查看当前 DB 中的全部触发器
二、从系统内置 DB 的 triggers
表中查询全部触发器
我们可以通过 where
增加对字段 trigger_name
的条件过滤
在确认命名可用后,那就可以开始考虑触发器该怎么写了
创建触发器
创建触发器的标准语法
[DEFINER = user]
涉及到触发器的权限,本人不是太懂,只了解创建时可以省略不写。下文是原文的翻译
CREATE TRIGGER
需要TRIGGER
与触发器关联的表的权限。如果DEFINER
存在该子句,则所需的权限取决于该user
值,如 第 25.6 节,“存储对象访问控制”中所述。如果启用了二进制日志记录,则CREATE TRIGGER
可能需要SUPER
特权,如第 25.7 节,“存储程序二进制日志记录”中所述。
创建语法解析
trigger_time: { BEFORE | AFTER }
只触发器触发的时间节点,与紧随其后的 trigger_event: { INSERT | UPDATE | DELETE }
触发操作组合,表示在某个操作执行之前,或之后,需要调用触发器的逻辑
trigger_order: { FOLLOWS | PRECEDES } other_trigger_name
指这个触发器在触发的时候,与其他的触发器的联动效果。如,我们当前创建的 T1
在触发之前,需要先使用另一个已有的触发器 T2
,那么这段的声明就是 PRECEDES T2
;我们日常操作中基本不会有联动其他触发器的场景,因此这一段直接可以 省略
trigger_body
触发器的主体部分。如果有多个操作,即一个 sql 无法完成,那么需要使用 begin... end
语句块将多个操作的 sql 包裹起来
注意项
一、触发器只允许在原始表上创建,即不能在临时表和视图上创建
二、触发器只能绑定到当前 DB 的表上。如果尝试在 DB1 中为 DB2.tab_name 创建触发器时,控制台会报错:[Err] 1435 - Trigger in wrong schema
三、触发器的主体部分,如果因多个 sql 操作需要使用 begin... end
语句块包裹,那么,记得在 begin
之后重命名 mysql 的语句分隔符,在 end
之前使用自己重命名的结束符作为结尾!!!
因为 mysql 默认都是以分号结尾,如果我们不重命名语句分隔符,那么 begin end
中只有第一条 sql 生效,剩下的都会忽略,从而执行的结果出乎我们的预期
多 sql 操作触发器创建模版:
版权声明: 本文为 InfoQ 作者【安逸的咸鱼】的原创文章。
原文链接:【http://xie.infoq.cn/article/e41bffaa6515cf1017e1ae074】。文章转载请联系作者。
评论