表达式
本节列出了MySQL中表达式必须遵循的语法规则,并提供了有关表达式中可能出现的术语类型的其他信息。
- 表达式语法
- 表达术语注释
- 时间间隔
表达式语法
以下语法规则定义了MySQL中的表达式语法。此处显示的语法基于sql/sql_yacc.yyMySQL源代码分发文件中给出的语法。有关某些表达术语的更多信息,请参见表达术语注释。
expr:
    expr OR expr
  | expr || expr
  | expr XOR  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_expr SOUNDS  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_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
有关运算符的优先级,请参见“运算符的优先级”。一些运算符的优先级和含义取决于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
