MySQL 触发器

2023-11-18

1.简介

触发器(Trigger)是与表关联的命名数据库对象,当表发生特定事件时激活。 触发器的一些用途是对要插入表中的值执行检查或对更新中涉及的值执行计算。

触发器也是一种存储程序,它和一个指定的表相关联,当该表中的数据发生变化(增加、更新、删除)时自动执行。 这些修改数据行的操作被称为触发器事件,例如 INSERT 或者 LOAD DATA 等插入数据的语句可以激活插入触发器。触发器可以设置为在触发事件之前或之后激活。 例如,您可以在插入表中的每行之前或更新每行之后激活触发器。

通过编写触发器,你可以实现数据的验证、记录变更、数据同步等操作。触发器是数据库中强大的功能之一,可以在保持数据完整性和一致性方面发挥重要作用。

2.行级与语句级触发器

按照 SQL 标准,触发器可以分为行级触发器(row-level trigger)和语句级触发器( statement-level trigger)。行级触发器对于修改的每一行数据都会激活一次,如果一个语句插入了 100 行数据,将会调用触发器 100 次;语句级触发器针对每个语句激活一次,一个插入 100 行数据的语句只会调用一次触发器。

MySQL 只支持行级触发器,不支持预语句级触发器。

3.触发时机

在 MySQL 中,只有执行增加、更新和删除操作时才能触发触发器的执行。

不同事件可以激活不同类型的触发器。

  • INSERT 事件触发器用于插入数据的操作,包括 INSERT、LOAD DATA、REPLACE 语句等。
  • UPDATE 事件触发器用于更新操作,例如 UPDATE 语句。
  • DELETE 事件触发器用于删除操作,例如 DELETE 和 REPLACE 语句等。

DROP TABLE 和 TRUNCATE TABLE 语句不会激活删除触发器。

另外,MySQL 触发器可以在触发事件之前或者之后执行,分别称为 BEFORE 触发器和 AFTER 触发器。这两种触发时机可以和不同的触发事件进行组合,例如 BEFORE INSERT 触发器或者 AFTER UPDATE 触发器。

4.触发器优缺点

MySQL 触发器的优点包括:

  • 记录并审核用户对表中数据的修改操作,实现审计功能。
  • 实现比检查约束更复杂的完整性约束,例如禁止非业务时间的数据操作。
  • 实现某种业务逻辑,例如增加或删除员工时自动更新部门中的人数。
  • 实时同步表中的数据。

虽然触发器功能强大,但是它也存在一些缺点:

  • 触发器会增加数据库结构的复杂度,而且触发器对应用程序不可见,难以调试。
  • 触发器需要占用更多的数据库服务器资源,尽量使用数据库提供的非空、唯一、检查约束等。
  • 触发器不能接收参数,只能基于当前的触发对象进行操作。

针对特殊场景使用触发器可以带来一定的便利性,但不要过渡依赖触发器,避免造成数据库的性能下降和维护困难。接下来我们介绍触发器的管理操作。

5.创建触发器

语法

MySQL 使用 CREATE TRIGGRT 语句创建触发器。

CREATE
    [DEFINER = user]
    TRIGGER [IF NOT EXISTS] trigger_name
    trigger_time trigger_event
    ON tbl_name FOR EACH ROW
    [trigger_order]
    trigger_body

trigger_time: { BEFORE | AFTER }

trigger_event: { INSERT | UPDATE | DELETE }

trigger_order: { FOLLOWS | PRECEDES } other_trigger_name

DEFINER 子句是可选的,用于指定触发器的创建者或所有者。它定义了谁有权利执行和管理这个触发器。具体来说,DEFINER 子句决定了触发器在哪个数据库用户的权限下运行。

如果存在 DEFINER 子句,则用户值应为指定为 ‘user_name’@‘host_name’、CURRENT_USER 或 CURRENT_USER() 的 MySQL 帐户,允许的用户值取决于您拥有的权限。缺省为当前执行创建操作的用户。

trigger_name 是触发器的名称。

trigger_time 指定触发器的触发时机,在触发事件之前(BEFORE )还是之后(AFTER)执行。

trigger_event 用于定义触发事件的类型 INSERT、UPDATE 还是 DELETE。

table_name 是触发器关联的表名,不能是临时表或者视图。

FOR EACH ROW 表明这是一个行级触发器。

trigger_order 是可选的,用于指定与其他具有相同触发事件和动作时间的现有触发器的先后触发关系。如果没有指定任何选项,默认情况下按照触发器的创建顺序执行。

trigger_body 是触发器执行的具体语句。

在触发器主体中,您可以通过使用别名 OLD 和 NEW 来引用主题表(与触发器关联的表)中的列。OLD.col_name 引用更新或删除之前的现有行的列。NEW.col_name 是指要插入的新行或更新后的现有行的列。

示例

下面是一个简单的示例,它将触发器与表关联起来,以激活 INSERT 操作。 触发器充当累加器,对插入表的某一列中的值求和。

