当前位置: 首页 > news >正文

MySQL:触发器(Trigger)

触发器(TRIGGER)是用户定义在关系表上的一类由事件驱动的特殊过程,在满足一定条件或达到一定阈值时会自动触发。可以进行更为复杂的检查和操作,具有更精细和更强大的数据控制能力。

Trigger 又叫做 事件-条件-动作(event- condition-action)规则。当特定的系统事件(如对一个表的增、删、改操作,事务的结束等)发生时,对规则的条件进行检查,如果条件成立则执行规则中的动作,否则不执行该动作。规则中的动作体可以很复杂,可以涉及其他表和其他数据库对象,通常是一段 SQL 存储过程

触发器是 MySQL 提供给程序员和数据分析员来保证数据完整性的一种方法,它是与表事件相关的特殊的存储过程,它的执行不是由程序调用,也不是 CALL 手动启动,而是由事件来触发,比如当对一个表进行操作(INSERTDELETEUPDATE)时就会激活它执行。

创建触发器

四要素

触发器创建的四个要素

  1. 监视地点 TABLE

  2. 监视事件 INSERT / UPDATE / DELETE

  3. 触发时间 AFTER / BEFORE

  4. 触发事件 INSERT / UPDATE / DELETE

只有表的创建者才可以在表上创建触发器,并且一个表上只能创建有限数量的触发器

语法

触发器的语法会根据具体的数据库管理系统而有所不同,下面是一般常用的触发器语法:

CREATE TRIGGER trigger_name
{BEFORE | AFTER} {INSERT | UPDATE | DELETE} ON table_name
[REFERNCEING NEW|OLD ROW|TABLE AS <var_name>]
FOR EACH [ROW | STATEMENT]
[WHEN condition]
BEGIN-- 触发器动作
END;
  • trigger_name 是触发器的名称,可以自定义。

  • {BEFORE | AFTER} 指定触发器在事件之前或之后执行。

    • AFTER 操作,是在执行了监视动作后,才会执行触发事件
    • BEFORE 操作,是在执行了监视动作前,会执行触发事件
  • {INSERT | UPDATE | DELETE} 指定触发器关联的事件类型。可以是INSERT、DELETE或UPDATE,也可以是它们的组合;同样也可以 UPDATE OF<列名,...,>,也即进一步指明哪些列变化时需要激活触发器

  • table_name 是触发器关联的表名。触发器只能定义在表上,不可在视图上。当基本表的数据发生变化时,将激活定义在该表上相应触发事件的触发器

  • REFERENCING 用来指定在触发器程序中使用的伪表或变量的名称,以便访问新插入、更新或删除的行。

    • OLD ROWNEW ROW: 分别代表被修改的行之前和之后的值。这些值可以通过使用 OLDNEW 前缀来访问到,例如在 AFTER UPDATE 触发器中,可以通过 OLD.column_nameNEW.column_name 分别访问修改之前和之后的列值。

    • OLD TABLENEW TABLE: 用于 DELETEINSERT 操作时访问伪表。Oracle 数据库中,这些伪表也称为临时表,它们具有与被触发的表相同的结构,但内容为更新前或更新后的值。在 MySQL 中使用 OLD TABLE 可以访问删除操作之前的表中的行,使用 NEW TABLE 可以访问插入操作之后的表中的行。

  • FOR EACH ROW 行级触发器:针对每一条记录执行触发器操作,当有大量行被修改时,FOR EACH ROW 触发器会执行相同数量次的操作。

  • FOR EACH STATEMENT 语句触发器:只执行一次触发体动作,即在触发器执行的条件下对整个 SQL 语句中受影响的所有行执行相同的操作。即使它会受到多行更新的影响,只会执行一次触发器操作

  • WHEN condition 是可选的,用于指定触发器执行的条件。如果省略WHEN 触发条件,则触发体动作在触发器激活后立即执行

  • BEGINEND 之间是触发器的动作,可以包含 SQL 语句或调用其他存储过程、函数等。

  • 触发体动作:触发动作体既可以是一个匿名 PL/SQL 过程块,也可以是对已创建存储过程的调用。

    • 如果是行级触发器,用户可以在过程体中使用 NEW 和 OLD 引用 UPDATE/INSERT 事件之后的新值和 UPDATE/DELETE 事件之前的旧值

    • 如果是语句级触发器,则不能在触发动作体中使用 NEW 或 OLD 进行引用。

    • 如果触发动作体执行失败,激活触发器的事件就会终止执行,触发器的目标表或触发器可能影响的其他对象不发生任何变化

示例

创建 INSERT 触发器
DELIMITER $$  
CREATE TRIGGER user_insert_trigger  
AFTER INSERT ON user  
FOR EACH ROW  
BEGIN  INSERT INTO user_operation(operation_type, operation_content)  VALUES('insert', CONCAT('添加后的数据:', NEW.name));  
END$$  
DELIMITER ;

这个触发器会在向 user 表插入数据后,向 user_operation 表中插入一条记录,记录操作类型为 INSERT 和插入的数据内容。

