Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

MySQL 8.3 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 需要对要创建事件的模式的 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 个字符。 事件名称不区分大小写,因此您不能在同一个模式中拥有两个名为 myeventMyEvent 的事件。 一般来说,事件名称的规则与存储例程的名称规则相同。 参见 第 11.2 节,“模式对象名称”

事件与模式关联。 如果事件名称中没有指定模式,则假设为当前模式。 要在特定模式中创建事件,请使用 schema_name.event_name 语法来限定事件名称。

DEFINER 子句指定了在事件执行时检查访问权限的 MySQL 帐户。如果存在 DEFINER 子句,则 user 值应为指定的 MySQL 帐户,格式为 'user_name'@'host_name'CURRENT_USERCURRENT_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 值的表达式。您可以使用 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 语句本身无效—无论出于什么原因—将以错误形式失败。

    您可以使用 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 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 语句”)。

第三个值也可以出现在 ENABLEDISABLE 的位置; 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 语句似乎成功了;然而,当服务器尝试执行生成的计划事件时,执行将失败并出现错误。

Note

诸如 SELECTSHOW 仅返回结果集的语句在事件中没有效果;这些语句的输出不会发送到 MySQL 监视器,也不会存储在任何地方。然而,您可以使用诸如 SELECT ... INTOINSERT INTO ... SELECT 的语句来存储结果。(见本节中的下一个示例。)

事件所属的模式是 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 节,“存储例程语法”。无法在存储例程中创建事件或由另一个事件创建事件。