ITPub博客

首页 > 数据库 > > 23.3 使用触发器

23.3 使用触发器

作者:飘絮絮絮丶 时间:2020-05-11 11:10:19 0 删除 编辑

参考官方文档:

23.3 Using Triggers​dev.mysql.com



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


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


重要


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


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


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


23.3.1 触发器的语法和例子


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


mysql>CREATETABLEaccount(acct_numINT,amountDECIMAL(10,2));

Query OK, 0 rows affected (0.03 sec)

mysql>CREATETRIGGERins_sumBEFOREINSERTONaccountFOREACHROWSET@sum=@sum+NEW.amount;

Query OK, 0 rows affected (0.01 sec)


CREATE TRIGGER语句创建一个名为ins_sum的触发器,该触发器与帐户表关联。 它还包括指定触发器操作时间,触发事件以及触发器激活时要执行的操作的子句:



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


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


mysql> SET @sum = 0;

mysql>INSERTINTOaccountVALUES(137,14.98),(141,1937.50),(97,-100.00);

mysql>SELECT@sumAS'Total amount inserted';

+-----------------------+

| Total amount inserted |

+-----------------------+

| 1852.48 |

+-----------------------+

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


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

mysql>DROPTRIGGERtest.ins_sum;


如果删除表,则表的任何触发器也将被删除。


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


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



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


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


在BEFORE触发器中,AUTO_INCREMENT列的NEW值为0,而不是实际插入新行时自动生成的序列号。


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


mysql> delimiter //

mysql>CREATETRIGGERupd_checkBEFORE

UPDATEONaccountFOREACHROW

BEGINIFNEW.amount<0THENSETNEW.amount=0;

ELSEIFNEW.amount>100THENSETNEW.amount=100;

ENDIF;

END;//

mysql>delimiter;


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


触发器在执行时其中执行的语句的内容有一些限制:


  • 触发器不能使用CALL语句来调用将数据返回给客户端或使用动态SQL的存储过程。 (允许存储过程通过OUT或INOUT参数将数据返回到触发器。)


  • 触发器不能使用显式或隐式开始或结束事务的语句,例如START TRANSACTION,COMMIT或ROLLBACK。 (允许ROLLBACK到SAVEPOINT,因为它不会结束事务。)。



MySQL在触发器执行期间处理错误,如下所示


  • 如果BEFORE触发器失败,则不执行相应行的操作。
  • 无论尝试是否成功,尝试插入或修改行都会激活BEFORE触发器。
  • 仅当任何BEFORE触发器和行操作成功执行时,才会执行AFTER触发器。
  • BEFORE或AFTER触发期间的错误导致导致触发器调用的整个语句失败。
  • 对于事务表,语句失败应导致回滚语句执行的所有更改。 触发器失败会导致语句失败,因此触发器失败也会导致回滚。 对于非事务性表,无法执行此类回滚,因此尽管语句失败,但在错误点之前执行的任何更改仍然有效。



23.3.2 触发器元数据


  • 查询INFORMATION_SCHEMA数据库的TRIGGERS表。
  • 使用SHOW CREATE TRIGGER语句。
  • 使用SHOW TRIGGERS语句。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69946831/viewspace-3148089/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-09-09

  • 博文量
    2646
  • 访问量
    42135