创建 UPDATE 触发器
DELIMITER $$  
CREATE TRIGGER user_update_trigger  
AFTER UPDATE ON user  
FOR EACH ROW  
BEGIN  INSERT INTO user_operation(operation_type, operation_content)  VALUES('update', CONCAT('修改前的数据: name:', OLD.name, ', age:', OLD.age));  INSERT INTO user_operation(operation_type, operation_content)  VALUES('update', CONCAT('修改后的数据: name:', NEW.name, ', age:', NEW.age));  
END$$  
DELIMITER ;

这个触发器会在 user 表的数据更新后,向 user_operation 表中插入两条记录,分别记录修改前后的数据。

激活触发器

每当触发事件发生时,该触发器会被激活

触发器的执行是由触发器事件激活的,如果同一个表上有多个触发器,激活时会按照以下顺序执行

  1. 执行该表上的 BEFORE 触发器
  2. 激活触发器的 SQL 语句
  3. 执行该表上的 AFTER 触发器

对于同一个表上的多个 BEFORE(AFTER) 触发器,遵循“谁先创建谁先执行”的原则,即按照触发器创建的时间先后顺序执行

删除触发器

删除触发器:

DROP TRIGGER [IF EXISTS] trigger_name;

触发器引用行变量

  1. 在触发目标上执行 INSERT 操作后会有一个新行,如果在触发事件中需要用到这个新行的变量,可以用 NEW 关键字表示。

  2. 在触发目标上执行 DELETE 操作后会有一个旧行,如果在触发事件中需要用到这个旧行的变量,可以用 OLD 关键字表示。

  3. 在触发目标上执行 UPDATE 操作后原记录是旧行,新记录是新行,可以使用 NEWOLD 关键字来分别操作。

NEW.column
OLD.column

触发器的作用

触发器在数据库管理中具有多种作用,包括但不限于:

  • 维护数据完整性:确保数据的正确性和一致性。

  • 自动化业务逻辑:在数据变更时自动执行复杂的业务逻辑。

  • 审计和日志记录:记录数据变更的历史,方便追踪和审计。

总结

MySQL 触发器是一种强大的数据库功能,能够在特定事件发生时自动执行预定义的 SQL 语句或程序块。通过合理使用触发器,可以极大地简化数据库的管理和维护工作,提高数据处理的效率和准确性。但需要注意的是,过度使用触发器可能会降低数据库的性能,因此在设计时应谨慎考虑。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C# 枚举 扩展方法
  • 【乐吾乐大屏可视化组态编辑器】数据绑定
  • Mac 连接 Synology NAS【Finder】
  • 【C语言篇】自定义类型:联合体和枚举详细介绍
  • 【django升级】django从2.2.6版本升级到3.2.25
  • 【ubuntu20.04 运行sudo apt-get upgrade报错】
  • 主机加固是什么?主机加固与产线工控安全关系
  • pg_stat_statements插件使用指南
  • NLP——文本预处理-新闻主题分类案例
  • MySQL——数据库的设计、事务、视图
  • GraalVM全面介绍:革新Java应用开发的利器
  • 【循环神经网络】案例:周杰伦歌词文本预测【训练+python代码】
  • 你真正了解低代码么?(国内低代码平台状况分析)
  • 华为od(D卷)最大N个数和最小N个数的和
  • 怎么用云手机进行TikTok矩阵运营
  • Bytom交易说明(账户管理模式)
  • CentOS 7 防火墙操作
  • express.js的介绍及使用
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • mysql 数据库四种事务隔离级别
  • nfs客户端进程变D,延伸linux的lock
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • Vue官网教程学习过程中值得记录的一些事情
  • 基于HAProxy的高性能缓存服务器nuster
  • 前端面试总结(at, md)
  • 浅谈Golang中select的用法
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 《码出高效》学习笔记与书中错误记录
  • 通过调用文摘列表API获取文摘
  • ​io --- 处理流的核心工具​
  • ​Python 3 新特性:类型注解
  • ‌前端列表展示1000条大量数据时,后端通常需要进行一定的处理。‌
  • ###STL(标准模板库)
  • #Z0458. 树的中心2
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • $GOPATH/go.mod exists but should not goland
  • $LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (1)虚拟机的安装与使用,linux系统安装
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (php伪随机数生成)[GWCTF 2019]枯燥的抽奖
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (七)Flink Watermark
  • (一)项目实践-利用Appdesigner制作目标跟踪仿真软件
  • ****Linux下Mysql的安装和配置
  • .mysql secret在哪_MySQL如何使用索引
  • .NET 设计模式初探
  • .NET 线程 Thread 进程 Process、线程池 pool、Invoke、begininvoke、异步回调
  • .net通用权限框架B/S (三)--MODEL层(2)
  • @RestController注解的使用
  • @zabbix数据库历史与趋势数据占用优化(mysql存储查询)
  • [23] 4K4D: Real-Time 4D View Synthesis at 4K Resolution
  • [AIGC] 广度优先搜索(Breadth-First Search,BFS)详解
  • [Android Studio 权威教程]断点调试和高级调试
  • [Asp.net mvc]国际化