MySQL学习——触发器的语法和示例

触发器(trigger)是数据库中的一个重要概念。触发器是与表相关联的命名数据库对象,当表上发生特定事件时,触发器会被激活。

触发器定义为在语句插入、更新或删除关联表中的行时激活。这些行操作是触发事件。例如,可以通过INSERT或LOAD DATA语句插入行,并为每个插入的行激活插入触发器。触发器可以设置为在触发事件之前或之后激活。例如,可以在表中插入的每一行之前或更新的每一行都激活触发器。

MySQL触发器仅针对SQL语句对表所做的更改而激活。这包括对作为可更新视图基础的基表的更改。对于不将SQL语句传输到MySQL Server的API对表所做的更改,触发器不会激活。这意味着触发器不会被使用NDB API进行的更新激活。

INFORMATION_SCHEMA或performance_SCHEMA表中的更改不会激活触发器。这些表实际上是视图,不允许在视图上使用触发器。

以下部分描述了创建和删除触发器的语法,显示了一些如何使用触发器的示例,并指示了如何获取触发器元数据。

这里有一个简单的例子,它将触发器与表相关联,以激活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)

CREATE TRIGGER语句创建一个名为ins_sum的触发器,该触发器与account表相关联。它还包括指定触发器动作时间、触发事件以及触发器激活时要做什么的条款:

  1. 关键字BEFORE表示触发器动作时间。在这种情况下,触发器会在每一行插入表之前激活。这里允许的另一个关键字是AFTER。
  2. 关键字INSERT表示触发事件;即激活触发器的操作类型。在该示例中,INSERT操作会导致触发器激活。您还可以为DELETE和UPDATE操作创建触发器。
  3. FOR EACH ROW后面的语句定义了触发器主体;也就是说,每次触发器激活时要执行的语句,对于受触发事件影响的每一行都会发生一次。在该示例中,触发器主体是一个简单的SET,它将插入金额列的值累积到用户变量中。该语句将该列称为NEW.amount,意思是“要插入新行的金额列的值”

要使用触发器,请将accumulator变量设置为零,执行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 | +-----------------------+

在这种情况下,INSERT语句执行后@sum的值为14.98+1937.50-100,或1852.48。

要销毁触发器,请使用DROP trigger语句。如果触发器不在默认架构中,则必须指定架构名称:

mysql> DROP TRIGGER test.ins_sum;

如果您删除了一个表,那么该表的所有触发器也会被删除。

触发器名称存在于架构命名空间中,这意味着所有触发器在架构中都必须具有唯一的名称。不同架构中的触发器可以具有相同的名称。

从MySQL 5.7.2开始,可以为给定的表定义多个具有相同触发事件和操作时间的触发器。例如,一个表可以有两个BEFORE UPDATE触发器。默认情况下,具有相同触发事件和操作时间的触发器按创建顺序激活。若要影响触发器顺序,请在FOR EACH ROW后面指定一个子句,该子句指示FOLLOWS或PRECEDES以及具有相同触发器事件和操作时间的现有触发器的名称。使用FOLLOWS,新触发器在现有触发器之后激活。使用PRECEDES,新触发器会在现有触发器之前激活。

例如,以下触发器定义为帐户表定义了另一个BEFORE INSERT触发器:

mysql> CREATE TRIGGER ins_transaction BEFORE INSERT ON account FOR EACH ROW PRECEDES ins_sumSET @deposits = @deposits + IF(NEW.amount>0,NEW.amount,0), @withdrawals = @withdrawals + IF(NEW.amount<0,-NEW.amount,0); Query OK, 0 rows affected (0.01 sec)

触发器ins_transaction类似于ins_sum,但分别累积存储提取。它有一个PRECEDS子句,使它在ins_sum之前激活;如果没有该子句,它将在inssum之后激活,因为它是在inssums之后创建的。

在MySQL 5.7.2之前,给定表不能有多个触发器具有相同的触发事件和操作时间。例如,一个表不能有两个BEFORE UPDATE触发器。要解决此问题,可以使用BEGIN…END定义一个执行多个语句的触发器。。。在FOR EACH ROW之后结束复合语句构造。

在触发器主体中,OLD和NEW关键字使您能够访问受触发器影响的行中的列。OLD和NEW是触发器的MySQL扩展;它们不区分大小写。

