13.1.20 CREATE TRIGGER 语句

CREATE
    [DEFINER = user]
    TRIGGER 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

该语句创建一个新的触发器。触发器是与 table 相关联的命名数据库对象,并在 table 发生特定事件时激活。触发器与名为* tbl_name *的 table 相关联,该 table 必须引用一个永久 table。您不能将触发器与TEMPORARYtable 或视图相关联。

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

本节介绍CREATE TRIGGER语法。有关其他讨论,请参见第 23.3.1 节“触发器语法和示例”

CREATE TRIGGER要求具有与触发器关联的 table 的TRIGGER特权。如果存在DEFINER子句,则所需的特权取决于* user *值,如第 23.6 节“存储的对象访问控制”中所述。如果启用了二进制日志记录,则CREATE TRIGGER可能需要SUPER特权,如第 23.7 节“存储的程序二进制日志”中所述。

DEFINER子句确定在触发器激活时检查访问权限时要使用的安全上下文,如本节后面所述。

  • trigger_time *是触发动作时间。可以是BEFOREAFTER来指示触发器在要修改的每一行之前或之后激活。

基本的列值检查在激活触发器之前进行,因此您不能使用BEFORE触发器将不适用于该列类型的值转换为有效值。

  • trigger_event table 示激活触发器的操作类型。这些 trigger_event *值是允许的:
  • trigger_event *并不 table 示激活触发器的 SQL 语句的 Literals 类型,而是 table 示 table 操作的类型。例如,INSERT触发器不仅为INSERT语句激活,而且为LOAD DATA语句激活,因为这两个语句都将行插入 table 中。

一个可能令人困惑的例子是INSERT INTO ... ON DUPLICATE KEY UPDATE ...语法:每行都会激活BEFORE INSERT触发器,然后是AFTER INSERT触发器或BEFORE UPDATEAFTER UPDATE触发器,这取决于该行是否有重复的键。

Note

级联的外键操作不会激活触发器。

可以为给定的 table 定义具有相同触发事件和动作时间的多个触发。例如,一个 table 可以有两个BEFORE UPDATE触发器。默认情况下,具有相同触发事件和动作时间的触发器将按照其创建 Sequences 进行激活。要影响触发器的 Sequences,请指定* trigger_order *子句以指示FOLLOWSPRECEDES以及现有触发器的名称,该触发器也具有相同的触发器事件和动作时间。使用FOLLOWS,新触发器将在现有触发器之后激活。使用PRECEDES,新触发器将在现有触发器之前激活。

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

触发器不能使用NEW.col_nameOLD.col_name来引用生成的列。有关生成的列的信息,请参见第 13.1.18.7 节“创建 table 和生成的列”

MySQL 会在创建触发器时存储有效的sql_mode系统变量设置,并始终在有效的情况下执行触发器主体,而与触发器开始执行时当前的服务器 SQL 模式无关。

DEFINER子句指定在触发器激活时检查访问权限时要使用的 MySQL 帐户。如果存在DEFINER子句,则* user 值应为指定为'user_name'@'host_name'CURRENT_USERCURRENT_USER()的 MySQL 帐户。允许的 user *值取决于您所拥有的特权,如第 23.6 节“存储的对象访问控制”中所述。另请参阅该部分以获取有关触发器安全性的其他信息。

如果省略DEFINER子句,则默认定义器是执行CREATE TRIGGER语句的用户。这与显式指定DEFINER = CURRENT_USER相同。

当检查触发特权时,MySQL 将DEFINER用户考虑在内:

  • CREATE TRIGGER时间,发出该语句的用户必须具有TRIGGER特权。

  • 在触发器激活时,将针对DEFINER用户检查特权。该用户必须具有以下特权:

  • 主题 table 的TRIGGER特权。

    • 如果使用触发器主体中的OLD.col_nameNEW.col_name引用 table 列,则主题 table 具有SELECT特权。

    • 如果 table 列是触发器主体中SET NEW.col_name = value分配的目标,则主题 table 具有UPDATE特权。

    • 触发器执行的语句通常需要任何其他特权。

在触发器主体中,CURRENT_USER函数返回用于在触发器激活时检查特权的帐户。这是DEFINER用户,而不是其操作导致触发器被激活的用户。有关触发器内用户审核的信息,请参见第 6.2.18 节“基于 SQL 的帐户活动审核”

如果您使用LOCK TABLES锁定具有触发器的 table,则该触发器中使用的 table 也会被锁定,如锁定 table 和触发器中所述。

有关触发器使用的其他讨论,请参见第 23.3.1 节“触发器语法和示例”