MySQL 9.0 參考手冊  /  語言結構  /  運算式

11.5 運算式

本節列出運算式在 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 的優先順序相同。

請參閱 第 7.1.11 節,「伺服器 SQL 模式」

運算式詞彙註解

關於常值語法,請參閱 第 11.1 節,「常值」

關於識別碼語法,請參閱 第 11.2 節,「結構描述物件名稱」

變數可以是使用者變數、系統變數,或是儲存程式區域變數或參數。

param_marker?,用於預處理陳述式中的佔位符。請參閱 第 15.5.1 節,「PREPARE 陳述式」

(subquery) 表示傳回單一值的子查詢;也就是說,純量子查詢。請參閱 第 15.2.15.1 節,「作為純量運算元的子查詢」

{identifier expr} 是 ODBC 跳脫語法,為 ODBC 相容性所接受。值為 expr。語法中的 {} 大括弧應按字面寫入;它們不是語法描述中其他地方使用的後設語法。

match_expr 表示 MATCH 運算式。請參閱 第 14.9 節,「全文檢索函數」

case_expr 表示 CASE 運算式。請參閱 第 14.5 節,「流程控制函數」

interval_expr 表示時間間隔。請參閱 時間間隔

時間間隔

運算式中的 interval_expr 表示時間間隔。間隔具有以下語法

INTERVAL expr unit

expr 表示數量。unit 表示解釋數量的單位;它是一個規範,例如 HOURDAYWEEKINTERVAL 關鍵字和 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_SECONDunit,則預期 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'

如果您加入 MONTHYEAR_MONTHYEAR,且結果日期的日數大於新月份的最大日數,則該日會調整為新月份的最大日數。

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