表达式
本节列出了MySQL中表达式必须遵循的语法规则,并提供了有关表达式中可能出现的术语类型的其他信息。
- 表达式语法
- 表达术语注释
- 时间间隔
表达式语法
以下语法规则定义了MySQL中的表达式语法。此处显示的语法基于sql/sql_yacc.yy
MySQL源代码分发文件中给出的语法。有关某些表达术语的更多信息,请参见表达术语注释。
expr: expr OR expr | expr || expr | exprXOR expr | expr AND expr | expr && expr | NOT expr | ! expr | oolean_primary IS [NOT] {TRUE | FALSE |UNKNOWN } | oolean_primary oolean_primary: oolean_primary IS [NOT] NULL | oolean_primary <=> predicate | oolean_primary comparison_operator predicate | oolean_primary comparison_operator {ALL |ANY } (subquery) | predicate comparison_operator: = | >= | > | <= | < | <> | != predicate: it_expr [NOT]IN (subquery) | it_expr [NOT]IN (expr [, expr] ...) | it_expr [NOT] BETWEEN it_expr AND predicate | it_exprSOUNDS LIKE it_expr | it_expr [NOT] LIKE simple_expr [ESCAPE simple_expr] | it_expr [NOT] REGEXP it_expr | it_expr it_expr: it_expr | it_expr | it_expr & it_expr | it_expr << it_expr | it_expr >> it_expr | it_expr + it_expr | it_expr - it_expr | it_expr * it_expr | it_expr / it_expr | it_expr DIV it_expr | it_expr MOD it_expr | it_expr % it_expr | it_expr ^ it_expr | it_expr + interval_expr | it_expr - interval_expr | simple_expr simple_expr: literal | identifier | unction_call | simple_exprCOLLATE 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
有关运算符的优先级,请参见“运算符的优先级”。一些运算符的优先级和含义取决于SQL模式:
- 默认情况下,
||
是逻辑OR
运算符。与PIPES_AS_CONCAT
启用,||
是字符串连接,与之间的优先级^
和元运算符。 - 默认情况下,
!
其优先级高于NOT
。随着HIGH_NOT_PRECEDENCE
启用,!
并且NOT
具有相同的优先级。
请参见“服务器SQL模式”。
表达术语注释
有关文字值的语法,请参见“文字值”。
有关标识符语法,请参见“模式对象名称”。
变量可以是用户变量,系统变量或存储的程序局部变量或参数:
- 用户变量:“用户定义的变量”
- 系统变量:“使用系统变量”
- 存储的程序局部变量:“局部变量DECLARE语句”
- 存储的程序参数:“ CREATE PROCEDURE和CREATE FUNCTION语句”
param_marker
是?
如在用于占位符准备语句使用。请参见“ PREPARE语句”。
(subquery)
指示返回单个值的子查询;也就是标量子查询。请参见“作为标量操作数的子查询”。
{identifierexpr}
是ODBC转义语法,并且为ODBC兼容性而接受。值是expr
。该{
和}
在语法花括号应当从字面上写的;它们不是语法描述中其他地方使用的元语法。
match_expr
表示一个MATCH
表达式。请参见“全文搜索功能”。
case_expr
表示一个CASE
表达式。请参见“流程控制语句”。
interval_expr
代表时间间隔。请参阅时间间隔。
时间间隔
interval_expr
表达式中的表示时间间隔。间隔具有以下语法:
INTERVAL expr unit
expr
代表数量。unit
代表解释数量的单位;它是一个说明符如HOUR
,DAY
,或WEEK
。该INTERVAL
关键字和unit
符不区分大小写。
下表显示了expr
每个unit
值的参数的预期形式。
表9.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 1SECOND ); -> '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
与 +
or -
运算符一起使用:
date +INTERVAL expr unit date -INTERVAL expr unit
INTERVAL exprunit
+
如果另一侧的表达式是日期或日期时间值,则在运算符的任一侧都允许使用。对于-
操作员,只允许在右侧使用,因为从间隔中减去日期或日期时间值没有意义。INTERVAL exprunit
mysql>SELECT '2018-12-31 23:59:59' +INTERVAL 1SECOND ; -> '2019-01-01 00:00:00' mysql>SELECT INTERVAL 1 DAY + '2018-12-31'; -> '2019-01-01' mysql>SELECT '2025-01-01' -INTERVAL 1SECOND ; -> '2024-12-31 23:59:59'
该EXTRACT()
函数使用与或相同的unit
说明符,但从日期中提取部分而不是执行日期算术:DATE_ADD()
DATE_SUB()
mysql>SELECT EXTRACT(YEARFROM '2019-07-02'); -> 2019 mysql>SELECT EXTRACT(YEAR_MONTH FROM '2019-07-02 01:02:03'); -> 201907
时间间隔可用于以下CREATE EVENT
语句:
CREATE EVENT myeventON SCHEDULE AT CURRENT_TIMESTAMP +INTERVAL 1HOUR DO UPDATE myschem .mytableSET 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分钟:
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/4HOUR_MINUTE ); -> '2019-01-04 12:20:00'
为了确保按期望的方式解释间隔值,CAST()
可以使用一个操作。要将其6/4
视为1小时5分钟,请将其强制转换为DECIMAL
带有一个小数位的值:
mysql>SELECT CAST(6/4AS DECIMAL(3,1)); -> 1.5 mysql>SELECT DATE_ADD('1970-01-01 12:00:00', ->INTERVAL CAST(6/4AS 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 1HOUR ); -> '2023-01-01 01:00:00'
如果添加MONTH
,YEAR_MONTH
或YEAR
,并且结果日期的天数大于新月的最大天数,则该天将调整为新月的最大天数:
mysql>SELECT DATE_ADD('2019-01-30',INTERVAL 1MONTH ); -> '2019-02-28'
日期算术运算需要完整的日期,并且不适用于不完整的日期,例如'2016-07-00'
日期严重错误或格式错误:
mysql>SELECT DATE_ADD('2016-07-00',INTERVAL 1 DAY); -> NULL mysql>SELECT '2005-03-32' +INTERVAL 1MONTH ; -> NULL