Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

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 代表解释数量的单位;它是一个specifier,如 HOURDAYWEEKINTERVAL 关键字和 unit specifier 不区分大小写。

以下表格显示了每个 unit 值的预期 expr 参数形式。

表 11.2 时间间隔表达式和单位参数

unit Value Expected expr Format
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 将假设您遗漏了间隔值的左侧部分。例如,如果您指定的 unitDAY_SECOND,则 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'

如果您将包含时间部分的内容添加到日期值中,结果将自动转换为 datetime 值:

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