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 識別符。事件名稱不區分大小寫,因此您不能在同一結構描述中擁有兩個名為 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 為基礎的帳戶活動稽核」。
IF NOT EXISTS
對於 CREATE EVENT
的意義與對於 CREATE TABLE
的意義相同:如果名為 event_name
的事件已存在於相同的結構描述中,則不會執行任何動作,且不會產生錯誤。(但是,在這種情況下會產生警告。)
ON SCHEDULE
子句決定為事件定義的 event_body
重複的時間、頻率和持續時間。此子句採用以下兩種形式之一:
AT
用於一次性事件。它指定事件僅在timestamp
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
子句為事件提供註解。註解
可以是任何您希望用來描述事件的字串,最多 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
子句中看似會成功;但是,當伺服器嘗試執行產生的排程事件時,執行會失敗並顯示錯誤。
諸如 SELECT
或 SHOW
等僅傳回結果集的語法在事件中使用時無效;這些語法的輸出不會傳送至 MySQL Monitor,也不會儲存在任何地方。但是,您可以使用諸如 SELECT ... INTO
和 INSERT INTO ... SELECT
等會儲存結果的語法。(請參閱本章節的下一個範例,以了解後者的實例。)
事件所屬的 schema 是 DO
子句中資料表參照的預設 schema。任何對其他 schema 中資料表的參照都必須以正確的 schema 名稱加以限定。
與預存程序一樣,您可以使用 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,「預存程序語法」。無法將事件建立為預存程序的一部分,或由另一個事件建立事件。