mysql> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2));
Query OK, 0 rows affected (0.03 sec)

mysql> CREATE TRIGGER ins_sum BEFORE INSERT ON account
       FOR EACH ROW SET @sum = @sum + NEW.amount;
Query OK, 0 rows affected (0.01 sec)

上面创建了一个名为 ins_sum 的触发器,该触发器与 ins_sum 表关联。 它还指定了触发器动作时间(BEFORE)、触发事件(INSERT)以及触发器激活时执行的操作的子句。

要使用触发器,请将累加器变量设置为零,执行 INSERT 语句,然后查看变量的值。

mysql> SET @sum = 0;
mysql> INSERT INTO account VALUES(137,14.98),(141,1937.50),(97,-100.00);
mysql> SELECT @sum AS 'Total amount inserted';
+-----------------------+
| Total amount inserted |
+-----------------------+
|               1852.48 |
+-----------------------+

6.查看触发器

使用 SHOW TRIGGERS 语句可以查看数据库中的触发器列表。

SHOW TRIGGERS
    [{FROM | IN} db_name]
    [LIKE 'pattern' | WHERE expr]

db_name 用于查看指定数据库中的触发器,默认为当前数据库。

LIKE 子句(如果存在)指示要匹配的表名称(不是触发器名称),显示这些表的触发器。

可以使用 WHERE 子句来使用更通用的条件筛选。

比如查看上面创建的触发器 ins_sum。

mysql> SHOW TRIGGERS LIKE 'acc%'\G
*************************** 1. row ***************************
             Trigger: ins_sum
               Event: INSERT
               Table: account
           Statement: SET @sum = @sum + NEW.amount
              Timing: BEFORE
             Created: 2023-08-24 10:10:12.61
            sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,
                      NO_ZERO_IN_DATE,NO_ZERO_DATE,
                      ERROR_FOR_DIVISION_BY_ZERO,
                      NO_ENGINE_SUBSTITUTION
             Definer: me@localhost
character_set_client: utf8mb4
collation_connection: utf8mb4_0900_ai_ci
  Database Collation: utf8mb4_0900_ai_ci

另外,MySQL 系统表 INFORMATION_SCHEMA.TRIGGERS 中包含了更详细的触发器信息。

如果想要获取创建某个触发器的 DDL 语句,可以 SHOW CREATE TRIGGER 语句。

mysql> SHOW CREATE TRIGGER ins_sum\G
*************************** 1. row ***************************
               Trigger: ins_sum
              sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,
                        NO_ZERO_IN_DATE,NO_ZERO_DATE,
                        ERROR_FOR_DIVISION_BY_ZERO,
                        NO_ENGINE_SUBSTITUTION
SQL Original Statement: CREATE DEFINER=`me`@`localhost` TRIGGER `ins_sum`
                        BEFORE INSERT ON `account`
                        FOR EACH ROW SET @sum = @sum + NEW.amount
  character_set_client: utf8mb4
  collation_connection: utf8mb4_0900_ai_ci
    Database Collation: utf8mb4_0900_ai_ci
               Created: 2023-08-24 10:10:12.61

7.删除触发器

MySQL 没有提供修改触发器的语句,只能通过 DROP TRIGGER 语句删除并再次创建触发器。

DROP TRIGGER [IF EXISTS] [schema_name.]trigger_name

该语句会删除一个触发器。 模式(数据库)名称是可选的。 如果省略模式,则会在当前的数据库中查找并删除触发器。DROP TRIGGER 需要与触发器关联的表的 TRIGGER 权限。

IF EXISTS 可以避免触发器 tri_audit_salary 不存在时产生错误。

例如,以下语句可以用于删除触发器 ins_sum。

DROP TRIGGER IF EXISTS ins_sum;

参考文献

MySQL 8.0 Reference Manual :: 25 Stored Objects
MySQL 8.0 Reference Manual :: 25.3 Using Triggers
13.1.22 CREATE TRIGGER Statement
13.7.7.40 SHOW TRIGGERS Statement
13.7.7.11 SHOW CREATE TRIGGER Statement
13.1.34 DROP TRIGGER Statement
《MySQL 入门教程》第 33 篇 触发器

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL 触发器 的相关文章

