文档首页
MySQL 9.0 参考手册
相关文档 下载本手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 参考手册  /  ...  /  CREATE TRIGGER 语句

15.1.22 CREATE TRIGGER 语句

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 的表关联,该表必须引用永久表。您无法将触发器与 TEMPORARY 表或视图关联。

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

IF NOT EXISTS 可防止在同一个架构中,同一个表上,具有相同名称的触发器已经存在时出现错误。

本节介绍 CREATE TRIGGER 语法。有关更多讨论,请参阅 第 27.4.1 节,“触发器语法和示例”

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

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

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

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

trigger_event 指示激活触发器的操作类型。允许使用以下 trigger_event

  • INSERT:每当向表中插入新行时(例如,通过 INSERTLOAD DATAREPLACE 语句),触发器都会激活。

  • UPDATE:每当修改一行时(例如,通过 UPDATE 语句),触发器都会激活。

  • DELETE:每当从表中删除一行时(例如,通过 DELETEREPLACE 语句),触发器都会激活。对表的 DROP TABLETRUNCATE TABLE 语句 不会 激活此触发器,因为它们不使用 DELETE。删除分区也不会激活 DELETE 触发器。

trigger_event 并不代表激活触发器的字面 SQL 语句类型,而是代表表操作类型。例如,INSERT 触发器不仅针对 INSERT 语句激活,而且针对 LOAD DATA 语句激活,因为这两种语句都将行插入到表中。

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

注意

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

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

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

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

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

MySQL 会存储创建触发器时有效的 sql_mode 系统变量设置,并且始终使用此设置执行触发器主体,而不管触发器开始执行时当前的服务器 SQL 模式

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

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

MySQL 在检查触发器权限时会考虑 DEFINER 用户,如下所示

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

  • 在触发器激活时,会针对 DEFINER 用户检查权限。此用户必须具有以下权限

    • 主题表的 TRIGGER 权限。

    • 如果触发器主体中使用 OLD.col_nameNEW.col_name 引用表列,则该用户必须具有主题表的 SELECT 权限。

    • 如果表列是触发器主体中 SET NEW.col_name = value 赋值的目标,则该用户必须具有主题表的 UPDATE 权限。

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

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

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

有关触发器使用的更多讨论,请参见 第 27.4.1 节“触发器语法和示例”