Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  CREATE TRIGGER Statement

15.1.22 创建触发器语句

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

该语句创建一个新的触发器。触发器是与表相关联的命名数据库对象,在特定的事件发生时激活。触发器将与名称为 tbl_name 的表相关联,该表必须是永久表,不可以与临时表或视图相关联。

触发器名在模式命名空间中存在,意味着所有触发器在同一个模式下必须具有唯一的名称,而不同的模式下的触发器可以拥有相同的名称。

IF NOT EXISTS 防止在同一个模式下,如果已经存在同名触发器,则不发生错误。

本节描述了CREATE TRIGGER 语法。关于触发器语法和示例的详细讨论,请参见第27.3.1节,“触发器语法和示例”

CREATE TRIGGER 需要与触发器关联的表的TRIGGER特权。如果存在 DEFINER 子句,所需特权取决于 user 值,如第27.6节,“存储对象访问控制”中讨论。如果启用二进制日志记录,CREATE TRIGGER 可能需要SUPER 特权,如第27.7节,“存储程序二进制日志记录”中讨论。

DEFINER 子句确定在触发器激活时使用的安全上下文,后续部分将对其进行描述。

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

基本列值检查在触发器激活前发生,因此不能使用 BEFORE 触发器将值转换为合法值。

trigger_event 指示激活触发器的操作类型。这些 trigger_event 值允许:

"trigger_event" 不是表示激活触发器的 SQL 语句类型,而是表示表操作类型。例如,一个INSERT 触发器不仅激活于INSERT 语句,还激活于LOAD DATA 语句,因为这两个语句都将行插入到表中。

一个混淆的示例是 INSERT INTO ... ON DUPLICATE KEY UPDATE ... 语法:一个BEFORE INSERT 触发器激活于每一行,接着可能是AFTER INSERT 触发器或同时激活BEFORE UPDATEAFTER UPDATE 触发器,取决于该行是否存在重复键。

Note

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

可以为同一表定义多个触发器,它们具有相同的触发事件和动作时间。例如,可以有两个BEFORE UPDATE 触发器。默认情况下,具有相同触发事件和动作时间的触发器按照创建顺序激活。要影响触发器顺序,可以指定一个trigger_order 子句,该子句指示 FOLLOWSPRECEDES,并且指定一个具有相同触发事件和动作时间的现有触发器的名称。使用 FOLLOWS,新触发器激活于现有触发器后;使用 PRECEDES,新触发器激活于现有触发器前。

trigger_body 是触发器激活时执行的语句。要执行多个语句,使用BEGIN ... END复合语句结构。这也使您可以使用存储程序中允许的同样语句。见第15.6.1节,“BEGIN ... END复合语句”。有些语句在触发器中不可用;见第27.8节,“存储程序限制”

在触发器体内,您可以使用别名OLDNEW来引用主体表(与触发器关联的表)的列。OLD.col_name 引用一个将要更新或删除的行的列。NEW.col_name 引用要插入或已更新的行的列。

触发器不能使用NEW.col_name 或者使用OLD.col_name 来引用生成列。关于生成列的信息,见第15.1.20.8节,“CREATE TABLE 和生成列”

MySQL 在创建触发器时将存储sql_mode系统变量的设置,并总是以这个设置强制执行触发器体不管触发器开始执行时当前服务器 SQL 模式是什么

DEFINER take子句指定在触发器激活时间检查访问权限时使用的 MySQL 账户。如果存在DEFINER子句,user值应该是指定的 MySQL 账户,如'user_name'@'host_name',CURRENT_USERCURRENT_USER()。允许的user值取决于您所持有的权限,详见第27.6节,“存储对象访问控制”。另外,请查看该节关于触发器安全的其他信息。

如果省略DEFINER子句,缺省定义者是执行CREATE TRIGGER语句的用户。这等同于指定DEFINER = CURRENT_USER

MySQL 在检查触发器权限时考虑DEFINER用户如下:

  • CREATE TRIGGER时,执行该语句的用户必须拥有TRIGGER特权。

  • 在触发器激活时间,权限将被检查对DEFINER用户。这个用户必须拥有这些特权:

    • 触发器的主体表TRIGGER特权。

    • 如果在触发器体中使用SELECT语句来引用主体表的列,必须拥有主体表SELECT特权,以便使用OLD.col_nameNEW.col_name

    • 如果触发器体中有UPDATE语句,更新主体表的列,必须拥有主体表UPDATE特权,以便使用SET NEW.col_name = value赋值语句。

    • 触发器执行的语句所需的其他特权。

在触发器体内,CURRENT_USER 函数返回用于检查权限的账户,这是触发器激活时的账户,而不是导致触发器被激活的用户。关于在触发器中的用户审核,请参见第8.2.23节,“基于SQL的账户活动审核”

如果使用LOCK TABLES 锁定一个带有触发器的表,触发器内的表也将被锁定,详见LOCK TABLES 和 触发器

关于触发器的使用,请参见第27.3.1节,“触发器语法和示例”