本节列出了 MySQL 中表达式必须遵守的语法规则,并提供了有关表达式中可能出现的术语类型的附加信息。
以下语法规则定义了 MySQL 中的表达式语法。这里显示的语法基于 MySQL 源代码分布中的 sql/sql_yacc.yy
文件。有关某些表达式术语的附加信息,请参阅 表达式术语注释。
Press CTRL+C to copyexpr: 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 节,“模式对象名称”。
变量可以是用户变量、系统变量或存储程序局部变量或参数:
-
用户变量:第 11.4 节,“用户定义变量”
-
系统变量:第 7.1.9 节,“使用系统变量”
-
存储程序局部变量:第 15.6.4.1 节,“局部变量 DECLARE 语句”
param_marker
是 ?
,如在准备语句中用于占位符。请参阅 第 15.5.1 节,“PREPARE 语句”。
(
表示返回单个值的子查询,即标量子查询。请参阅 第 15.2.15.1 节,“子查询作为标量操作数”。subquery
)
{
是 ODBC 逃逸语法,用于 ODBC 兼容性。值是 identifier
expr
}expr
。语法中的 {
和 }
花括号应逐字写入;它们不是元语法,如语法描述中的其他地方。
match_expr
表示 MATCH
表达式。请参阅 第 14.9 节,“全文搜索函数”。
case_expr
表示一个 CASE
表达式。见 第 14.5 节,“流控制函数”。
interval_expr
代表一个时间间隔。见 时间间隔。
interval_expr
在表达式中表示一个时间间隔。时间间隔具有以下语法:
Press CTRL+C to copyINTERVAL expr unit
expr
代表一个数量。unit
代表解释数量的单位;它是一个specifier,如 HOUR
、DAY
或 WEEK
。 INTERVAL
关键字和 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()
:
Press CTRL+C to copymysql> 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
连同 +
或 -
运算符:
Press CTRL+C to copydate + INTERVAL expr unit date - INTERVAL expr unit
INTERVAL
在 expr
unit
+
运算符的任一侧都允许,如果另一个侧是日期或日期时间值。对于 -
运算符,INTERVAL
只允许在右侧,因为从日期或日期时间值中减去间隔没有意义。expr
unit
Press CTRL+C to copymysql> 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
指定符,但从日期中提取部分,而不是执行日期算术:
Press CTRL+C to copymysql> SELECT EXTRACT(YEAR FROM '2019-07-02'); -> 2019 mysql> SELECT EXTRACT(YEAR_MONTH FROM '2019-07-02 01:02:03'); -> 201907
时间间隔可以在 CREATE EVENT
语句中使用:
Press CTRL+C to copyCREATE EVENT myevent ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR DO UPDATE myschema.mytable SET mycol = mycol + 1;
如果您指定的间隔值太短(不包括从 unit
关键字期望的所有间隔部分),MySQL 将假设您遗漏了间隔值的左侧部分。例如,如果您指定的 unit
为 DAY_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 分钟:
Press CTRL+C to copymysql> 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
值:
Press CTRL+C to copymysql> 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 值:
Press CTRL+C to copymysql> 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
,并且结果日期的天数大于新月份的最大天数,则天数将被调整为新月份的最大天数:
Press CTRL+C to copymysql> SELECT DATE_ADD('2019-01-30', INTERVAL 1 MONTH); -> '2019-02-28'
日期算术操作需要完整的日期,不适用于不完整的日期,例如 '2016-07-00'
或坏格式的日期:
Press CTRL+C to copymysql> SELECT DATE_ADD('2016-07-00', INTERVAL 1 DAY); -> NULL mysql> SELECT '2005-03-32' + INTERVAL 1 MONTH; -> NULL