CREATE
[DEFINER = user]
EVENT
[IF NOT EXISTS]
event_name
ON SCHEDULE schedule
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE | DISABLE ON {REPLICA | SLAVE}]
[COMMENT 'string']
DO event_body;
schedule: {
AT timestamp [+ INTERVAL interval] ...
| EVERY interval
[STARTS timestamp [+ INTERVAL interval] ...]
[ENDS timestamp [+ INTERVAL interval] ...]
}
interval:
quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |
WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}
此语句创建并计划一个新事件。除非启用了事件调度程序,否则该事件不会运行。有关检查事件调度程序状态并在必要时启用它的信息,请参阅 第 27.4.2 节“事件调度程序配置”。
CREATE EVENT
需要对要在其中创建事件的模式具有 EVENT
权限。如果存在 DEFINER
子句,则所需的权限取决于 user
值,如 第 27.6 节“存储对象访问控制” 中所述。
有效的 CREATE EVENT
语句的最低要求如下:
关键字
CREATE EVENT
加上事件名称,该名称在数据库模式中唯一标识该事件。一个
ON SCHEDULE
子句,用于确定事件的执行时间和频率。一个
DO
子句,其中包含要由事件执行的 SQL 语句。
这是一个最小的 CREATE EVENT
语句的示例:
CREATE EVENT myevent
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
DO
UPDATE myschema.mytable SET mycol = mycol + 1;
上一条语句创建了一个名为 myevent
的事件。此事件在其创建一小时后执行一次,它通过运行一条 SQL 语句将 myschema.mytable
表的 mycol
列的值增加 1。
event_name
必须是有效的 MySQL 标识符,最大长度为 64 个字符。事件名称不区分大小写,因此您不能在同一个模式中拥有两个名为 myevent
和 MyEvent
的事件。通常,控制事件名称的规则与存储例程名称的规则相同。请参阅 第 11.2 节,“模式对象名称”。
事件与模式关联。如果在 event_name
中未指示模式,则假定为默认(当前)模式。要在特定模式中创建事件,请使用
语法用模式限定事件名称。schema_name
.event_name
DEFINER
子句指定在事件执行时检查访问权限时要使用的 MySQL 帐户。如果存在 DEFINER
子句,则 user
值应为指定为 '
、user_name
'@'host_name
'CURRENT_USER
或 CURRENT_USER()
的 MySQL 帐户。允许的 user
值取决于您拥有的权限,如 第 27.6 节,“存储对象访问控制” 中所述。另请参阅该部分,以获取有关事件安全的其他信息。
如果省略 DEFINER
子句,则默认定义者是执行 CREATE EVENT
语句的用户。这与显式指定 DEFINER = CURRENT_USER
相同。
在事件体中,CURRENT_USER
函数返回用于在事件执行时检查权限的帐户,即 DEFINER
用户。有关事件内用户审计的信息,请参阅 第 8.2.23 节,“基于 SQL 的帐户活动审计”。
对于 CREATE EVENT
,IF NOT EXISTS
的含义与 CREATE TABLE
相同:如果在同一个模式中已存在名为 event_name
的事件,则不执行任何操作,也不会产生错误。(但是,在这种情况下会生成警告。)
ON SCHEDULE
子句确定为事件定义的 event_body
何时、多久重复一次以及重复多长时间。此子句采用以下两种形式之一
AT
用于一次性事件。它指定事件仅在timestamp
timestamp
给定的日期和时间执行一次,该时间戳必须包含日期和时间,或者必须是解析为日期时间值的表达式。为此,您可以使用DATETIME
或TIMESTAMP
类型的值。如果日期已过,则会发出警告,如下所示mysql> SELECT NOW(); +---------------------+ | NOW() | +---------------------+ | 2006-02-10 23:59:01 | +---------------------+ 1 row in set (0.04 sec) mysql> CREATE EVENT e_totals -> ON SCHEDULE AT '2006-02-10 23:59:00' -> DO INSERT INTO test.totals VALUES (NOW()); Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> SHOW WARNINGS\G *************************** 1. row *************************** Level: Note Code: 1588 Message: Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation.
本身无效的
CREATE EVENT
语句(无论出于何种原因)都会失败并报错。您可以使用
CURRENT_TIMESTAMP
指定当前日期和时间。在这种情况下,事件会在创建后立即生效。要创建一个在相对于当前日期和时间的某个未来时间点发生的事件(例如短语““从现在开始三周后””所表达的时间点),您可以使用可选子句
+ INTERVAL
。interval
interval
部分由时间量和时间单位两部分组成,并遵循 时间间隔 中描述的语法规则,但您不能使用任何涉及微秒的单位关键字来定义事件。对于某些间隔类型,可以使用复杂的时间单位。例如,““两分钟零十秒””可以表示为+ INTERVAL '2:10' MINUTE_SECOND
。您还可以组合间隔。例如,
AT CURRENT_TIMESTAMP + INTERVAL 3 WEEK + INTERVAL 2 DAY
等效于““从现在开始三周零两天””。此类子句的每个部分都必须以+ INTERVAL
开头。要按固定间隔重复操作,请使用
EVERY
子句。EVERY
关键字后跟一个interval
,如前面讨论AT
关键字时所述。(+ INTERVAL
不 与EVERY
一起使用。)例如,EVERY 6 WEEK
表示““每六周””。虽然
+ INTERVAL
子句在EVERY
子句中不允许使用,但您可以使用+ INTERVAL
中允许的相同复杂时间单位。EVERY
子句可能包含可选的STARTS
子句。STARTS
后跟一个timestamp
值,该值指示操作应何时开始重复,并且还可以使用+ INTERVAL
指定““从现在开始””的时间量。例如,interval
EVERY 3 MONTH STARTS CURRENT_TIMESTAMP + INTERVAL 1 WEEK
表示““每三个月,从现在开始一周后开始””。类似地,您可以将““每两周,从现在开始六小时十五分钟后开始””表示为EVERY 2 WEEK STARTS CURRENT_TIMESTAMP + INTERVAL '6:15' HOUR_MINUTE
。未指定STARTS
与使用STARTS CURRENT_TIMESTAMP
相同,也就是说,为事件指定的操作会在创建事件后立即开始重复。EVERY
子句可能包含可选的ENDS
子句。ENDS
关键字后跟一个timestamp
值,该值告诉 MySQL 事件应何时停止重复。您也可以将+ INTERVAL
与interval
ENDS
一起使用;例如,EVERY 12 HOUR STARTS CURRENT_TIMESTAMP + INTERVAL 30 MINUTE ENDS CURRENT_TIMESTAMP + INTERVAL 4 WEEK
等效于““每十二小时,从现在开始三十分钟后开始,到从现在开始四周后结束””。不使用ENDS
意味着事件会无限期地继续执行。ENDS
支持与STARTS
相同的复杂时间单位语法。您可以在
EVERY
子句中使用STARTS
、ENDS
,也可以同时使用或都不使用。如果重复事件在其调度间隔内未终止,则可能会导致事件的多个实例同时执行。如果这不希望出现这种情况,则应建立一种机制来防止同时出现多个实例。例如,您可以使用
GET_LOCK()
函数,或行锁或表锁。
ON SCHEDULE
子句可以使用涉及内置 MySQL 函数和用户变量的表达式来获取其包含的任何 timestamp
或 interval
值。您不能在此类表达式中使用存储函数或可加载函数,也不能使用任何表引用;但是,您可以使用 SELECT FROM DUAL
。这对 CREATE EVENT
和 ALTER EVENT
语句都适用。在这种情况下,明确不允许引用存储函数、可加载函数和表,并且会失败并报错(请参阅错误 #22830)。
ON SCHEDULE
子句中的时间使用当前会话 time_zone
值解释。这将成为事件时区;也就是说,用于事件调度并在事件执行期间生效的时区。这些时间将转换为 UTC,并与事件时区一起存储在内部。这使得事件执行能够按定义进行,而不管服务器时区或夏令时的任何后续更改。有关事件时间表示的其他信息,请参阅 第 27.4.4 节,“事件元数据”。另请参阅 第 15.7.7.19 节,“SHOW EVENTS 语句” 和 第 28.3.14 节,“INFORMATION_SCHEMA EVENTS 表”。
通常,一旦事件过期,就会立即将其删除。您可以通过指定 ON COMPLETION PRESERVE
来覆盖此行为。使用 ON COMPLETION NOT PRESERVE
只是明确了默认的非持久性行为。
您可以创建事件,但可以使用 DISABLE
关键字阻止其处于活动状态。或者,您可以使用 ENABLE
明确默认状态,即活动状态。这与 ALTER EVENT
一起使用最有效(请参阅 第 15.1.3 节,“ALTER EVENT 语句”)。
第三个值也可以出现在 ENABLE
或 DISABLE
的位置;DISABLE ON REPLICA
用于设置副本上事件的状态,以指示该事件是在复制源服务器上创建并复制到副本的,但未在副本上执行。请参阅 第 19.5.1.16 节,“调用功能的复制”。
DISABLE ON REPLICA
替换了已弃用的 DISABLE ON SLAVE
,因此可能会在未来版本的 MySQL 中删除。
您可以使用 COMMENT
子句为事件提供注释。comment
可以是您希望用于描述事件的任何字符串,最多 64 个字符。注释文本是字符串文字,因此必须用引号引起来。
DO
子句指定事件执行的操作,并包含一个 SQL 语句。几乎所有可以在存储例程中使用的有效 MySQL 语句都可以用作计划事件的操作语句。(请参阅 第 27.8 节,“存储程序的限制”。)例如,以下事件 e_hourly
每小时删除一次 sessions
表中的所有行,其中该表是 site_activity
模式的一部分
CREATE EVENT e_hourly
ON SCHEDULE
EVERY 1 HOUR
COMMENT 'Clears out sessions table each hour.'
DO
DELETE FROM site_activity.sessions;
MySQL 存储在创建或更改事件时生效的 sql_mode
系统变量设置,并始终使用此设置执行事件,而不管事件开始执行时的当前服务器 SQL 模式如何。
包含 ALTER EVENT
语句的 CREATE EVENT
语句在其 DO
子句中似乎成功;但是,当服务器尝试执行生成的计划事件时,执行失败并出现错误。
诸如 SELECT
或 SHOW
之类的仅仅返回结果集的语句在事件中使用时无效;这些语句的输出不会发送到 MySQL Monitor,也不会存储在任何地方。但是,您可以使用诸如 SELECT ... INTO
和 INSERT INTO ... SELECT
之类的存储结果的语句。(有关后者的实例,请参见本节中的下一个示例。)
事件所属的模式是 DO
子句中表引用的默认模式。对其他模式中表的任何引用都必须使用正确的模式名称进行限定。
与存储例程一样,您可以使用 BEGIN
和 END
关键字在 DO
子句中使用复合语句语法,如下所示
delimiter |
CREATE EVENT e_daily
ON SCHEDULE
EVERY 1 DAY
COMMENT 'Saves total number of sessions then clears the table each day'
DO
BEGIN
INSERT INTO site_activity.totals (time, total)
SELECT CURRENT_TIMESTAMP, COUNT(*)
FROM site_activity.sessions;
DELETE FROM site_activity.sessions;
END |
delimiter ;
此示例使用 delimiter
命令更改语句分隔符。请参阅 第 27.1 节“定义存储程序”。
在事件中可以使用更复杂的复合语句,例如存储例程中使用的那些语句。此示例使用局部变量、错误处理程序和流程控制结构
delimiter |
CREATE EVENT e
ON SCHEDULE
EVERY 5 SECOND
DO
BEGIN
DECLARE v INTEGER;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;
SET v = 0;
WHILE v < 5 DO
INSERT INTO t1 VALUES (0);
UPDATE t2 SET s1 = s1 + 1;
SET v = v + 1;
END WHILE;
END |
delimiter ;
没有办法直接将参数传递给事件或从事件传递参数;但是,可以在事件中使用参数调用存储例程
CREATE EVENT e_call_myproc
ON SCHEDULE
AT CURRENT_TIMESTAMP + INTERVAL 1 DAY
DO CALL myproc(5, 27);
如果事件的定义者具有足够的权限来设置全局系统变量(请参阅 第 7.1.9.1 节“系统变量权限”),则该事件可以读取和写入全局变量。由于授予此类权限可能导致滥用,因此必须格外小心。
通常,存储例程中有效的任何语句都可用于事件执行的操作语句。有关存储例程中允许使用的语句的更多信息,请参阅 第 27.2.1 节“存储例程语法”。无法将事件创建为存储例程的一部分,也无法通过另一个事件创建事件。