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.5.2 節「事件排程器組態」。
CREATE EVENT
需要在要建立事件的結構描述中具有 EVENT
權限。如果存在 DEFINER
子句,則所需的權限取決於 user
值,如第 27.7 節「已儲存物件存取控制」中所述。
有效的 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 節「結構描述物件名稱」。
事件與結構描述相關聯。如果未指示結構描述作為 event_name
的一部分,則會假設預設 (目前) 結構描述。若要在特定結構描述中建立事件,請使用
語法以結構描述限定事件名稱。schema_name
.event_name
DEFINER
子句指定在事件執行時檢查存取權限時要使用的 MySQL 帳戶。如果存在 DEFINER
子句,則 user
值應為指定為 '
、user_name
'@'host_name
'CURRENT_USER
或 CURRENT_USER()
的 MySQL 帳戶。允許的 user
值取決於您擁有的權限,如第 27.7 節「已儲存物件存取控制」中所述。另請參閱該節以取得關於事件安全性的其他資訊。
如果省略 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
或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.5.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
子句為事件提供註解。comment
可以是任何最多 64 個字元的字串,您可以用於描述事件。註解文字是字串常值,必須用引號括起來。
DO
子句指定由事件執行的動作,並包含一個 SQL 陳述式。幾乎任何可以在儲存程序中使用的有效 MySQL 陳述式也可以用作排程事件的動作陳述式。(請參閱 第 27.9 節,「儲存程序的限制」。)例如,以下事件 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 模式為何。
在 DO
子句中包含 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);
在 MySQL 9.0 中,可以準備 CREATE EVENT
陳述式,但陳述式文字不得包含任何預留位置 (?
)。解決此限制的一種方法是組合陳述式的文字,準備它,並在儲存程序中執行它;CREATE EVENT
陳述式的可變部分可以作為參數傳遞到儲存程序中。我們在以下範例中示範了這一點,此範例假設在資料庫 d
中已經存在一個表格 t
,其建立方式如下所示
USE d;
CREATE TABLE t (
c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
c2 VARCHAR(20),
c3 INT
);
我們希望建立一個事件,該事件以在建立時確定的間隔將列插入此表格,類似於此處顯示的陳述式所定義的事件
CREATE EVENT e
ON SCHEDULE EVERY interval SECOND
STARTS CURRENT_TIMESTAMP + INTERVAL 10 SECOND
ENDS CURRENT_TIMESTAMP + INTERVAL 2 MINUTE
ON COMPLETION PRESERVE
DO
INSERT INTO d.t1 VALUES ROW(NULL, NOW(), FLOOR(RAND()*100));
我們不能使用 ?
作為 interval
的預留位置,但我們可以將參數值傳遞給像這樣的一個儲存程序
delimiter |
CREATE PROCEDURE sp(n INT)
BEGIN
SET @s1 = "CREATE EVENT e ON SCHEDULE EVERY ";
SET @s2 = " SECOND
STARTS CURRENT_TIMESTAMP + INTERVAL 10 SECOND
ENDS CURRENT_TIMESTAMP + INTERVAL 2 MINUTE
ON COMPLETION PRESERVE
DO
INSERT INTO d.t VALUES ROW(NULL, NOW(), FLOOR(RAND()*100))";
SET @s = CONCAT(@s1, n, @s2);
PREPARE ps FROM @s;
EXECUTE ps;
DEALLOCATE PREPARE ps;
END |
delimiter ;
mysql> TABLE t;
Empty set (0.00 sec)
mysql> CALL sp(5);
Query OK, 0 rows affected (0.01 sec)
# Wait 2 minutes...
mysql> TABLE t;
+----+---------------------+------+
| c1 | c2 | c3 |
+----+---------------------+------+
| 1 | 2024-06-12 15:53:36 | 41 |
| 2 | 2024-06-12 15:53:41 | 84 |
| 3 | 2024-06-12 15:53:46 | 71 |
| 4 | 2024-06-12 15:53:51 | 78 |
| 5 | 2024-06-12 15:53:56 | 53 |
| 6 | 2024-06-12 15:54:01 | 6 |
| 7 | 2024-06-12 15:54:06 | 48 |
| 8 | 2024-06-12 15:54:11 | 98 |
| 9 | 2024-06-12 15:54:16 | 22 |
| 10 | 2024-06-12 15:54:21 | 88 |
| 11 | 2024-06-12 15:54:26 | 53 |
| 12 | 2024-06-12 15:54:31 | 75 |
| 13 | 2024-06-12 15:54:36 | 93 |
| 14 | 2024-06-12 15:54:41 | 13 |
| 15 | 2024-06-12 15:54:46 | 62 |
| 16 | 2024-06-12 15:54:51 | 47 |
| 17 | 2024-06-12 15:54:56 | 22 |
| 18 | 2024-06-12 15:55:01 | 47 |
| 19 | 2024-06-12 15:55:06 | 43 |
| 20 | 2024-06-12 15:55:11 | 50 |
| 21 | 2024-06-12 15:55:16 | 98 |
| 22 | 2024-06-12 15:55:21 | 15 |
| 23 | 2024-06-12 15:55:26 | 56 |
+----+---------------------+------+
23 rows in set (0.00 sec)
在使用引數值 5
調用 sp
後(如所示),並等待 2 分鐘直到事件 e
完成執行,我們可以發現表格 t
每 5 秒更新一次。由於 e
是以 ON COMPLETION PRESERVE
建立的,我們可以在資訊綱要的 EVENTS
表格中看到它,並驗證它是按照預期建立的
mysql> SELECT EVENT_NAME, EVENT_SCHEMA, EVENT_DEFINITION, EVENT_TYPE
> FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='e'\G
*************************** 1. row ***************************
EVENT_NAME: e
EVENT_SCHEMA: d
EVENT_DEFINITION: INSERT INTO d.t VALUES ROW(NULL, NOW(), FLOOR(RAND()*100))
EVENT_TYPE: RECURRING
1 row in set (0.00 sec)
如果事件的定義者具有足夠的權限來設定全域系統變數(請參閱 第 7.1.9.1 節,「系統變數權限」),則事件可以讀取和寫入全域變數。由於授予此類權限會導致潛在的濫用,因此在執行此操作時必須格外小心。
通常,任何在儲存程序中有效的陳述式都可以用於事件執行的動作陳述式。有關儲存程序中允許的陳述式的更多資訊,請參閱 第 27.2.1 節,「儲存程序語法」。無法將事件建立為儲存程序的一部分,或透過另一個事件建立事件。