创建触发器(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
此语句创建一个新触发器。触发器是与表关联的命名数据库对象,当表发生特定事件时会激活该对象。触发器与名为 tbl_name
的表相关联,该表必须引用永久表。不能将触发器与临时表或视图相关联。
触发器名称存在于schema
命名空间中,这意味着所有触发器在schema
中必须具有唯一的名称。不同schema
中的触发器可以具有相同的名称。
本节介绍 CREATE TRIGGER
语法。有关其他讨论,请参阅 “Trigger Syntax and Examples”。CREATE TRIGGER
需要与触发器关联的表的触发器权限。如果存在DEFINER
子句,则所需的权限取决于用户值,如第“Stored Object Access Control” 中所述。如果启用了binary logging,则 CREATE TRIGGER
可能需要[SUPER](https://dev.mysql.com/doc/refman/5.7/en/privileges-provided.html#priv_super)权限
,如“Stored Program Binary Logging”中所述。DEFINER
子句确定在触发器激活时检查访问权限时使用的安全上下文,如本节后面所述。
trigger_time
Trigger_time
是触发器触发的时间。它可以是BEFORE
或AFTER
,以指示触发器在每个要修改的行之前或之后激活。
基本列值检查在触发激活之前进行,因此您不能使用 BEFORE
触发器将不适合列类型的值转换为有效值。
trigger_event
Trigger_event
表示激活触发器的操作类型。以下trigger_event
是允许的:
INSERT
: 每当将新行插入表中 (例如,通过INSERT
、LOAD DATA
和REPLACE
语句) 时,触发器都会激活。UPDATE
: 每当修改一行时 (例如,通过UPDATE
语句),触发器都会激活。DELETE
: 只要从表中删除一行 (例如,通过DELETE
和REPLACE
语句),触发器就会激活。DROP TABLE
和TRUNCATE TABLE
语句不会激活此触发器,因为它们不使用DELETE
。删除分区也不会激活DELETE
触发器。
Trigger_event
并不表示激活触发器的 SQL 语句的文字类型(即insert
不仅仅只包含insert
语句),而是表示表操作的类型。例如,INSERT
触发器不仅会激活 INSERT
语句,还会激活 LOAD DATA
语句,因为这两个语句都将行插入表中。
一个可能令人困惑的例子是INSERT INTO ... ON DUPLICATE KEY UPDATE ...
语法: 每一行都激活一个BEFORE INSERT
触发器,后跟一个AFTER INSERT
触发器,或者同时激活BEFORE UPDAT
和AFTER UPDATE
触发器,这取决于该行是否存在重复键。
NOTE级联外键操作不会激活触发器。
trigger_order
可以为具有相同触发事件和操作时间的给定表定义多个触发器。例如,您可以为表设置两个BEFORE UPDATE
触发器。默认情况下,具有相同触发事件和操作时间的触发器按创建顺序激活。要影响触发顺序,请指定一个trigger_order
子句,该子句指示FOLLOWS
或PRECEDES
,以及具有相同触发事件和操作时间的现有触发器的名称。使用 FOLLOWS
,新触发器在现有触发器之后激活。使用 PRECEDES
,新触发器在现有触发器之前激活。
Trigger_body
Trigger_body
是触发器激活时要执行的语句。要执行多个语句,请使用BEGIN ... END
复合语句构造。这也使您能够使用stored routines中允许的相同语句。参见“BEGIN … END Compound Statement”。触发器中不允许某些语句; 请参阅“Restrictions on Stored Programs”。
在触发器主体中,您可以通过使用OLD
和NEW
别名来引用主表 (与触发器关联的表) 中的列。OLD.col_name
是指在更新或删除现有行之前的列。NEW.col_name
是指要插入的新行或更新后的现有行的列。
触发器不能使用 NEW.col_name
或使用 OLD.col_name
引用生成的列。有关生成列的信息,请参阅“CREATE TABLE and Generated Columns”。
MySQL 在创建触发器时存储有效的 sql_mode 系统变量设置,并且无论触发器开始执行时的当前服务器 SQL 模式如何,都始终使用该设置执行触发器主体。
权限
DEFINER
子句指定在触发器激活时检查访问权限时使用的 MySQL 帐户。如果存在DEFINER
子句,则用户值应为指定为 ‘user_name’@‘host_name’
、 CURRENT_USER
或 CURRENT_USER()
的 MySQL 帐户。允许的用户值取决于您持有的权限,如“Stored Object Access Control”中所述。有关触发器安全性的其他信息,请参见该部分。
如果省略了DEFINER
子句,则默认定义符是执行CREATE TRIGGER
语句的用户。这与显式指定DEFINER = CURRENT_USER
相同。
MySQL 在检查触发器权限时考虑了DEFINER
用户,如下所示:
- 在
CREATE TRIGGER
时,发布语句的用户必须具有TRIGGER
权限。 - 在触发激活时,会针对
DEFINER
用户检查特权。此用户必须具有以下权限:- 主表的
TRIGGER
权限。 - 如果在触发器正文中使用
OLD.col_name
或NEW.col_name
对表列进行引用,则主表的SELECT
特权。 - 如果表列是触发器正文中设置
SET NEW._
colname` =value
赋值的目标,则主表的
UPDATE权限`。
- 主表的
在触发器主体中,CURRENT_USER
函数返回用于在触发器激活时检查权限的帐户。这是DEFINER
用户,而不是其操作导致触发器被激活的用户。有关触发器内的用户审核的信息,请参阅“SQL-Based Account Activity Auditing”。
其他
如果使用LOCK TABLES
锁定具有触发器的表,则触发器中使用的表也会被锁定,如Lcok Tables和Trigger中所述。
有关触发器使用的其他讨论,请参见“Trigger Syntax and Examples”。
删除触发器(DROP TRIGGER)
DROP TRIGGER [IF EXISTS] [schema_name.]trigger_name
此语句删除一个触发器。schema (database) 名称是可选的。如果省略schema,则从默认schema中删除触发器。DROP TRIGGER
需要与触发器关联的表的[TRIGGER](https://dev.mysql.com/doc/refman/5.7/en/privileges-provided.html#priv_trigger)
权限。
可以使用IF EXISTS
来防止触发器不存在时发生错误。如果使用了IF EXISTS
,则为不存在的触发器生成NOTE
。见“SHOW WARNINGS Statement”。
如果删除表,表的触发器也会被删除。