本章節列出運算式在 MySQL 中必須遵循的語法規則,並提供關於可能出現在運算式中的詞彙類型的額外資訊。
以下語法規則定義了 MySQL 中的運算式語法。此處顯示的語法基於 MySQL 原始發行版本中 sql/sql_yacc.yy
檔案中給出的語法。有關某些運算式詞彙的額外資訊,請參閱 運算式詞彙注意事項。
expr:
expr OR expr
| expr || expr
| expr XOR expr
| expr AND expr
| expr && expr
| NOT expr
| ! expr
| boolean_primary IS [NOT] {TRUE | FALSE | UNKNOWN}
| boolean_primary
boolean_primary:
boolean_primary IS [NOT] NULL
| boolean_primary <=> predicate
| boolean_primary comparison_operator predicate
| boolean_primary comparison_operator {ALL | ANY} (subquery)
| predicate
comparison_operator: = | >= | > | <= | < | <> | !=
predicate:
bit_expr [NOT] IN (subquery)
| bit_expr [NOT] IN (expr [, expr] ...)
| bit_expr [NOT] BETWEEN bit_expr AND predicate
| bit_expr SOUNDS LIKE bit_expr
| bit_expr [NOT] LIKE simple_expr [ESCAPE simple_expr]
| bit_expr [NOT] REGEXP bit_expr
| bit_expr
bit_expr:
bit_expr | bit_expr
| bit_expr & bit_expr
| bit_expr << bit_expr
| bit_expr >> bit_expr
| bit_expr + bit_expr
| bit_expr - bit_expr
| bit_expr * bit_expr
| bit_expr / bit_expr
| bit_expr DIV bit_expr
| bit_expr MOD bit_expr
| bit_expr % bit_expr
| bit_expr ^ bit_expr
| bit_expr + interval_expr
| bit_expr - interval_expr
| simple_expr
simple_expr:
literal
| identifier
| function_call
| simple_expr COLLATE collation_name
| param_marker
| variable
| simple_expr || simple_expr
| + simple_expr
| - simple_expr
| ~ simple_expr
| ! simple_expr
| BINARY simple_expr
| (expr [, expr] ...)
| ROW (expr, expr [, expr] ...)
| (subquery)
| EXISTS (subquery)
| {identifier expr}
| match_expr
| case_expr
| interval_expr
關於運算子優先順序,請參閱 第 14.4.1 節,「運算子優先順序」。某些運算子的優先順序和意義取決於 SQL 模式。
預設情況下,
||
是邏輯OR
運算子。啟用PIPES_AS_CONCAT
時,||
是字串串接,其優先順序介於^
和一元運算子之間。預設情況下,
!
的優先順序高於NOT
。啟用HIGH_NOT_PRECEDENCE
時,!
和NOT
具有相同的優先順序。
關於常值語法,請參閱 第 11.1 節,「常值」。
關於識別符語法,請參閱 第 11.2 節,「綱要物件名稱」。
變數可以是使用者變數、系統變數或儲存的程式區域變數或參數。
param_marker
是 ?
,用於預備陳述式中的佔位符。請參閱 第 15.5.1 節,「PREPARE 陳述式」。
(
表示傳回單一值的子查詢;也就是純量子查詢。請參閱 第 15.2.15.1 節,「作為純量運算元的子查詢」。subquery
)
{
是 ODBC escape 語法,為了 ODBC 相容性而被接受。其值為 identifier
expr
}expr
。語法中的 {
和 }
大括號應按字面意思書寫;它們不是在其他語法描述中使用的元語法。
match_expr
表示 MATCH
運算式。請參閱 第 14.9 節,「全文檢索函數」。
case_expr
表示 CASE
運算式。請參閱 第 14.5 節,「流程控制函數」。
interval_expr
代表時間間隔。請參閱 時間間隔。
運算式中的 interval_expr
代表時間間隔。間隔具有以下語法:
INTERVAL expr unit
expr
代表數量。unit
代表解釋數量的單位;它是一個指定符,例如 HOUR
、DAY
或 WEEK
。INTERVAL
關鍵字和 unit
指定符不區分大小寫。
下表顯示每個 unit
值的 expr
引數的預期格式。
表 11.2 時間間隔運算式和單位引數
unit 值 |
預期的 expr 格式 |
---|---|
MICROSECOND |
MICROSECONDS |
SECOND |
SECONDS |
MINUTE |
MINUTES |
HOUR |
HOURS |
DAY |
DAYS |
WEEK |
WEEKS |
MONTH |
MONTHS |
QUARTER |
QUARTERS |
YEAR |
YEARS |
SECOND_MICROSECOND |
'SECONDS.MICROSECONDS' |
MINUTE_MICROSECOND |
'MINUTES:SECONDS.MICROSECONDS' |
MINUTE_SECOND |
'MINUTES:SECONDS' |
HOUR_MICROSECOND |
'HOURS:MINUTES:SECONDS.MICROSECONDS' |
HOUR_SECOND |
'HOURS:MINUTES:SECONDS' |
HOUR_MINUTE |
'HOURS:MINUTES' |
DAY_MICROSECOND |
'DAYS HOURS:MINUTES:SECONDS.MICROSECONDS' |
DAY_SECOND |
'DAYS HOURS:MINUTES:SECONDS' |
DAY_MINUTE |
'DAYS HOURS:MINUTES' |
DAY_HOUR |
'DAYS HOURS' |
YEAR_MONTH |
'YEARS-MONTHS' |
MySQL 允許在 expr
格式中使用任何標點符號分隔符號。表中顯示的是建議的分隔符號。
時間間隔用於某些函數,例如 DATE_ADD()
和 DATE_SUB()
。
mysql> SELECT DATE_ADD('2018-05-01',INTERVAL 1 DAY);
-> '2018-05-02'
mysql> SELECT DATE_SUB('2018-05-01',INTERVAL 1 YEAR);
-> '2017-05-01'
mysql> SELECT DATE_ADD('2020-12-31 23:59:59',
-> INTERVAL 1 SECOND);
-> '2021-01-01 00:00:00'
mysql> SELECT DATE_ADD('2018-12-31 23:59:59',
-> INTERVAL 1 DAY);
-> '2019-01-01 23:59:59'
mysql> SELECT DATE_ADD('2100-12-31 23:59:59',
-> INTERVAL '1:1' MINUTE_SECOND);
-> '2101-01-01 00:01:00'
mysql> SELECT DATE_SUB('2025-01-01 00:00:00',
-> INTERVAL '1 1:1:1' DAY_SECOND);
-> '2024-12-30 22:58:59'
mysql> SELECT DATE_ADD('1900-01-01 00:00:00',
-> INTERVAL '-1 10' DAY_HOUR);
-> '1899-12-30 14:00:00'
mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY);
-> '1997-12-02'
mysql> SELECT DATE_ADD('1992-12-31 23:59:59.000002',
-> INTERVAL '1.999999' SECOND_MICROSECOND);
-> '1993-01-01 00:00:01.000001'
時間算術也可以在運算式中使用 INTERVAL
和 +
或 -
運算子來執行。
date + INTERVAL expr unit
date - INTERVAL expr unit
如果另一側的運算式是日期或日期時間值,則允許在 +
運算子的任一側使用 INTERVAL
。對於 expr
unit
-
運算子,僅允許在右側使用 INTERVAL
,因為從間隔中減去日期或日期時間值沒有意義。expr
unit
mysql> SELECT '2018-12-31 23:59:59' + INTERVAL 1 SECOND;
-> '2019-01-01 00:00:00'
mysql> SELECT INTERVAL 1 DAY + '2018-12-31';
-> '2019-01-01'
mysql> SELECT '2025-01-01' - INTERVAL 1 SECOND;
-> '2024-12-31 23:59:59'
EXTRACT()
函數使用與 DATE_ADD()
或 DATE_SUB()
相同的 unit
指定符種類,但會從日期中擷取部分,而不是執行日期算術。
mysql> SELECT EXTRACT(YEAR FROM '2019-07-02');
-> 2019
mysql> SELECT EXTRACT(YEAR_MONTH FROM '2019-07-02 01:02:03');
-> 201907
時間間隔可以在 CREATE EVENT
陳述式中使用。
CREATE EVENT myevent
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
DO
UPDATE myschema.mytable SET mycol = mycol + 1;
如果您指定的時間間隔值太短(不包括 unit
關鍵字預期的所有間隔部分),MySQL 會假設您遺漏了間隔值最左邊的部分。例如,如果您指定 DAY_SECOND
的 unit
,則 expr
的值預期會有天數、小時、分鐘和秒數部分。如果您指定像 '1:10'
這樣的值,MySQL 會假設天數和小時部分遺失,且該值代表分鐘和秒數。換句話說,'1:10' DAY_SECOND
的解讀方式使其等同於 '1:10' MINUTE_SECOND
。這類似於 MySQL 將 TIME
值解讀為代表經過的時間,而不是一天中的時間。
expr
被視為字串,因此如果您使用 INTERVAL
指定非字串值時請小心。例如,如果間隔指定符是 HOUR_MINUTE
,則 '6/4' 會被視為 6 小時 4 分鐘,而 6/4
會計算為 1.5000
,並被視為 1 小時 5000 分鐘。
mysql> SELECT '6/4', 6/4;
-> 1.5000
mysql> SELECT DATE_ADD('2019-01-01', INTERVAL '6/4' HOUR_MINUTE);
-> '2019-01-01 06:04:00'
mysql> SELECT DATE_ADD('2019-01-01', INTERVAL 6/4 HOUR_MINUTE);
-> '2019-01-04 12:20:00'
為了確保間隔值的解釋符合您的預期,可以使用 CAST()
操作。若要將 6/4
視為 1 小時 5 分鐘,請將其轉換為具有單一小數位數的 DECIMAL
值。
mysql> SELECT CAST(6/4 AS DECIMAL(3,1));
-> 1.5
mysql> SELECT DATE_ADD('1970-01-01 12:00:00',
-> INTERVAL CAST(6/4 AS DECIMAL(3,1)) HOUR_MINUTE);
-> '1970-01-01 13:05:00'
如果您對日期值加上或減去包含時間部分的值,結果會自動轉換為日期時間值。
mysql> SELECT DATE_ADD('2023-01-01', INTERVAL 1 DAY);
-> '2023-01-02'
mysql> SELECT DATE_ADD('2023-01-01', INTERVAL 1 HOUR);
-> '2023-01-01 01:00:00'
如果您加上 MONTH
、YEAR_MONTH
或 YEAR
,且產生的日期之日份大於新月份的最大日份,則該日份會調整為新月份的最大日份。
mysql> SELECT DATE_ADD('2019-01-30', INTERVAL 1 MONTH);
-> '2019-02-28'
日期算術運算需要完整的日期,且無法使用不完整的日期,例如 '2016-07-00'
或格式錯誤的日期。
mysql> SELECT DATE_ADD('2016-07-00', INTERVAL 1 DAY);
-> NULL
mysql> SELECT '2005-03-32' + INTERVAL 1 MONTH;
-> NULL