在INSERT触发器中,只能使用NEW.col_name;没有旧。在DELETE触发器中,只能使用OLD.col_name;没有新行。在UPDATE触发器中,可以使用OLD.col_name引用行更新前的列,使用NEW.col_name引用行更新后的列。

以OLD命名的列是只读的。您可以引用它(如果您拥有SELECT特权),但不能修改它。如果您拥有它的SELECT特权,您可以引用以NEW命名的列。在BEFORE触发器中,如果您拥有UPDATE特权,您也可以使用SET NEW.col_name=value更改它的值。这意味着您可以使用触发器修改要插入新行或用于更新行的值。(这样的SET语句在AFTER触发器中无效,因为行更改已经发生。在BEFORE触发器中,AUTO_INCREMENT列的NEW值为0,而不是实际插入新行时自动生成的序列号。

通过使用BEGIN。。。END构造,您可以定义一个执行多个语句的触发器。在BEGIN块中,您还可以使用存储例程中允许的其他语法,如条件语句和循环。然而,正如存储例程一样,如果您使用mysql程序定义一个执行多条语句的触发器,则有必要重新定义mysql语句分隔符,以便使用;触发器定义中的语句分隔符。以下示例说明了这些要点。它定义了一个UPDATE触发器,用于检查用于更新每一行的新值,并将该值修改为在0到100的范围内。这必须是BEFORE触发器,因为在使用该值更新行之前必须检查该值:

mysql> delimiter // mysql> CREATE TRIGGER upd_check BEFORE UPDATE ON account FOR EACH ROW BEGIN IF NEW.amount < 0 THEN SET NEW.amount = 0; ELSEIF NEW.amount > 100 THEN SET NEW.amount = 100; END IF; END;// mysql> delimiter ;

可以更容易地单独定义存储过程,然后使用简单的CALL语句从触发器调用它。如果您想在多个触发器中执行相同的代码,这也是有利的。

触发器在激活时执行的语句中可能出现的内容存在限制:

  1. 触发器不能使用CALL语句来调用向客户端返回数据或使用动态SQL的存储过程。(允许存储过程通过OUT或INOUT参数将数据返回到触发器)
  2. 触发器不能使用显式或隐式开始或结束事务的语句,如START transaction、COMMIT或ROLLBACK。(允许ROLLBACK到SAVEPOINT,因为它不会结束事务)。

MySQL处理触发器执行过程中的错误如下:

  1. 如果BEFORE触发器失败,则不执行对相应行的操作。
  2. BEFORE触发器由插入或修改行的尝试激活,无论该尝试随后是否成功。
  3. 只有当任何BEFORE触发器和行操作成功执行时,才执行AFTER触发器。
  4. BEFORE或AFTER触发器期间的错误会导致导致触发器调用的整个语句失败。
  5. 对于事务表,语句的失败应该会导致该语句执行的所有更改的回滚。触发器失败会导致语句失败,因此触发器失败也会导致回滚。对于非事务表,不能进行这样的回滚,因此,尽管语句失败,但在错误点之前执行的任何更改仍然有效。

触发器可以包含按名称对表的直接引用,例如本例中显示的名为testref的触发器:

CREATE TABLE test1(a1 INT); CREATE TABLE test2(a2 INT); CREATE TABLE test3(a3 INT NOT NULL AUTO_INCREMENT PRIMARY KEY); CREATE TABLE test4( a4 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b4 INT DEFAULT 0 ); delimiter | CREATE TRIGGER testref BEFORE INSERT ON test1FOR EACH ROW BEGIN INSERT INTO test2 SET a2 = NEW.a1; DELETE FROM test3 WHERE a3 = NEW.a1; UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1; END; | delimiter ; INSERT INTO test3 (a3) VALUES (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL); INSERT INTO test4 (a4) VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0), (0);

假设您将以下值插入到表test1中,如下所示:

mysql> INSERT INTO test1 VALUES , (3), (1), (7), (1), (8), (4), (4); 
Query OK, 8 rows affected (0.01 sec)Records: 8 Duplicates: 0 Warnings: 0

因此,这四个表包含以下数据:

