文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  ...  /  CREATE EVENT 陳述式

15.1.13 CREATE EVENT 陳述式

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 必須是長度上限為 64 個字元的有效 MySQL 識別符。事件名稱不區分大小寫,因此您不能在同一結構描述中擁有兩個名為 myeventMyEvent 的事件。一般而言,事件名稱的規則與儲存常式的名稱規則相同。請參閱第 11.2 節「結構描述物件名稱」

事件與結構描述相關聯。如果沒有將結構描述指示為 event_name 的一部分,則會假設為預設(目前)結構描述。若要在特定結構描述中建立事件,請使用 schema_name.event_name 語法,以結構描述限定事件名稱。

DEFINER 子句指定在事件執行時檢查存取權限時要使用的 MySQL 帳戶。如果存在 DEFINER 子句,則 user 值應該是指定為 'user_name'@'host_name'CURRENT_USERCURRENT_USER() 的 MySQL 帳戶。允許的 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 給定的日期和時間執行一次,其中 timestamp 必須包含日期和時間,或必須是解析為日期時間值的運算式。您可以使用 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 intervalinterval 部分由兩個部分組成:數量和時間單位,並遵循時間間隔中描述的語法規則,但您在定義事件時不能使用任何涉及微秒的時間單位關鍵字。使用某些間隔類型時,可以使用複雜的時間單位。例如,兩分鐘又十秒可以表示為 + 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 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 陳述式都是如此。在這種情況下,明確不允許參考儲存函式、可載入函式和資料表,並且會因錯誤而失敗(請參閱錯誤 #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 版本中可能會移除。

您可以使用 COMMENT 子句為事件提供註解。註解 可以是任何您希望用來描述事件的字串,最多 64 個字元。註解文字是字串常值,必須以引號括住。

DO 子句指定事件執行的動作,其中包含一個 SQL 語法。幾乎任何可以在預存程序中使用的有效 MySQL 語法,也可以用作排程事件的動作語法。(請參閱章節 27.8,「預存程序的限制」。)例如,以下事件 e_hourly 每小時從 sessions 資料表中刪除所有資料列,此資料表屬於 site_activity schema 的一部分。

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 子句中看似會成功;但是,當伺服器嘗試執行產生的排程事件時,執行會失敗並顯示錯誤。

注意

諸如 SELECTSHOW 等僅傳回結果集的語法在事件中使用時無效;這些語法的輸出不會傳送至 MySQL Monitor,也不會儲存在任何地方。但是,您可以使用諸如 SELECT ... INTOINSERT INTO ... SELECT 等會儲存結果的語法。(請參閱本章節的下一個範例,以了解後者的實例。)

事件所屬的 schema 是 DO 子句中資料表參照的預設 schema。任何對其他 schema 中資料表的參照都必須以正確的 schema 名稱加以限定。

與預存程序一樣,您可以使用 BEGINEND 關鍵字,在 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,「預存程序語法」。無法將事件建立為預存程序的一部分,或由另一個事件建立事件。