写点什么

Mysql 温故知新系列「触发器详解」

作者:安逸的咸鱼
  • 2022 年 7 月 17 日
  • 本文字数:1653 字

    阅读完需:约 5 分钟

本文内容基于 mysql 的 官方文档,如果内容存在错误,欢迎指正

触发器

用途

可以把触发器当成是 java 中的 aop 切面,一样的思路。不过,mysql 的切入层面是数据库。通过触发器,我们可以定义哪些表,在执行了如 增删改 的操作,以及操作的时间节点,并且在操作触发后,需要有什么样的动作


一些比较经典的案例:


  1. 我们可以用触发对相关的数据录入做数据库层面的校验

  2. 当数据记录删除时,我们需要将他转移到数据备份表,保证当前活动表的数据量在相对较少的层面

  3. 我最近经历过的,数据库表记录变更留痕。以触发器的方式实现,可以避免代码层面的改动 (① 是改了代码需要重新发布;② 是改了,万一涉及的地方太多,没改到位)

删除触发器

DROP TRIGGER [IF EXISTS] [schema_name.]trigger_name
复制代码


[if exists] 是可选的,表示会删除指定的并且存在的触发器;要是不存在,也不会报错


[schema_name.] 触发器所在的 DB 库,如果不指定,就会删除当前库下的这个触发器

查看触发器

我们最习惯的写法就是,第一步先删除目标触发器,第二步就是创建自己需要的触发器,sql 如下:


drop trigger if exists myTrigger;create trigger myTrigger......
复制代码


这种操作习惯是出于,在触发器刚创建的那段时间,我们会非常频繁的 删除 - 创建,重复创建会提示命名被占用,因此就有了上述代码的雏形


但是,如果我们上来就这么操作,或许会不小心删除已经在运行的同名触发器!!


因此,在触发器创建之前,我们需要确认命名是否被占用,有两个方法:


一、查看当前 DB 中的全部触发器


show TRIGGERS
复制代码



二、从系统内置 DB 的 triggers 表中查询全部触发器


SELECT *from information_schema.`TRIGGERS`
复制代码



我们可以通过 where 增加对字段 trigger_name 的条件过滤




在确认命名可用后,那就可以开始考虑触发器该怎么写了

创建触发器

创建触发器的标准语法


CREATE    [DEFINER = user]    TRIGGER trigger_name    trigger_time trigger_event    ON tbl_name FOR EACH ROW    [trigger_order]    trigger_body
复制代码


[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 操作触发器创建模版:


CREATE    TRIGGER trigger_name    trigger_time trigger_event    ON tbl_name FOR EACH ROW    [trigger_order]    begin    delimiter //    -- 你的操作逻辑1    -- 2    -- 。。    //    end
复制代码


发布于: 刚刚阅读数: 5
用户头像

还未添加个人签名 2022.07.13 加入

还未添加个人简介

评论

发布
暂无评论
Mysql 温故知新系列「触发器详解」_MySQL_安逸的咸鱼_InfoQ写作社区