mysql> SELECT * FROM test1;
+------+
| a1   |
+------+
|    1 |
|    3 |
|    1 |
|    7 |
|    1 |
|    8 |
|    4 |
|    4 |
+------+
8 rows in set (0.00 sec)mysql> SELECT * FROM test2;
+------+
| a2   |
+------+
|    1 |
|    3 |
|    1 |
|    7 |
|    1 |
|    8 |
|    4 |
|    4 |
+------+
8 rows in set (0.00 sec)mysql> SELECT * FROM test3;
+----+
| a3 |
+----+
|  2 |
|  5 |
|  6 |
|  9 |
| 10 |
+----+
5 rows in set (0.00 sec)mysql> SELECT * FROM test4;
+----+------+
| a4 | b4   |
+----+------+
|  1 |    3 |
|  2 |    0 |
|  3 |    1 |
|  4 |    2 |
|  5 |    0 |
|  6 |    0 |
|  7 |    1 |
|  8 |    1 |
|  9 |    0 |
| 10 |    0 |
+----+------+
10 rows in set (0.00 sec)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/848060.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot前后端简单集成MinIo开发

Spring Boot前后端简单集成MinIo开发 源码地址重要配置和代码MinIO配置核心代码 最终效果 源码地址 minioStudy 重要配置和代码 MinIO配置 pom文件引入依赖 <!-- minio --> <dependency><groupId>io.minio</groupId><artifactId>minio</ar…

C++中常见的初始化类型

目录 摘要 1. 默认初始化&#xff08;Default Initialization&#xff09; 2. 值初始化&#xff08;Value Initialization&#xff09; 3. 直接初始化&#xff08;Direct Initialization&#xff09; 4. 拷贝初始化&#xff08;Copy Initialization&#xff09; 5. 列表初…

【C语言之排序】-------六大排序

作者主页&#xff1a;作者主页 数据结构专栏&#xff1a;数据结构 创作时间 &#xff1a;2024年5月18日 前言&#xff1a; 今天我们就给大家带来几种排序的讲解&#xff0c;包括冒泡排序&#xff0c;插入排序&#xff0c;希尔排序&#xff0c;选择排序&#xff0c;堆排序&…

揭秘成都跃享未来教育:安全靠谱,打造教育新未来?

在当今这个信息爆炸的时代&#xff0c;教育行业的变革日新月异&#xff0c;各种教育机构如雨后春笋般涌现。其中&#xff0c;成都跃享未来教育咨询有限公司以其独特的教育理念和创新的教学模式&#xff0c;吸引了众多家长和学生的目光。那么&#xff0c;这家公司到底安不安全&a…

湖南(广告效果测评)源点调研 广告对消费者行为的影响效果

湖南&#xff08;市场调研&#xff09;源点咨询认为&#xff1a;调查在市场中是一个万万不可忽视的环节。 产品在问世之前要认真地调查&#xff0c;广告在投放之前也要认真地调查。由于广告实质是商家和消费者沟通的一个过程&#xff0c;所以在广告投放前&#xff0c;商家就应…

【AOP】ASP.NET Core中各种Filter(拦截器)

在ASP.NET Core中&#xff0c;Filter&#xff08;过滤器&#xff09;是一种强大的机制&#xff0c;允许你在请求处理管道中的特定阶段运行代码。这些过滤器提供了在请求的不同阶段执行逻辑的能力&#xff0c;比如授权、日志记录、异常处理等。ASP.NET Core 提供了多种类型的过滤…

Spark中把所有的列转换成string操作

##事例代码 from pyspark.sql.functions import col df.select(*[col(c).cast("string").alias(c) for c in df.columns]) 这段代码使用了Spark SQL中的select函数和列表推导式来选择DataFrame中的所有列&#xff0c;并将它们的数据类型转换为字符串类型。 select(*…

案例分享:需求管理工具Jama Connect助力某财富100强的半导体巨头缩短项目周期、降低开发成本,提高需求复用率及可追溯性

案例分享&#xff1a;作为全球领导者&#xff0c;该财富100强公司以扩大其在移动技术领域的领导力和影响力为使命&#xff0c;该领域是其行业中增长最快的细分市场。公司有超过2,100名工程师、设计师和利益相关者通过使用Jama Connect加速产品开发。 成果概述&#xff1a; •…

数据新生态:Web3如何重新定义个人数据权利

