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 EVENT Statement

15.1.13 创建事件语句

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 需要在事件将被创建的 schema 中的EVENT特权。如果存在DEFINER子句,所需权限取决于user值,详见第27.6节,“存储对象访问控制”

一个有效的CREATE EVENT 语句的最低要求如下:

  • 关键字CREATE EVENT 加上一个唯一标识事件在数据库 schema 中的事件名称。

  • 一个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个字符。事件名称不区分大小写,所以在同一个 schema 中不能有两个名为 myeventMyEvent 的事件。一般来说,事件名称遵循存储程序名称的规则。见第11.2节,“schema 对象名称”

事件与 schema 关联。如果没有指定 event_name 中的 schema,使用默认(当前)schema。要在特定的 schema 中创建事件,请使用 schema_name.event_name 语法。

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

如果省略了 DEFINER 子句,缺省定义器是执行CREATE EVENT 语句的用户。这等同于显式指定 DEFINER = CURRENT_USER

在事件体内,CURRENT_USER 函数返回用于检查权限的账户,这是 DEFINER 用户。关于事件中的用户审核,请查看第8.2.23节,“基于 SQL 的帐号活动审核”

IF NOT EXISTSCREATE EVENTCREATE TABLE 的含义相同:如果在同一个架构中已经存在名为 event_name 的事件,不执行任何操作,且不产生错误(但是会生成警告信息)。

ON SCHEDULE 子句确定了事件 event_body 何时、何频率、何长时间重复。该子句可以采取两种形式:

  • AT timestamp 用于一次性事件,指定事件在由 timestamp 指定的日期和时间执行,timestamp 必须包含日期和时间,或者是一个可以解析为datetime值的表达式。您可以使用DATETIMETIMESTAMP 类型来实现这个目的。如果日期已经过去,会生成警告信息,如下所示:

    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 语句本身无效—for whatever reason—会以错误方式失败。

    您可以使用CURRENT_TIMESTAMP 指定当前日期和时间。在这种情况下,事件在创建时立即执行。

    创建一个将在当前日期和时间以后的某个点发生的事件,例如表达式"三周后",可以使用可选的子句+ INTERVAL interval。该interval部分由数量和时间单位组成,遵循时间间隔的语法规则,但不能使用涉及微秒的单元关键字。在某些间隔类型中,可以使用复杂的时间单位。例如,"两分钟十秒"可以表达为+ INTERVAL '2:10' MINUTE_SECOND

    您也可以组合间隔。例如,AT CURRENT_TIMESTAMP + INTERVAL 3 WEEK + INTERVAL 2 DAY等同于"三周两天后"。每个这样的子句都必须以+ INTERVAL开头。

  • 为了重复某些操作,使用一个EVERY子句。EVERY关键字后面跟着一个遵循前一讨论的AT关键字描述的interval。(+ 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 intervalENDS;例如,EVERY 12 HOUR STARTS CURRENT_TIMESTAMP + INTERVAL 30 MINUTE ENDS CURRENT_TIMESTAMP + INTERVAL 4 WEEK等同于每十二小时,从现在开始三十分钟,到现在四周结束。没有使用ENDS意味着事件将继续执行不止。

    ENDS支持与STARTS相同的复杂时间单位语法。

    你可以在一个EVERY子句中使用STARTSENDS,或者都不要。

    如果重复事件在其调度间隔内不能终止,结果可能是多个事件同时执行。如果这不可取,你应该设法防止同时执行。例如,你可以使用GET_LOCK()函数,或者行或表锁定。

ON SCHEDULE 子句可以使用 MySQL 内置函数和用户变量来获取其中包含的 timestampinterval 值。您不能使用存储函数或可加载函数,也不能使用表引用;但是,您可以使用 SELECT FROM DUAL。这对CREATE EVENTALTER 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 Statement”)结合使用时最有用。

第三个值也可以取代ENABLEDISABLE;DISABLE ON REPLICA用于表示事件在复制源服务器上创建,复制到副本,但在副本上不执行。见第19.5.1.16节,“Replication of Invoked Features”

DISABLE ON REPLICA取代了已弃用的DISABLE ON SLAVE,因此在MySQL的未来版本中将被删除。

您可以使用COMMENT子句为事件提供注释。comment可以是任何64个字符以内的字符串,您想用来描述事件。注释文本作为字符串字面量,必须被引号括起来。

DO 语句指定事件的操作,包括一个 SQL 语句。几乎任何可以在存储程序中使用的有效 MySQL 语句都可以用作计划事件的操作语句。例如,以下事件 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 模式是什么

包含CREATE EVENT 语句的ALTER EVENT 语句在 DO 子句中,虽然看起来成功,但是当服务器尝试执行生成的计划事件时,执行失败并出现错误。

Note

SELECTSHOW 只返回结果集,用于事件时无效;这些语句的输出不发送到 MySQL 监控器,也不存储任何地方。然而,您可以使用像SELECT ... INTOINSERT INTO ... SELECT 等存储结果的语句。 (本节下一个示例中有 latter 的实例。)

事件所属架构是DO 子句中的默认架构。对其他架构的表引用必须使用正确的架构名称。

像存储程序一样,在DO 子句中可以使用复合语句语法,使用BEGINEND 关键字,如下所示:

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节,“存储程序语法”。不能在存储程序中创建事件,也不能由另一个事件创建事件。