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 节,“模式对象名称”。
事件与模式关联。 如果事件名称中没有指定模式,则假设为当前模式。 要在特定模式中创建事件,请使用
语法来限定事件名称。schema_name
.event_name
该 DEFINER
子句指定了在事件执行时检查访问权限的 MySQL 帐户。如果存在 DEFINER
子句,则 user
值应为指定的 MySQL 帐户,格式为 '
,user_name
'@'host_name
'CURRENT_USER
或 CURRENT_USER()
。允许的 user
值取决于您拥有的权限,如 第 27.6 节,“存储对象访问控制” 中所讨论的那样。还可以查看该节以获取关于事件安全的更多信息。
如果省略 DEFINER
子句,则默认定义者是执行 CREATE EVENT
语句的用户。这与明确指定 DEFINER = CURRENT_USER
相同。
在事件体中,CURRENT_USER
函数返回在事件执行时用于检查权限的帐户,即 DEFINER
用户。有关事件中的用户审核信息,请参阅 第 8.2.23 节,“基于 SQL 的帐户活动审核”。
IF NOT EXISTS
对于 CREATE EVENT
的含义与 CREATE TABLE
相同:如果同一个模式中已经存在名为 event_name
的事件,则不执行任何操作,也不会出现错误。(但是,在这种情况下会生成警告。)
该 ON SCHEDULE
子句确定事件何时、何时重复执行 event_body
定义的事件。这一子句有两种形式:
-
AT
用于一次性事件。它指定事件在给定的日期和时间timestamp
timestamp
执行一次,该时间戳必须包括日期和时间,或者是一个解析为 datetime 值的表达式。您可以使用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
开头。 -
要在regular间隔重复操作,使用
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
语句。在这些情况下,存储函数、可加载函数和表引用的引用都是明确不允许的,并且会出错(见 Bug #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 8.2.0 开始弃用。
您可以使用 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 模式是什么时候开始执行事件的。不管当前服务器 SQL 模式是什么时候开始执行事件的。
包含 ALTER EVENT
语句的 CREATE EVENT
语句似乎成功了;然而,当服务器尝试执行生成的计划事件时,执行将失败并出现错误。
诸如 SELECT
或 SHOW
仅返回结果集的语句在事件中没有效果;这些语句的输出不会发送到 MySQL 监视器,也不会存储在任何地方。然而,您可以使用诸如 SELECT ... INTO
和 INSERT INTO ... SELECT
的语句来存储结果。(见本节中的下一个示例。)
事件所属的模式是 DO
子句中的默认模式。对其他模式中的表的引用必须用适当的模式名称限定。
与存储例程一样,您可以在 DO
子句中使用复合语句语法,使用 BEGIN
和 END
关键字,如下所示:
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 节,“存储例程语法”。无法在存储例程中创建事件或由另一个事件创建事件。