随机推荐

  • 使用RPC对某者web端骑行数据进行爬取

    使用RPC技术hook web端JS 骑行app某者web端爬虫 2022 2 1 获取轨迹ID 通过更改年月 可以发现获取每个月轨迹ID 的方式 这个非常简单 只需要拷贝请求头headers就可以直接获取 2 获取轨迹详情 可以发现三个请
  • 主键和唯一索引

    主键和唯一索引 主键 主关键字 primary key 是表中的一个或多个字段 它的值用于唯一地标识表中的某一条记录 唯一索引 一种索引 不允许具有索引值相同的行 从而禁止重复的索引或键值 系统在创建该索引时检查是否有重复的键值 并在每次使
  • 【生信原理】初探芯片表达谱分析

    初探芯片表达谱分析 文章目录 初探芯片表达谱分析 实验目的 实验内容 实验题目 实验过程 数据的获取 解压与读取 数据预处理 背景纠正 标准化和探针信号汇总等 数据过滤 探针过滤 探针注释 添加基因注释信息 limma差异分析 差异表达基因
  • DM备份数据或者还原备份管道连接超时问题。

    问题 第一 必须以dmdba的用户执行 第二 启动DmAPService 服务 启动失败了 删掉管道文件再启动 启动成功 再执行就OK了
  • 【华为OD机试 2023 B卷

    在线OJ 已购买本专栏用户 请私信博主开通账号 在线刷题 运行出现 Runtime Error 0Aborted 请忽略 华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一
  • linux C程序中获取shell脚本输出

    linux C程序中获取shell脚本输出 分类 linux C开发 2008 06 16 22 44 820人阅读 评论 0 收藏 举报 shell 脚本 linux c system cmd 目录 linux C程序中获取shell脚本
  • 【业务功能篇78】微服务-前端后端校验- 统一异常处理-JSR-303-validation注解

    5 前端校验 我们在前端提交的表单数据 我们也是需要对提交的数据做相关的校验的 Form 组件提供了表单验证的功能 只需要通过 rules 属性传入约定的验证规则 并将 Form Item 的 prop 属性设置为需校验的字段名即可 校验的
  • socket局域网测试是可以的,但是在腾讯云/阿里云上报错“[Errno 99] Cannot assign requested address”

    现在云服务器一般都是只有内网地址 通过公网IP访问时 由云服务器运营商映射到内部网络的 因此 如果部署socket服务时 配置server ip应该是内网IP 解决方法 服务端的ip填服务器的私网ip 客户端填公网ip
  • 【Django】Python+Django 图文教程

    Django新手图文教程 本文面向 有python基础 刚接触web框架的初学者 环境 windows7 python3 5 1 pycharm专业版 Django 1 10版 pip3 一 Django简介 百度百科 开放源代码的Web应
  • 字节跳动测试岗面试挂在2面,复盘后,我总结了失败原因,决定再战一次...

    先说下我基本情况 本科不是计算机专业 现在是学通信 然后做图像处理 可能面试官看我不是科班出身没有问太多计算机相关的问题 因为第一次找工作 字节的游戏专场又是最早开始的 就投递了 投递的是游戏测试开发岗 字节是自己投的第一家公司 也是第一家
  • 【NLP】通过迁移学习加速 AI 模型训练

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • Java机试题

    整理自Java经典编程50题 面试笔试机试 腾讯云开发者社区 腾讯云 1 回文数 public static boolean palindrom Integer integer String str1 String valueOf inte
  • Kibana在Centos上开机启动

    1 需要下载kibana 去官网下 2 解压到自己指定的目录下 我是放到了 usr local下 3 执行 vi usr lib systemd system kibana service 插入下面内容 Unit Description k
  • /dev/zero和/dev/null的区别

    可以通过使用dd if dev zero of archive test dbf bs 8k count 1000000 来测试磁盘的纯写入性能 使用dd if file of dev null 来测试磁盘的纯读取性能 使用dd if fi
  • 紫光同创 FPGA 开发跳坑指南(三)—— 联合 Modelsim 仿真

    Modelsim 是 FPGA 开发中重要的 EDA 设计仿真工具 主要用于验证数字电路设计是否正确 紫光 Pango Design Suite 开发套件支持联合 Modelsim 仿真 这里作简要的介绍 添加仿真库 方法一 打开 Pang
  • 实现mint操作(参考pancake)

    区块链发展越来越好 nft已经火了很久 今天写一下如何用js web3js 调用合约 实现mint nft 简单的调用 引入一些依赖 根据需要 有一些是其他功能的 import useActiveWeb3React from web3 ho
  • mysql read loop_mysql数据库游标的使用

    Mysql在5 0版本支持在存储过程中使用游标 游标声明必须出现在处理程序声明变量和条件的声明后 游标的使用如下 CREATE PROCEDURE curdemo BEGIN DECLARE done INT DEFAULT FALSE D
  • hive数据恢复

    truncate删除hive的表能恢复吗 0 jdbc hive2 localhost 10014 default gt create table test2 id int name string row format delimited
  • 在SpringBoot中利用nacos对数据源进行动态刷新

    一 重写DruidAbstractDataSource类 这里为什么要重写这个类 因为DruidDataSource数据源在初始化后 就不允许再重新设置数据库的url和userName 注意 类所在的包名必须为 com alibaba dr
  • MySQL 触发器

    文章目录 1 简介 2 行级与语句级触发器 3 触发时机 4 触发器优缺点 5 创建触发器 语法 示例 6 查看触发器 7 删除触发器 参考文献 1 简介 触发器 Trigger 是与表关联的命名数据库对象 当表发生特定事件时激活 触发器的