随着数字化时代的不断深入&#xff0c;个人数据已经成为了现代社会中最宝贵的资源之一。然而&#xff0c;传统互联网时代下&#xff0c;个人数据往往被大型科技公司垄断、滥用&#xff0c;个人数据权利常常受到侵犯。而随着Web3技术的崛起&#xff0c;人们开始期待一种全新的数…

zynq固化问题

zynq固化&#xff0c;sd卡如果没有用gpio那么这个地方不能选 另外ddr型号一定要选对&#xff0c;不同的容量不一样

即时设计工具对决:Figma、Sketch与XD的优劣比较

最近几年&#xff0c;UI 设计工具出现了许多后起之秀&#xff0c;其中有四款更具代表性的UI设计软件&#xff1a;Sketch、Adobe XD、Figma 和 即时设计&#xff0c;这四个设计软件都有自己的优势。如果合作对您的UI设计过程至关重要&#xff0c;那么Figma 和 即时设计 它应该是…

React中常见的面试题

本文是结合实践中和学习技术文章总结出来的笔记(个人使用),如有雷同纯属正常((✿◠‿◠)) 喜欢的话点个赞,谢谢! 1. 约束性组件与非约束性组件 1.1. 非约束性组件 非约束性组件其实就是不能控制状态的组件,比如: <input type"text" defaultValue"123&qu…

JSP与Servlet的区别

一、技术难点 本质与结构&#xff1a; JSP&#xff08;Java Server Pages&#xff09;在本质上可以被视为一种特殊的Servlet。但两者的创建方式和结构存在显著差异。Servlet完全由Java程序代码构成&#xff0c;擅长于流程控制和事务处理&#xff1b;而JSP则是由JSP容器执行页面…

python身份证ocr接口功能免费体验、身份证实名认证接口

翔云人工智能API开放平台提供身份证实名认证接口、身份证识别接口&#xff0c;两者的相结合可以实现身份证的快速、精准核验&#xff0c;当用户在进行身份证实名认证操作时&#xff0c;仅需上传身份证照片&#xff0c;证件识别接口即可快速、精准的对证件上的文字信息进行快速提…

腾讯云centos上安装docker

下面的操作是在root用户下操作的,如果非root用户在命令行前加上sudo 1. 系统及内核查看 操作系统&#xff1a;64位的CentOS 7或更新版本。内核版本&#xff1a;最低要求是3.10&#xff0c;推荐使用3.10或更高版本。 #查看内核版本 (base) [klfwjfweaVM-0-6-centos ~]$ uname…

rk3568定时器

前言 本文记录的是用rk3568开发板做定时器实验 1 定时器理论知识 1.1系统节拍 在linux的kernel路径中,输入: make ARCH=arm64 menuconfig // 在内核路径下执行打开配置界面 选中“Timer frequency”,打开以后如图所示: 从图 14.1.1.1 可以看出,可选的系统节拍率为 100…

对i += i -i和i = i - 1的理解

i i & -i迭代的结果是每次加i的最低次&#xff0c;直到加到与i最近的2的次幂。 比如&#xff0c;初始i是65&#xff0c;迭代的i的值如下&#xff1a;66&#xff0c; 68&#xff0c; 72&#xff0c; 80&#xff0c; 96&#xff0c;128&#xff0c; 256&#xff0c; 512 ..…

派派派森03

1.JSON数据 Python数据和Json数据的相互转化 # 导入json模块 import json#准备符合json格式要求的python数据 data [{"name": "老王", "age": 16}, {"name": "张三", "age": 20}]# 通过json.dump(data)方法把pyt…

配置无密码 sudo

配置无密码 sudo 需要谨慎操作&#xff0c;因为这会给你的系统安全带来一定的风险。在决定这么做之前&#xff0c;请确保你了解潜在的安全后果。以下是具体操作步骤&#xff1a; 步骤1: 使用 visudo 编辑 sudoers 文件 visudo 是一个命令行工具&#xff0c;它用于安全地编辑 …

黑龙江等保测评有哪些内容?

与等保1.0相比&#xff0c;新的等保2.0版本有了很大的变化&#xff0c;评估的内容、评估的标准也有了很大的差异。那么新版的《等保2.0》实施后&#xff0c;我们要测试什么&#xff1f; 等保测评首先是有十个大项&#xff0c;安全物理环境&#xff0c;安全区域边界&#xff0c;…