第九章语言结构
目录
本章讨论编写以下元素的规则SQL语句在使用MySQL时:
-
字符串和数字等文字值
-
标识符,如数据库、表和列名
-
关键词与保留词
-
用户定义和系统变量
-
评论意见
9.1文字值
本节描述如何在MySQL中写入文字值。这些值包括字符串、数字、十六进制和位值、布尔值和NULL
..本节还介绍了在MySQL中处理这些基本类型时可能遇到的各种细微差别。
9.1.1字符串文字
字符串是字节或字符的序列,括在单引号中('
)或双引号("
)人物。例子:
'a string' "another string"
放置在彼此旁边的引号字符串被连接到一个字符串上。以下几行是等价的:
'a string' 'a' ' ' 'string'
如果ANSI_QUOTES
启用SQL模式时,字符串文本只能在单引号中引用,因为双引号中引用的字符串被解释为标识符。
A 二进制串是字节的字符串。每个二进制字符串都有一个名为binary
..一个非二进制字符串是一串字符。它的字符集不是binary
以及与字符集兼容的排序规则。
对于这两种类型的字符串,比较都基于字符串单元的数值。对于二进制字符串,单位是字节;比较使用数字字节值。对于非二进制字符串,单位是字符,一些字符集支持多字节字符;比较使用数字字符代码值。字符代码排序是字符串排序规则的一个函数。(有关更多信息,请参见第10.8.5节,“二进制排序规则与_bin排序规则的比较”.)
字符串文字可能有一个可选的字符集引导者和COLLATE
子句,将其指定为使用特定字符集和排序规则的字符串:
[_charset_name
]'string
' [COLLATEcollation_name
]
例子:
SELECT _latin1'string
'; SELECT _binary'string
'; SELECT _utf8'string
' COLLATE utf8_danish_ci;
你可以用N'
(或literal
'n'
)在国家字符集中创建字符串。这些声明相当于:literal
'
SELECT N'some text'; SELECT n'some text'; SELECT _utf8'some text';
有关这些字符串语法形式的信息,请参阅第10.3.7节,“国家字符集”,和第10.3.8节,“字符集介绍人”.
在字符串中,某些序列具有特殊意义,除非NO_BACKSLASH_ESCAPES
启用SQL模式。这些序列中的每一个都以反斜杠开头(\
),称为转义字符..中显示的转义序列。表9.1“特殊字符逃逸序列”..对于所有其他转义序列,反斜杠将被忽略。也就是说,转义字符被解释为没有转义。例如,\x
只是x
..这些序列区分大小写。例如,\b
被解释为一个后置空间,但是\B
被解释为B
..转义处理是根据character_set_connection
系统变量即使在前面有一个指示不同字符集的引号的字符串,这也是正确的,如第10.3.6节,“字符串文字字符集和排序规则”.
表9.1特殊字符逃逸序列
逃逸序列 | 由序列表示的字符 |
---|---|
\0 | ASCII NUL(X'00' )性格 |
\' | 单引号(' )性格 |
\" | 双引号(" )性格 |
\b | 退格字符 |
\n | 换行符(行提要) |
\r | 回车字符 |
\t | 制表符字符 |
\Z | ASCII 26(控制+Z);见表后注 |
\\ | 反斜杠(\ )性格 |
\% | A % 字符;参见表后面的注释 |
\_ | A _ 字符;参见表后面的注释 |
ASCII 26字符可以编码为\Z
使您能够解决ASCII 26表示Windows上文件结束的问题.文件中的ASCII 26如果尝试使用mysql
.db_name
< file_name
这个\%
和\_
序列用于搜索%
和_
在模式匹配上下文中,否则它们将被解释为通配符。请参阅LIKE
运算符12.5.1节,“字符串比较函数”..如果你用\%
或\_
在模式匹配上下文之外,它们计算字符串。\%
和\_
,而不是%
和_
.
有几种方法可以在字符串中包括引号字符:
-
A
'
引用的字符串中'
可以写成''
. -
A
"
引用的字符串中"
可以写成""
. -
在引号字符前面加上转义字符(
\
). -
A
'
引用的字符串中"
不需要特殊治疗,也不需要加倍或逃跑。以同样的方式,"
引用的字符串中'
不需要特殊治疗。
以下内容SELECT
语句展示了引用和逃避工作的方式:
mysql>SELECT 'hello', '"hello"', '""hello""', 'hel''lo', '\'hello';
+-------+---------+-----------+--------+--------+ | hello | "hello" | ""hello"" | hel'lo | 'hello | +-------+---------+-----------+--------+--------+ mysql>SELECT "hello", "'hello'", "''hello''", "hel""lo", "\"hello";
+-------+---------+-----------+--------+--------+ | hello | 'hello' | ''hello'' | hel"lo | "hello | +-------+---------+-----------+--------+--------+ mysql>SELECT 'This\nIs\nFour\nLines';
+--------------------+ | This Is Four Lines | +--------------------+ mysql>SELECT 'disappearing\ backslash';
+------------------------+ | disappearing backslash | +------------------------+
将二进制数据插入字符串列(例如BLOB
列),则应使用转义序列表示某些字符。反斜杠\
),用于引用字符串的引号字符必须转义。在某些客户端环境中,也可能需要逃避。NUL
或控制+Z。MySQL客户端截断引用的字符串,其中包含NUL
如果没有转义字符,则可以选择Control+Z,如果不转义,则可以在Windows上作为文件结束。有关表示每个字符的转义序列,请参见表9.1“特殊字符逃逸序列”.
在编写应用程序时,在将字符串用作发送到MySQL服务器的SQL语句中的数据值之前,必须正确转义任何可能包含这些特殊字符的字符串。你可以用两种方式来做:
-
使用转义特殊字符的函数处理字符串。在C程序中,可以使用
mysql_real_escape_string_quote()
c API函数来转义字符。看见第27.8.7.56节,“MySQL_REAL_LEXING_STRING_QUERE()”..在构造其他SQL语句的SQL语句中,可以使用QUOTE()
功能。perl dbi接口提供了一个quote
方法将特殊字符转换为正确的转义序列。看见第27.10节,“MySQL Perl API”..其他语言接口可能提供类似的功能。 -
作为显式转义特殊字符的替代方法,许多MySQLAPI提供了占位符功能,使您能够将特殊标记插入语句字符串,然后在发出语句时将数据值绑定到它们。在本例中,API负责为您转义值中的特殊字符。
9.1.2数字文字
数字文字包括精确值(整数和DECIMAL
)文字和近似值(浮点)文字.
整数表示为数字序列。数字可能包括.
作为小数分隔符。数字之前可以-
或+
分别表示负值或正值。用带尾数和指数的科学表示法表示的数字是近似值数.
精确值数字文字有整数部分或小数部分,或两者兼有.他们可能会被签署。例子:1
, .2
, 3.4
, -5
, -6.78
, +9.10
.
近似值数字文字用一个尾数和指数的科学表示法表示.其中一部份或两部份均可签署。例子:1.2E3
, 1.2E-3
, -1.2E3
,-1.2E-3
.
两个看起来类似的数字可能会被不同的对待。例如,2.34
是一个精确的值(不动点)数,而2.34E0
是一个近似值(浮点)数字.
这个DECIMAL
数据类型是定点类型,计算是精确的.在MySQL中,DECIMAL
类型有几个同义词:NUMERIC
, DEC
,FIXED
..整数类型也是精确值类型.有关精确值计算的详细信息,请参阅第12.22节,“精确数学”.
这个FLOAT
和DOUBLE
数据类型是浮点类型,计算是近似的.在MySQL中,与FLOAT
或DOUBLE
是DOUBLE PRECISION
和REAL
.
整数可以在浮点上下文中使用;它被解释为等效的浮点数。
9.1.3日期和时间文字
日期和时间值可以用几种格式表示,例如引用字符串或数字,具体取决于值的确切类型和其他因素。例如,在MySQL期望日期的上下文中,它解释'2015-07-21'
, '20150721'
,和20150721
作为约会。
本节描述日期和时间文本的可接受格式。有关时间数据类型(如允许值的范围)的更多信息,请参阅以下部分:
标准SQL和ODBC日期和时间文字。标准SQL允许使用类型关键字和字符串指定时间文本。关键字和字符串之间的空格是可选的。
DATE 'str
' TIME 'str
' TIMESTAMP 'str
'
MySQL识别这些构造以及相应的ODBC语法:
{ d 'str
' } { t 'str
' } { ts 'str
' }
MySQL使用type关键字,这些构造生成DATE
, TIME
,和DATETIME
值,如果指定,则分别包括尾随小数秒部分。这个TIMESTAMP
语法生成一个DATETIME
值在MySQL中,因为DATETIME
具有与标准sql更接近的范围。TIMESTAMP
类型,其年范围从0001
到9999
..(MySQLTIMESTAMP
年份范围是1970
到2038
.)
日期和时间上下文中的字符串和数字文字。MySQL识别DATE
这些格式的值:
-
中的字符串
'YYYY-MM-DD'
或'YY-MM-DD'
格式。一个“放松”语法是允许的:任何标点符号都可以用作日期部分之间的分隔符。例如,'2012-12-31'
,'2012/12/31'
,'2012^12^31'
,和'2012@12@31'
都是等价物。 -
中没有分隔符的字符串。
'YYYYMMDD'
或'YYMMDD'
格式,只要字符串作为日期具有意义。例如,'20070523'
和'070523'
被解释为'2007-05-23'
,但是'071332'
是非法的(它有荒谬的月份和白天的部分)并成为'0000-00-00'
. -
作为一个数字
YYYYMMDD
或YYMMDD
格式,只要数字作为日期是有意义的。例如,19830905
和830905
被解释为'1983-09-05'
.
MySQL识别DATETIME
和TIMESTAMP
这些格式的值:
-
中的字符串
'YYYY-MM-DD HH:MM:SS'
或'YY-MM-DD HH:MM:SS'
格式。一个“放松”这里也允许语法:任何标点符号都可以用作日期部分或时间部分之间的分隔符。例如,'2012-12-31 11:30:45'
,'2012^12^31 11+30+45'
,'2012/12/31 11*30*45'
,和'2012@12@31 11^30^45'
都是等价物。日期和时间部分与小数秒部分之间唯一可识别的分隔符是小数点。
日期和时间部分可由
T
而不是一个空间。例如,'2012-12-31 11:30:45'
'2012-12-31T11:30:45'
都是等价物。 -
中没有分隔符的字符串。
'YYYYMMDDHHMMSS'
或'YYMMDDHHMMSS'
格式,只要字符串作为日期具有意义。例如,'20070523091528'
和'070523091528'
被解释为'2007-05-23 09:15:28'
,但是'071122129015'
是非法的(它有一个荒谬的分钟部分)并成为'0000-00-00 00:00:00'
. -
作为一个数字
YYYYMMDDHHMMSS
或YYMMDDHHMMSS
格式,只要数字作为日期是有意义的。例如,19830905132800
和830905132800
被解释为'1983-09-05 13:28:00'
.
A DATETIME
或TIMESTAMP
值可以包括以微秒(6位)精度为单位的尾随小数秒部分。小数部分应始终用小数点与其余时间分隔;没有其他小数秒分隔符。有关MySQL中支持小数秒的信息,请参阅第11.3.6节,“分数秒的时间值”.
包含两位数年份值的日期是不明确的,因为世纪是未知的。MySQL使用以下规则解释两位数的年份值:
-
范围内的年份值
70-99
转换成1970-1999
. -
范围内的年份值
00-69
转换成2000-2069
.
对于指定为包含日期部分分隔符的字符串的值,没有必要为小于日期部分分隔符的月份或日值指定两位数。10
.'2015-6-9'
是相同的'2015-06-09'
..类似地,对于指定为包含时间部分分隔符的字符串的值,没有必要为小时、分钟或第二个小于时间部分分隔符的值指定两位数。10
. '2015-10-30 1:2:3'
是相同的'2015-10-30 01:02:03'
.
指定为数字的值应该是6、8、12或14位长。如果一个数字有8或14位长,则假定为YYYYMMDD
或YYYYMMDDHHMMSS
格式和年份由前4位数字表示。如果该数字为6或12位长,则假定为YYMMDD
或YYMMDDHHMMSS
格式和年份由前2位数字表示。不是这些长度之一的数字被解释为用前导零填充到最近的长度。
指定为非分隔字符串的值将根据其长度进行解释。对于长度为8或14个字符的字符串,假定年份由前4个字符指定。否则,假设年份由前两个字符指定。字符串从左到右进行解释,以查找年份、月、日、小时、分钟和第二个值,以查找字符串中存在的尽可能多的部分。这意味着您不应该使用少于6个字符的字符串。例如,如果指定'9903'
,表示1999年3月,MySQL将其转换为“零”日期值这是因为年份和月份的值是99
和03
但是白天的部分已经完全消失了。但是,您可以显式地指定一个值为零来表示缺少的月或日部分。例如,要插入值'1999-03-00'
,使用'990300'
.
MySQL识别TIME
这些格式的值:
-
作为字符串
'D HH:MM:SS'
格式。您还可以使用以下内容之一“放松”语法:'HH:MM:SS'
,'HH:MM'
,'D HH:MM'
,'D HH'
,或'SS'
..这里D
表示天数,并且可以有一个从0到34的值。 -
中没有分隔符的字符串。
'HHMMSS'
格式,只要它作为一段时间是有意义的。例如,'101112'
被理解为'10:11:12'
,但是'109712'
是非法的(它有一个荒谬的分钟部分)并成为'00:00:00'
. -
作为一个数字
HHMMSS
格式,只要它作为一段时间是有意义的。例如,101112
被理解为'10:11:12'
..还可理解以下替代格式:SS
,MMSS
,或HHMMSS
.
后面的小数秒部分在'D HH:MM:SS.fraction'
, 'HH:MM:SS.fraction'
, 'HHMMSS.fraction'
,和HHMMSS.fraction
时间格式fraction
是以微秒(6位)精度为单位的小数部分。小数部分应始终用小数点与其余时间分隔;没有其他小数秒分隔符。有关MySQL中支持小数秒的信息,请参阅第11.3.6节,“分数秒的时间值”.
为TIME
值指定为包含时间部分分隔符的字符串,因此不需要为小于小时、分钟或秒的值指定两位数。10
. '8:3:2'
是相同的'08:03:02'
.
9.1.4十六进制文字
十六进制的文字值是用X'
或val
'0x
符号,在哪里val
val
包含十六进制数字(0..9
, A..F
)。数字和任何前导的字母大写X
不重要。领军0x
是区分大小写的,不能写为0X
.
合法十六进制文字:
X'01AF' X'01af' x'01AF' x'01af' 0x01AF 0x01af
非法十六进制文字:
X'0G' (G is not a hexadecimal digit) 0X01AF (0X must be written as 0x)
使用X'
符号必须包含偶数位数或出现语法错误。若要更正此问题,请使用前导零填充该值:val
'
mysql>SET @s = X'FFF';
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'X'FFF'' mysql>SET @s = X'0FFF';
Query OK, 0 rows affected (0.00 sec)
使用0x
包含奇数位数的表示法被视为具有额外的前导。val
0
..例如,0xaaa
被解释为0x0aaa
.
默认情况下,十六进制文字是二进制字符串,其中每一对十六进制数字表示一个字符:
mysql>SELECT X'4D7953514C', CHARSET(X'4D7953514C');
+---------------+------------------------+ | X'4D7953514C' | CHARSET(X'4D7953514C') | +---------------+------------------------+ | MySQL | binary | +---------------+------------------------+ mysql>SELECT 0x5461626c65, CHARSET(0x5461626c65);
+--------------+-----------------------+ | 0x5461626c65 | CHARSET(0x5461626c65) | +--------------+-----------------------+ | Table | binary | +--------------+-----------------------+
十六进制文字可能有一个可选的字符集介绍器和COLLATE
子句,将其指定为使用特定字符集和排序规则的字符串:
[_charset_name
] X'val
' [COLLATEcollation_name
]
例子:
SELECT _latin1 X'4D7953514C'; SELECT _utf8 0x4D7953514C COLLATE utf8_danish_ci;
示例使用X'
符号,但是val
'0x
符号也允许介绍。有关介绍人的信息,请参阅第10.3.8节,“字符集介绍人”.val
在数值上下文中,MySQL将十六进制文本视为BIGINT
(64位整数)。若要确保十六进制文字的数值处理,请在数字上下文中使用它。这样做的方法包括添加0或使用CAST(... AS UNSIGNED)
..例如,分配给用户定义变量的十六进制文字默认是二进制字符串.若要将值赋值为数字,请在数字上下文中使用它:
mysql>SET @v1 = X'41';
mysql>SET @v2 = X'41'+0;
mysql>SET @v3 = CAST(X'41' AS UNSIGNED);
mysql>SELECT @v1, @v2, @v3;
+------+------+------+ | @v1 | @v2 | @v3 | +------+------+------+ | A | 65 | 65 | +------+------+------+
空十六进制值(X''
)计算结果为零长度二进制字符串。转换成一个数字,它产生0:
mysql>SELECT CHARSET(X''), LENGTH(X'');
+--------------+-------------+ | CHARSET(X'') | LENGTH(X'') | +--------------+-------------+ | binary | 0 | +--------------+-------------+ mysql>SELECT X''+0;
+-------+ | X''+0 | +-------+ | 0 | +-------+
这个X'
符号是基于标准SQL的。这个val
'0x
表示法是基于odbc的,对于odbc,通常使用十六进制字符串来提供BLOB
柱子。
若要将字符串或数字转换为十六进制格式的字符串,请使用HEX()
职能:
mysql>SELECT HEX('cat');
+------------+ | HEX('cat') | +------------+ | 636174 | +------------+ mysql>SELECT X'636174';
+-----------+ | X'636174' | +-----------+ | cat | +-----------+
9.1.5位值文字
位值文字是使用b'
或val
'0b
符号。val
val
是使用零和1编写的二进制值。任何前导字母b
不重要。领军0b
是区分大小写的,不能写为0B
.
法律位值文字:
b'01' B'01' 0b01
非法位值文字:
b'2' (2 is not a binary digit) 0B01 (0B must be written as 0b)
默认情况下,位值文字是二进制字符串:
mysql>SELECT b'1000001', CHARSET(b'1000001');
+------------+---------------------+ | b'1000001' | CHARSET(b'1000001') | +------------+---------------------+ | A | binary | +------------+---------------------+ mysql>SELECT 0b1100001, CHARSET(0b1100001);
+-----------+--------------------+ | 0b1100001 | CHARSET(0b1100001) | +-----------+--------------------+ | a | binary | +-----------+--------------------+
位值文字可能有一个可选的字符集引导者和COLLATE
子句,将其指定为使用特定字符集和排序规则的字符串:
[_charset_name
] b'val
' [COLLATEcollation_name
]
例子:
SELECT _latin1 b'1000001'; SELECT _utf8 0b1000001 COLLATE utf8_danish_ci;
示例使用b'
符号,但是val
'0b
符号也允许介绍。有关介绍人的信息,请参阅第10.3.8节,“字符集介绍人”.val
在数字上下文中,MySQL将一点文字视为整数。若要确保对位文字进行数值处理,请在数字上下文中使用它。这样做的方法包括添加0或使用CAST(... AS UNSIGNED)
..例如,在默认情况下,分配给用户定义变量的位文字是二进制字符串.若要将值赋值为数字,请在数字上下文中使用它:
mysql>SET @v1 = b'1100001';
mysql>SET @v2 = b'1100001'+0;
mysql>SET @v3 = CAST(b'1100001' AS UNSIGNED);
mysql>SELECT @v1, @v2, @v3;
+------+------+------+ | @v1 | @v2 | @v3 | +------+------+------+ | a | 97 | 97 | +------+------+------+
空位值(b''
)计算结果为零长度二进制字符串。转换成一个数字,它产生0:
mysql>SELECT CHARSET(b''), LENGTH(b'');
+--------------+-------------+ | CHARSET(b'') | LENGTH(b'') | +--------------+-------------+ | binary | 0 | +--------------+-------------+ mysql>SELECT b''+0;
+-------+ | b''+0 | +-------+ | 0 | +-------+
位值表示法便于指定要分配给的值。BIT
栏:
mysql>CREATE TABLE t (b BIT(8));
mysql>INSERT INTO t SET b = b'11111111';
mysql>INSERT INTO t SET b = b'1010';
mysql>INSERT INTO t SET b = b'0101';
结果集中的位值作为二进制值返回,可能显示得不好。若要将位值转换为可打印形式,请在数值上下文中使用该值,或使用转换函数(如BIN()
或HEX()
..转换后的值中不显示高阶0位数.
mysql> SELECT b+0, BIN(b), OCT(b), HEX(b) FROM t;
+------+----------+--------+--------+
| b+0 | BIN(b) | OCT(b) | HEX(b) |
+------+----------+--------+--------+
| 255 | 11111111 | 377 | FF |
| 10 | 1010 | 12 | A |
| 5 | 101 | 5 | 5 |
+------+----------+--------+--------+
9.1.6布尔文字
常数TRUE
和FALSE
评估到1
和0
分别。常量名称可以用任何字母写成。
mysql> SELECT TRUE, true, FALSE, false;
-> 1, 1, 0, 0
9.1.7空值
这个NULL
价值手段“没有数据。” NULL
可以用任何字母写。同义词是\N
(区分大小写)。对.的处理\N
作为同义词NULL
在SQL中,语句在MySQL5.7.18中不再受欢迎,并在MySQL8.0中被删除;NULL
相反。
请注意,NULL
值与诸如0
对于数值类型或字符串类型的空字符串。有关更多信息,请参见第B.6.4.3节,“空值问题”.
执行的文本文件导入或导出操作LOAD DATA INFILE
或SELECT ... INTO OUTFILE
, NULL
由\N
顺序。看见第13.2.6节,“加载数据信息语法”..使用\N
在文本文件中,不受\N
在SQL语句中。
用于分类ORDER BY
, NULL
值排序在升序排序的其他值之前,降序排序的其他值之后。
9.2架构对象名称
MySQL中的某些对象(包括数据库、表、索引、列、别名、视图、存储过程、分区、表空间和其他对象名称)称为标识符。本节描述MySQL中允许的标识符语法。第9.2.2节,“标识大小写敏感性”,描述哪些类型的标识符区分大小写,以及在何种条件下。
标识符可以引用,也可以不引用。如果标识符包含特殊字符或保留字,则必只要你提到它,就引用它。(例外:限定名中句点后面的保留字必须是标识符,因此不需要引用。)保留字列在第9.3节,“关键词和保留词”.
标识符在内部转换为Unicode。它们可能包含以下字符:
-
未引号标识符中允许的字符:
-
ASCII:[0-9,a-z,A-Z$_](基本拉丁字母,数字0-9,美元,下划线)
-
扩展:U+0080.U+FFFF
-
-
引号中允许的字符包括完整的Unicode基本多语言平面(BMP),但U+0000除外:
-
ASCII:U+0001.U+007F
-
扩展:U+0080.U+FFFF
-
-
ASCII NUL(U+0000)和补充字符(U+10000及更高)不允许在引号或非引用标识符中使用。
-
标识符可以数字开头,但除非引用,否则不能仅由数字组成。
-
数据库、表和列名不能以空格字符结尾。
标识符引号字符是回勾符(`
):
mysql> SELECT * FROM `select` WHERE `select`.id > 100;
如果ANSI_QUOTES
启用SQL模式时,还允许在双引号中引用标识符:
mysql>CREATE TABLE "test" (col INT);
ERROR 1064: You have an error in your SQL syntax... mysql>SET sql_mode='ANSI_QUOTES';
mysql>CREATE TABLE "test" (col INT);
Query OK, 0 rows affected (0.00 sec)
这个ANSI_QUOTES
模式使服务器将双引号字符串解释为标识符。因此,当启用此模式时,字符串文本必须用单引号括起来。它们不能用双引号括起来。服务器sql模式被控制,如第5.1.10节,“服务器SQL模式”.
如果引用标识符,则可以将标识符引号字符包括在标识符中。如果要包含在标识符中的字符与引用标识符本身的字符相同,则需要将该字符加倍。下面的语句创建一个名为a`b
,它包含一个名为c"d
:
mysql> CREATE TABLE `a``b` (`c"d` INT);
在查询的选择列表中,可以使用标识符或字符串引用字符指定引用的列别名:
mysql> SELECT 1 AS `one`, 2 AS 'two';
+-----+-----+
| one | two |
+-----+-----+
| 1 | 2 |
+-----+-----+
在语句的其他地方,引用对别名的引用必须使用标识符引用,否则引用将被视为字符串文本。
建议您不要使用以
或M
e
,在哪里M
eN
M
和N
是整数。例如,避免使用1e
作为标识符,因为表达式如1e+3
是模棱两可的。根据上下文,它可能被解释为表达式。1e + 3
或者作为数字1e+3
.
使用时要小心MD5()
生成表名,因为它可以生成非法或模棱两可的名称,如刚才描述的名称。
用户变量不能直接在SQL语句中用作标识符或标识符的一部分。看见第9.4节,“用户定义的变量”,以获得更多的信息和解决方法的示例。
数据库和表名中的特殊字符在相应的文件系统名称中编码,如第9.2.3节,“将标识符映射到文件名”..如果您的数据库或表来自MySQL的旧版本,这些数据库或表包含特殊字符,并且基础目录名或文件名尚未更新以使用新编码,则服务器将显示它们的名称,前缀为#mysql50#
..有关引用此类名称或将其转换为较新的编码的信息,请参阅该节。
下表描述了每种类型标识符的最大长度。
标识符类型 | 最大长度(字符) |
---|---|
数据库 | 64 (NDB 储存引擎:63) |
表 | 64 (NDB 储存引擎:63) |
列 | 64 |
指数 | 64 |
约束 | 64 |
存储程序 | 64 |
视点 | 64 |
表空间 | 64 |
服务器 | 64 |
日志文件组 | 64 |
化名 | 256(见下表例外情况) |
复合语句标号 | 16 |
用户定义变量 | 64 |
中列名的别名CREATE VIEW
语句的最大列长度为64个字符(而不是256个字符的最大别名长度)。
标识符使用Unicode(UTF-8)存储。中存储的表定义中的标识符。.frm
中的授予表中存储的文件和标识符。mysql
数据库。授予表中标识符字符串列的大小以字符度量。您可以使用多字节字符,而不需要减少这些列中存储的值所允许的字符数。如前所述,允许的Unicode字符是基本多语言平面(BMP)中的字符。不允许补充字符。
NDB群集为数据库和表的名称规定了63个字符的最大长度。看见第21.1.7.5节,“NDB群集中与数据库对象相关的限制”.
9.2.1标识符限定符
对象名称可以是不限定的,也可以是限定的。在对名称的解释明确的上下文中,允许使用不限定的名称。限定名包括至少一个限定符,通过覆盖默认上下文或提供缺失上下文来澄清解释性上下文。
例如,此语句使用非限定名创建一个表。t1
:
CREATE TABLE t1 (i INT);
因为t1
不包括用于指定数据库的限定符,则语句将在默认数据库中创建表。如果没有默认数据库,则会发生错误。
此语句使用限定名创建表。db1.t1
:
CREATE TABLE db1.t1 (i INT);
因为db1.t1
包括数据库限定符db1
,则该语句将创建t1
在名为db1
,而不管默认数据库是什么。限定符必如果没有默认数据库,则指定。限定符可以,可能如果存在默认数据库,则指定该数据库,指定与默认数据库不同的数据库,或如果默认数据库与指定的数据库相同,则指定该数据库显式。
限定符具有以下特点:
-
非限定名由单个标识符组成。限定名由多个标识符组成。
-
多部分名称的组件必须用句点分隔(
.
)人物。多部分名称的初始部分充当限定符,影响要解释最终标识符的上下文。 -
限定符字符是一个单独的令牌,不需要与关联的标识符相邻。例如,
tbl_name.col_name
和tbl_name . col_name
都是等价物。 -
如果多部分名称的任何组件需要引用,请单独引用它们,而不是引用整个名称。例如,编写
`my-table`.`my-column`
,不是`my-table.my-column`
. -
限定名中的句点后面的保留字必须是标识符,因此在这种情况下不需要引用它。
-
语法
意思是桌子.tbl_name
tbl_name
在默认数据库中。注
这种语法在MySQL5.7.20中被取消,并将在MySQL的未来版本中删除。
对象名称的允许限定符取决于对象类型:
-
数据库名称是完全限定的,不带限定符:
CREATE DATABASE db1;
-
表、视图或存储的程序名可以被赋予数据库名限定符.中的非限定名和限定名的示例
CREATE
发言:CREATE TABLE mytable ...; CREATE VIEW myview ...; CREATE PROCEDURE myproc ...; CREATE FUNCTION myfunc ...; CREATE EVENT myevent ...; CREATE TABLE mydb.mytable ...; CREATE VIEW mydb.myview ...; CREATE PROCEDURE mydb.myproc ...; CREATE FUNCTION mydb.myfunc ...; CREATE EVENT mydb.myevent ...;
-
触发器与表相关联,因此任何限定符都适用于表名:
CREATE TRIGGER mytrigger ... ON mytable ...; CREATE TRIGGER mytrigger ... ON mydb.mytable ...;
-
一个列名可以被赋予多个限定符,以指示引用它的语句中的上下文,如下表所示。
列参考 意义 col_name
列 col_name
从语句中使用的任何表中包含该名称的列。tbl_name.col_name
列 col_name
从桌子上tbl_name
默认数据库的db_name.tbl_name.col_name
列 col_name
从桌子上tbl_name
数据库的db_name
换句话说,列名可以被赋予一个表名限定符,而表名限定符本身也可以被赋予一个数据库名限定符。中不合格和限定列引用的示例。
SELECT
发言:SELECT c1 FROM mytable WHERE c2 > 100; SELECT mytable.c1 FROM mytable WHERE mytable.c2 > 100; SELECT mydb.mytable.c1 FROM mydb.mytable WHERE mydb.mytable.c2 > 100;
除非限定引用不明确,否则不需要为语句中的对象引用指定限定符。假设那列c1
仅发生在表中。t1
, c2
只在t2
,和c
两种t1
和t2
..任何无条件的提述c
在引用两个表并必须限定为t1.c
或t2.c
要指出您指的是哪个表:
SELECT c1, c2, t1.c FROM t1 INNER JOIN t2 WHERE t2.c > 100;
类似地,从表中检索t
在数据库中db1
从桌子上t
在数据库中db2
在同一条语句中,必须限定表引用:对于那些表中列的引用,仅对出现在两个表中的列名需要限定符。假设那列c1
仅发生在表中。db1.t
, c2
只在db2.t
,和c
两种db1.t
和db2.t
..在这种情况下,c
是模棱两可的,必须是限定的,但是c1
和c2
不必是:
SELECT c1, c2, db1.t.c FROM db1.t INNER JOIN db2.t WHERE db2.t.c > 100;
表别名可以编写更简单的限定列引用:
SELECT c1, c2, t1.c FROM db1.t AS t1 INNER JOIN db2.t AS t2 WHERE t2.c > 100;
9.2.2标识大小写敏感性
在MySQL中,数据库对应于数据目录中的目录。数据库中的每个表对应于数据库目录中的至少一个文件(可能更多,取决于存储引擎)。触发器也对应于文件。因此,底层操作系统的大小写敏感性在数据库、表和触发器名称的区分大小写方面起着重要作用。这意味着这些名称在Windows中不区分大小写,但在大多数Unix变体中都是区分大小写的。一个值得注意的例外是MacOS,它基于Unix,但使用不区分大小写的默认文件系统类型(hfs+)。然而,MacOS也支持UFS卷,它和任何Unix一样区分大小写.看见第1.8.1节,“MySQL对标准SQL的扩展”..这个lower_case_table_names
系统变量还会影响服务器处理标识符大小写敏感性的方式,如本节后面部分所述。
注
虽然数据库、表和触发器的名称在某些平台上不区分大小写,但是您不应该在同一语句中使用不同的情况来引用其中的一个。下面的语句不能工作,因为它引用了一个表,这两个表都是my_table
和ASMY_TABLE
:
mysql> SELECT * FROM my_table WHERE MY_TABLE.col=1;
列、索引、存储例程和事件名称在任何平台上都不区分大小写,列别名也不敏感。
但是,日志文件组的名称是区分大小写的.这与标准SQL不同。
默认情况下,表别名在Unix上是区分大小写的,而在Windows或MacOS上则不然.以下语句不能在Unix上工作,因为它将别名引用为a
和ASA
:
mysql>SELECT
col_name
FROMtbl_name
AS aWHERE a.
col_name
= 1 OR A.col_name
= 2;
但是,Windows上允许使用相同的语句。为了避免这种差异造成的问题,最好采用一致的约定,例如始终使用小写名称创建和引用数据库和表。为了最大限度地提高可移植性和易用性,建议使用此约定。
表和数据库名称存储在磁盘上并在MySQL中使用的方式受到lower_case_table_names
系统变量,启动时可以设置该变量。米舍尔德. lower_case_table_names
可以接受下表中所示的值。这个变量不影响触发器标识符的大小写敏感性。在unix上,默认值为lower_case_table_names
是0。在Windows上,默认值为1。在MacOS上,默认值是2。
价值 | 意义 |
---|---|
0 | 表和数据库名称存储在磁盘上,使用CREATE TABLE 或CREATE DATABASE 声明。名称比较区分大小写。你应该不如果在具有不区分大小写的文件名(如Windows或MacOS)的系统上运行MySQL,则将此变量设置为0。如果将此变量强制为0,则--lower-case-table-names=0 不区分大小写的文件系统和访问MyISAM 使用不同字母大小写的表名,可能会导致索引损坏。 |
1 | 表名以小写形式存储在磁盘上,名称比较不区分大小写.MySQL在存储和查找时将所有表名转换为小写。此行为也适用于数据库名称和表别名。 |
2 | 表和数据库名称存储在磁盘上,使用CREATE TABLE 或CREATE DATABASE 语句,但是MySQL在查找时将它们转换为小写。名称比较不区分大小写。这行得通只在不区分大小写的文件系统上!InnoDB 表名和视图名称以小写形式存储,如lower_case_table_names=1 . |
如果只在一个平台上使用MySQL,则通常不必更改lower_case_table_names
变量的默认值。但是,如果要在文件系统区分大小写不同的平台之间传输表,则可能会遇到困难。例如,在unix上,可以有两个不同的表名为my_table
和MY_TABLE
,但在Windows上,这两个名称被认为是相同的。为了避免数据库或表名的字母大小写引起的数据传输问题,您有两个选项:
-
使用
lower_case_table_names=1
在所有系统上。这样做的主要缺点是当您使用SHOW TABLES
或SHOW DATABASES
,您看不到它们原来的字母中的名称。 -
使用
lower_case_table_names=0
关于Unix和lower_case_table_names=2
在窗户上。这保留了数据库和表名的字母大小写。这样做的缺点是,必须确保语句始终引用数据库和表名,并在Windows上使用正确的字母。如果将语句传输到Unix(其中的字母大小写很重要),则如果字母大小写不正确,它们就无法工作。例外*如果您正在使用
InnoDB
表和您试图避免这些数据传输问题,您应该设置lower_case_table_names
将所有平台上的名称转换为1,以强制将名称转换为小写。
如果您计划设置lower_case_table_names
在unix上,系统变量为1,在停止之前,必须先将旧数据库和表名转换为小写。米舍尔德并使用新变量设置重新启动它。若要对单个表执行此操作,请使用RENAME TABLE
:
RENAME TABLE T1 TO t1;
若要转换一个或多个完整数据库,请在设置lower_case_table_names
,然后删除数据库,并在设置后重新加载它们。lower_case_table_names
:
-
使用mysqldump要转储每个数据库:
mysqldump --databases db1 > db1.sql mysqldump --databases db2 > db2.sql ...
对必须重新创建的每个数据库执行此操作。
-
使用
DROP DATABASE
删除每个数据库。 -
停止服务器,设置
lower_case_table_names
,并重新启动服务器。 -
重新加载每个数据库的转储文件。因为
lower_case_table_names
设置后,每个数据库和表名将在重新创建时转换为小写:mysql < db1.sql mysql < db2.sql ...
根据二进制排序规则,如果对象名称的大写形式相等,则可视为重复名称。对于游标、条件、过程、函数、保存点、存储的例程参数、存储的程序局部变量和插件的名称,这是正确的。列的名称、约束、数据库、分区、用PREPARE
、表、触发器、用户和用户定义的变量。
文件系统区分大小写会影响在INFORMATION_SCHEMA
桌子。有关更多信息,请参见第10.8.7节,“在信息模式搜索中使用排序规则”.
9.2.3将标识符映射到文件名
数据库和表标识符以及文件系统中的名称之间存在对应关系。对于基本结构,MySQL将每个数据库表示为数据目录中的一个目录,每个表由适当数据库目录中的一个或多个文件表示。表格式文件(.FRM
),数据总是存储在这个结构和位置中。
对于数据和索引文件,磁盘上的确切表示形式是特定于存储引擎的。这些文件可以存储在与FRM
文件或信息可以存储在单独的文件中。InnoDB
数据存储在InnoDB数据文件中。如果您使用表空间InnoDB
,然后使用您创建的特定表空间文件。
任何字符在数据库或表标识符中都是合法的,但ASCII NUL除外(X'00'
)。MySQL对在创建数据库目录或表文件时在相应的文件系统对象中出现问题的任何字符进行编码:
-
基本拉丁文字母(
a..zA..Z
),数字(0..9
)和下划线(_
)按原样编码。因此,它们的大小写敏感性直接取决于文件系统的特性。 -
如下表所示,大写/小写映射字母中的所有其他国家字母都进行了编码。“代码范围”列中的值为UCS-2值.
编码范围 花纹 数 使用 未用 砌块 00C0.017 F [@][0.4][g.z] 5*20= 100 97 3 拉丁文-1补编+拉丁文扩展-A 0370.03 FF [@][5.9][g.z] 5*20= 100 88 12 希腊语和科普特语 0400.052 F [@][g.z][0.6] 20*7= 140 137 3 西里尔+西里尔补充物 0530.058 F [@][g.z][7.8] 20*2= 40 38 2 亚美尼亚人 2160.217 F [@][g.z][9] 20*1= 20 16 4 数字形式 0180.02AF [@][g.z][a.k] 20*11=220 203 17 拉丁文扩展-B+IPA扩展 1E00.1 EFF [@][g.z][l.r] 20*7= 140 136 4 拉丁文扩展额外 1 F00.1 FFF [@][g.z][s.z] 20*8= 160 144 16 希腊扩展 .... .... [@][a.f][g.z] 6*20= 120 0 120 预留 24B6.24E9 [@][a.z] 26 26 0 封闭字母数字 FF 21.FF5A [@][a.z][@] 26 26 0 半宽和全宽形式 序列中的一个字节编码字母大小写。例如:
LATIN CAPITAL LETTER A WITH GRAVE
编码为@0G
,鉴于LATIN SMALL LETTER A WITH GRAVE
编码为@0g
..这里是第三个字节(G
或g
)表示字母大小写。(在不区分大小写的文件系统中,这两个字母将被视为相同。)对于某些块,如Cyrilic,第二个字节决定字母大小写。对于其他块,如拉丁语1补编,第三个字节决定字母大小写。如果序列中的两个字节是字母(如希腊语扩展的那样),则最左边的字母字符表示字母大小写。所有其他字母字节必须是小写的。
-
除下划线外,所有非字母字符(
_
),以及没有大写/小写映射的字母(如希伯来语)使用十六进制表示方式对十六进制数字使用小写字母进行编码。a..f
:0x003F -> @003f 0xFFFF -> @ffff
十六进制值对应于
ucs2
双字节字符集。
在Windows上,一些名称如nul
, prn
,和aux
通过追加编码@@@
到服务器创建相应文件或目录时的名称。这发生在所有平台上,以便在平台之间实现相应的数据库对象的可移植性。
如果您的MySQL版本中的数据库或表包含特殊字符,且其基础目录名或文件名尚未更新以使用新编码,则服务器将显示它们的名称,前缀为#mysql50#
在输出中INFORMATION_SCHEMA
表或SHOW
陈述。例如,如果您有一个名为a@b
它的名字编码还没有更新,SHOW TABLES
显示如下:
mysql> SHOW TABLES;
+----------------+
| Tables_in_test |
+----------------+
| #mysql50#a@b |
+----------------+
若要引用编码尚未更新的名称,必须提供#mysql50#
前缀:
mysql>SHOW COLUMNS FROM `a@b`;
ERROR 1146 (42S02): Table 'test.a@b' doesn't exist mysql>SHOW COLUMNS FROM `#mysql50#a@b`;
+-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | i | int(11) | YES | | NULL | | +-------+---------+------+-----+---------+-------+
若要更新旧名称以避免使用特殊前缀引用它们,请用mysqleck..以下命令将所有名称更新为新编码:
mysqlcheck --check-upgrade --all-databases mysqlcheck --fix-db-names --fix-table-names --all-databases
若要只检查特定的数据库或表,请省略--all-databases
并提供适当的数据库或表参数。有关mysqleck调用语法,请参见第4.5.3节,“mysqleck-表维护方案“.
注
这个#mysql50#
前缀仅供服务器内部使用。不应使用此前缀创建具有名称的数据库或表。
还有,mysqleck控件的文字实例的名称无法修复。@
用于编码特殊字符的字符。如果有包含此字符的数据库或表,请使用mysqldump在升级到MySQL 5.1.6或更高版本之前将它们转储,然后在升级后重新加载转储文件。
注
将包含特殊字符的前MySQL 5.1数据库名称转换为5.1格式,并添加#mysql50#
前缀被废弃,并将在MySQL的未来版本中删除。由于此类转换不受欢迎,因此--fix-db-names
和--fix-table-names
可供选择的mysqleck而UPGRADE DATA DIRECTORY NAME
的条款ALTER DATABASE
语句也不受欢迎。
升级只支持从一个版本系列到另一个版本(例如5.0至5.1或5.1至5.5),因此不需要将较旧的5.0数据库名称转换为MySQL的当前版本。作为解决办法,在升级到最新版本之前,将MySQL5.0安装升级到MySQL5.1。
9.2.4函数名解析和解析
MySQL支持内置(本机)函数、用户定义函数(UDF)和存储函数.本节描述服务器如何识别内置函数的名称是用作函数调用还是用作标识符,以及服务器如何确定在不同类型的函数与给定名称共存的情况下使用哪个函数。
解析器使用默认规则解析内置函数的名称。这些规则可以通过启用IGNORE_SPACE
SQL模式
当解析器遇到作为内置函数名称的单词时,它必须确定名称是否表示函数调用,或者是对标识符(如表或列名)的非表达式引用。例如,在以下语句中,第一次引用count
是函数调用,而第二个引用是表名:
SELECT COUNT(*) FROM mytable; CREATE TABLE count (i INT);
解析器应该将内置函数的名称识别为仅在解析表达式时指示函数调用。也就是说,在非表达式上下文中,函数名被允许作为标识符。
但是,一些内置函数具有特殊的解析或实现考虑,因此解析器默认使用以下规则来区分它们的名称是用作函数调用还是用作非表达式上下文中的标识符:
-
若要将名称用作表达式中的函数调用,名称和下面的内容之间必须没有空格。
(
括号字符 -
相反,若要使用函数名作为标识符,则不能紧跟括号。
函数调用在名称和括号之间不带空格的要求只适用于有特殊考虑的内置函数。COUNT
就是这样一个名字。这个sql/lex.h
源文件列出这些特殊函数的名称,下面的空格确定它们的解释:SYM_FN()
宏中的symbols[]
阵列。
下面的列表列出MySQL 5.7中受IGNORE_SPACE
设置,并在sql/lex.h
源文件。您可能会发现,将不需要空格的要求作为应用于所有函数调用是最简单的。
-
ADDDATE
-
BIT_AND
-
BIT_OR
-
BIT_XOR
-
CAST
-
COUNT
-
CURDATE
-
CURTIME
-
DATE_ADD
-
DATE_SUB
-
EXTRACT
-
GROUP_CONCAT
-
MAX
-
MID
-
MIN
-
NOW
-
POSITION
-
SESSION_USER
-
STD
-
STDDEV
-
STDDEV_POP
-
STDDEV_SAMP
-
SUBDATE
-
SUBSTR
-
SUBSTRING
-
SUM
-
SYSDATE
-
SYSTEM_USER
-
TRIM
-
VARIANCE
-
VAR_POP
-
VAR_SAMP
中未列出为特殊的函数。sql/lex.h
,空格不重要。它们仅在表达式上下文中使用时才被解释为函数调用,否则可以作为标识符自由使用。ASCII
就是这样一个名字。但是,对于这些不受影响的函数名称,表达式上下文的解释可能有所不同:
如果存在具有给定名称的函数,则解释为内置函数;如果没有,func_name
()
被解释为用户定义的函数或存储函数,如果一个函数以该名称存在。func_name
()
这个IGNORE_SPACE
SQL模式可用于修改解析器如何处理对空格敏感的函数名称:
-
带着
IGNORE_SPACE
禁用时,当名称和下面的括号之间没有空格时,解析器将名称解释为函数调用。即使在非表达式上下文中使用函数名时,也会发生这种情况:mysql>
CREATE TABLE count(i INT);
ERROR 1064 (42000): You have an error in your SQL syntax ... near 'count(i INT)'若要消除错误并使名称被视为标识符,请在名称后面使用空格或将其写入引号标识符(或两者兼用):
CREATE TABLE count (i INT); CREATE TABLE `count`(i INT); CREATE TABLE `count` (i INT);
-
带着
IGNORE_SPACE
启用后,解析器就放松了在函数名和下面的括号之间没有空格的要求。这为编写函数调用提供了更大的灵活性。例如,下列任一函数调用都是合法的:SELECT COUNT(*) FROM mytable; SELECT COUNT (*) FROM mytable;
但是,
IGNORE_SPACE
还有一个副作用,即解析器将受影响的函数名视为保留字(请参见第9.3节,“关键词和保留词”)。这意味着名称后面的空格不再表示它用作标识符。名称可以用于带有或不跟随空格的函数调用,但除非引用,否则会在非表达式上下文中导致语法错误。例如,用IGNORE_SPACE
启用后,以下两条语句都会因语法错误而失败,因为解析器解释count
作为保留词:CREATE TABLE count(i INT); CREATE TABLE count (i INT);
若要在非表达式上下文中使用函数名,请将其写入引用的标识符:
CREATE TABLE `count`(i INT); CREATE TABLE `count` (i INT);
若要启用IGNORE_SPACE
SQL模式,使用以下语句:
SET sql_mode = 'IGNORE_SPACE';
IGNORE_SPACE
也是由某些其他复合模式启用的,例如ANSI
其中包括其价值:
SET sql_mode = 'ANSI';
查帐第5.1.10节,“服务器SQL模式”,以查看哪些复合模式启用IGNORE_SPACE
.
若要最小化SQL代码对IGNORE_SPACE
设置,使用以下指南:
-
避免创建与内置函数同名的UDF或存储函数。
-
避免在非表达式上下文中使用函数名。例如,这些语句使用
count
(受影响的函数名称之一)IGNORE_SPACE
),因此它们在名称后面有或没有空格时都会失败,如果IGNORE_SPACE
启用:CREATE TABLE count(i INT); CREATE TABLE count (i INT);
如果必须在非表达式上下文中使用函数名,请将其写入引用的标识符:
CREATE TABLE `count`(i INT); CREATE TABLE `count` (i INT);
以下规则描述了服务器如何解析函数创建和调用中对函数名称的引用:
-
内置函数和用户定义函数
如果尝试创建与内置函数同名的UDF,则会发生错误。
-
内置函数和存储函数
可以创建与内置函数同名的存储函数,但要调用存储的函数,就必须将其限定为模式名称。例如,如果您创建一个名为
PI
在test
模式,将其调用为test.PI()
因为服务器解析PI()
不使用限定符作为内建函数的引用。如果存储的函数名与内置函数名发生冲突,则服务器将生成警告。可以用SHOW WARNINGS
. -
用户定义函数和存储函数
用户定义的函数和存储的函数共享相同的命名空间,因此不能创建具有相同名称的UDF和存储函数。
前面的函数名称解析规则对升级到实现新内置函数的MySQL版本有影响:
-
如果您已经创建了一个具有给定名称的用户定义函数,并将MySQL升级到实现具有相同名称的新内置函数的版本,那么UDF将变得不可访问。若要更正此问题,请使用
DROP FUNCTION
放弃UDF和CREATE FUNCTION
使用不同的非冲突名称重新创建UDF。然后修改任何受影响的代码以使用新名称。 -
如果MySQL的新版本实现了与现有存储函数同名的内置函数,则有两种选择:重命名存储函数以使用非冲突的名称,或者更改对函数的调用,以便它们使用架构限定符(即使用
(语法)在这两种情况下,相应地修改任何受影响的代码。schema_name
.func_name
()
9.3关键词和保留词
关键字是在SQL中有意义的单词。某些关键字,如SELECT
, DELETE
,或BIGINT
,则需要特殊处理,以便作为标识符使用,例如表名和列名。对于内置函数的名称也可能是如此。
非保留关键字允许作为标识符而不引用。如果引用中所述的保留字,则允许作为标识符。第9.2节,“架构对象名称”:
mysql> CREATE TABLE interval (begin INT, end INT);
ERROR 1064 (42000): You have an error in your SQL syntax ...
near 'interval (begin INT, end INT)'
BEGIN
和END
是关键字,但不保留,因此它们作为标识符的使用不需要引用。INTERVAL
是一个保留关键字,必须引用它作为标识符:
mysql> CREATE TABLE `interval` (begin INT, end INT);
Query OK, 0 rows affected (0.01 sec)
例外:限定名中的句点后面的单词必须是标识符,因此即使保留它,也不需要引用它:
mysql> CREATE TABLE mydb.interval (begin INT, end INT);
Query OK, 0 rows affected (0.01 sec)
内置函数的名称允许作为标识符,但可能需要谨慎使用。例如,COUNT
作为列名可以接受。但是,默认情况下,在函数名称和下面的函数调用中不允许使用空格(
性格。此要求使解析器能够区分名称是在函数调用中使用还是在非函数上下文中使用。有关识别函数名的详细信息,请参阅第9.2.4节,“函数名解析和解决”.
MySQL 5.7关键词和保留词
下面的列表显示MySQL5.7中的关键字和保留单词,以及从版本到版本对单个单词的更改。保留关键字用(R)标记。此外,_FILENAME
是保留的。
在某种程度上,您可能会升级到更高的版本,所以看看未来的保留字也是个好主意。您可以在涵盖MySQL高级版本的手册中找到这些内容。标准SQL禁止列表中的大多数保留字作为列名或表名(例如,GROUP
)。有些是保留的,因为MySQL需要它们,并且使用雅克解析器。
A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z
-
ACCESSIBLE
(R) -
ACCOUNT
增加5.7.6(无保留) -
ACTION
-
ADD
(R) -
AFTER
-
AGAINST
-
AGGREGATE
-
ALGORITHM
-
ALL
(R) -
ALTER
(R) -
ALWAYS
增加5.7.6(无保留) -
ANALYSE
-
ANALYZE
(R) -
AND
(R) -
ANY
-
AS
(R) -
ASC
(R) -
ASCII
-
ASENSITIVE
(R) -
AT
-
AUTOEXTEND_SIZE
-
AUTO_INCREMENT
-
AVG
-
AVG_ROW_LENGTH
-
BACKUP
-
BEFORE
(R) -
BEGIN
-
BETWEEN
(R) -
BIGINT
(R) -
BINARY
(R) -
BINLOG
-
BIT
-
BLOB
(R) -
BLOCK
-
BOOL
-
BOOLEAN
-
BOTH
(R) -
BTREE
-
BY
(R) -
BYTE
-
CACHE
-
CALL
(R) -
CASCADE
(R) -
CASCADED
-
CASE
(R) -
CATALOG_NAME
-
CHAIN
-
CHANGE
(R) -
CHANGED
-
CHANNEL
增加5.7.6(无保留) -
CHAR
(R) -
CHARACTER
(R) -
CHARSET
-
CHECK
(R) -
CHECKSUM
-
CIPHER
-
CLASS_ORIGIN
-
CLIENT
-
CLOSE
-
COALESCE
-
CODE
-
COLLATE
(R) -
COLLATION
-
COLUMN
(R) -
COLUMNS
-
COLUMN_FORMAT
-
COLUMN_NAME
-
COMMENT
-
COMMIT
-
COMMITTED
-
COMPACT
-
COMPLETION
-
COMPRESSED
-
COMPRESSION
加入5.7.8(无保留) -
CONCURRENT
-
CONDITION
(R) -
CONNECTION
-
CONSISTENT
-
CONSTRAINT
(R) -
CONSTRAINT_CATALOG
-
CONSTRAINT_NAME
-
CONSTRAINT_SCHEMA
-
CONTAINS
-
CONTEXT
-
CONTINUE
(R) -
CONVERT
(R) -
CPU
-
CREATE
(R) -
CROSS
(R) -
CUBE
-
CURRENT
-
CURRENT_DATE
(R) -
CURRENT_TIME
(R) -
CURRENT_TIMESTAMP
(R) -
CURRENT_USER
(R) -
CURSOR
(R) -
CURSOR_NAME
-
DATA
-
DATABASE
(R) -
DATABASES
(R) -
DATAFILE
-
DATE
-
DATETIME
-
DAY
-
DAY_HOUR
(R) -
DAY_MICROSECOND
(R) -
DAY_MINUTE
(R) -
DAY_SECOND
(R) -
DEALLOCATE
-
DEC
(R) -
DECIMAL
(R) -
DECLARE
(R) -
DEFAULT
(R) -
DEFAULT_AUTH
-
DEFINER
-
DELAYED
(R) -
DELAY_KEY_WRITE
-
DELETE
(R) -
DESC
(R) -
DESCRIBE
(R) -
DES_KEY_FILE
-
DETERMINISTIC
(R) -
DIAGNOSTICS
-
DIRECTORY
-
DISABLE
-
DISCARD
-
DISK
-
DISTINCT
(R) -
DISTINCTROW
(R) -
DIV
(R) -
DO
-
DOUBLE
(R) -
DROP
(R) -
DUAL
(R) -
DUMPFILE
-
DUPLICATE
-
DYNAMIC
-
EACH
(R) -
ELSE
(R) -
ELSEIF
(R) -
ENABLE
-
ENCLOSED
(R) -
ENCRYPTION
加入5.7.11(无保留) -
END
-
ENDS
-
ENGINE
-
ENGINES
-
ENUM
-
ERROR
-
ERRORS
-
ESCAPE
-
ESCAPED
(R) -
EVENT
-
EVENTS
-
EVERY
-
EXCHANGE
-
EXECUTE
-
EXISTS
(R) -
EXIT
(R) -
EXPANSION
-
EXPIRE
-
EXPLAIN
(R) -
EXPORT
-
EXTENDED
-
EXTENT_SIZE
-
FALSE
(R) -
FAST
-
FAULTS
-
FETCH
(R) -
FIELDS
-
FILE
-
FILE_BLOCK_SIZE
增加5.7.6(无保留) -
FILTER
增加5.7.3(无保留) -
FIRST
-
FIXED
-
FLOAT
(R) -
FLOAT4
(R) -
FLOAT8
(R) -
FLUSH
-
FOLLOWS
加入5.7.2(无保留) -
FOR
(R) -
FORCE
(R) -
FOREIGN
(R) -
FORMAT
-
FOUND
-
FROM
(R) -
FULL
-
FULLTEXT
(R) -
FUNCTION
-
GENERAL
-
GENERATED
(R)增加5.7.6(保留) -
GEOMETRY
-
GEOMETRYCOLLECTION
-
GET
(R) -
GET_FORMAT
-
GLOBAL
-
GRANT
(R) -
GRANTS
-
GROUP
(R) -
GROUP_REPLICATION
增加5.7.6(无保留)
-
HANDLER
-
HASH
-
HAVING
(R) -
HELP
-
HIGH_PRIORITY
(R) -
HOST
-
HOSTS
-
HOUR
-
HOUR_MICROSECOND
(R) -
HOUR_MINUTE
(R) -
HOUR_SECOND
(R)
-
IDENTIFIED
-
IF
(R) -
IGNORE
(R) -
IGNORE_SERVER_IDS
-
IMPORT
-
IN
(R) -
INDEX
(R) -
INDEXES
-
INFILE
(R) -
INITIAL_SIZE
-
INNER
(R) -
INOUT
(R) -
INSENSITIVE
(R) -
INSERT
(R) -
INSERT_METHOD
-
INSTALL
-
INSTANCE
加入5.7.11(无保留) -
INT
(R) -
INT1
(R) -
INT2
(R) -
INT3
(R) -
INT4
(R) -
INT8
(R) -
INTEGER
(R) -
INTERVAL
(R) -
INTO
(R) -
INVOKER
-
IO
-
IO_AFTER_GTIDS
(R) -
IO_BEFORE_GTIDS
(R) -
IO_THREAD
-
IPC
-
IS
(R) -
ISOLATION
-
ISSUER
-
ITERATE
(R)
-
JOIN
(R) -
JSON
加入5.7.8(无保留)
-
KEY
(R) -
KEYS
(R) -
KEY_BLOCK_SIZE
-
KILL
(R)
-
LANGUAGE
-
LAST
-
LEADING
(R) -
LEAVE
(R) -
LEAVES
-
LEFT
(R) -
LESS
-
LEVEL
-
LIKE
(R) -
LIMIT
(R) -
LINEAR
(R) -
LINES
(R) -
LINESTRING
-
LIST
-
LOAD
(R) -
LOCAL
-
LOCALTIME
(R) -
LOCALTIMESTAMP
(R) -
LOCK
(R) -
LOCKS
-
LOGFILE
-
LOGS
-
LONG
(R) -
LONGBLOB
(R) -
LONGTEXT
(R) -
LOOP
(R) -
LOW_PRIORITY
(R)
-
MASTER
-
MASTER_AUTO_POSITION
-
MASTER_BIND
(R) -
MASTER_CONNECT_RETRY
-
MASTER_DELAY
-
MASTER_HEARTBEAT_PERIOD
-
MASTER_HOST
-
MASTER_LOG_FILE
-
MASTER_LOG_POS
-
MASTER_PASSWORD
-
MASTER_PORT
-
MASTER_RETRY_COUNT
-
MASTER_SERVER_ID
-
MASTER_SSL
-
MASTER_SSL_CA
-
MASTER_SSL_CAPATH
-
MASTER_SSL_CERT
-
MASTER_SSL_CIPHER
-
MASTER_SSL_CRL
-
MASTER_SSL_CRLPATH
-
MASTER_SSL_KEY
-
MASTER_SSL_VERIFY_SERVER_CERT
(R) -
MASTER_TLS_VERSION
加入5.7.10(无保留) -
MASTER_USER
-
MATCH
(R) -
MAXVALUE
(R) -
MAX_CONNECTIONS_PER_HOUR
-
MAX_QUERIES_PER_HOUR
-
MAX_ROWS
-
MAX_SIZE
-
MAX_STATEMENT_TIME
;在5.7.4(无保留)中添加;在5.7.8中删除 -
MAX_UPDATES_PER_HOUR
-
MAX_USER_CONNECTIONS
-
MEDIUM
-
MEDIUMBLOB
(R) -
MEDIUMINT
(R) -
MEDIUMTEXT
(R) -
MEMORY
-
MERGE
-
MESSAGE_TEXT
-
MICROSECOND
-
MIDDLEINT
(R) -
MIGRATE
-
MINUTE
-
MINUTE_MICROSECOND
(R) -
MINUTE_SECOND
(R) -
MIN_ROWS
-
MOD
(R) -
MODE
-
MODIFIES
(R) -
MODIFY
-
MONTH
-
MULTILINESTRING
-
MULTIPOINT
-
MULTIPOLYGON
-
MUTEX
-
MYSQL_ERRNO
-
NAME
-
NAMES
-
NATIONAL
-
NATURAL
(R) -
NCHAR
-
NDB
-
NDBCLUSTER
-
NEVER
加入5.7.4(无保留) -
NEW
-
NEXT
-
NO
-
NODEGROUP
-
NONBLOCKING
;在5.7.6中删除 -
NONE
-
NOT
(R) -
NO_WAIT
-
NO_WRITE_TO_BINLOG
(R) -
NULL
(R) -
NUMBER
-
NUMERIC
(R) -
NVARCHAR
-
OFFSET
-
OLD_PASSWORD
;在5.7.5中删除 -
ON
(R) -
ONE
-
ONLY
-
OPEN
-
OPTIMIZE
(R) -
OPTIMIZER_COSTS
(R)增加5.7.5(保留) -
OPTION
(R) -
OPTIONALLY
(R) -
OPTIONS
-
OR
(R) -
ORDER
(R) -
OUT
(R) -
OUTER
(R) -
OUTFILE
(R) -
OWNER
-
PACK_KEYS
-
PAGE
-
PARSER
-
PARSE_GCOL_EXPR
;在5.7.6(保留)中添加;在5.7.8中变为非保留 -
PARTIAL
-
PARTITION
(R) -
PARTITIONING
-
PARTITIONS
-
PASSWORD
-
PHASE
-
PLUGIN
-
PLUGINS
-
PLUGIN_DIR
-
POINT
-
POLYGON
-
PORT
-
PRECEDES
加入5.7.2(无保留) -
PRECISION
(R) -
PREPARE
-
PRESERVE
-
PREV
-
PRIMARY
(R) -
PRIVILEGES
-
PROCEDURE
(R) -
PROCESSLIST
-
PROFILE
-
PROFILES
-
PROXY
-
PURGE
(R)
-
QUARTER
-
QUERY
-
QUICK
-
RANGE
(R) -
READ
(R) -
READS
(R) -
READ_ONLY
-
READ_WRITE
(R) -
REAL
(R) -
REBUILD
-
RECOVER
-
REDOFILE
-
REDO_BUFFER_SIZE
-
REDUNDANT
-
REFERENCES
(R) -
REGEXP
(R) -
RELAY
-
RELAYLOG
-
RELAY_LOG_FILE
-
RELAY_LOG_POS
-
RELAY_THREAD
-
RELEASE
(R) -
RELOAD
-
REMOVE
-
RENAME
(R) -
REORGANIZE
-
REPAIR
-
REPEAT
(R) -
REPEATABLE
-
REPLACE
(R) -
REPLICATE_DO_DB
增加5.7.3(无保留) -
REPLICATE_DO_TABLE
增加5.7.3(无保留) -
REPLICATE_IGNORE_DB
增加5.7.3(无保留) -
REPLICATE_IGNORE_TABLE
增加5.7.3(无保留) -
REPLICATE_REWRITE_DB
增加5.7.3(无保留) -
REPLICATE_WILD_DO_TABLE
增加5.7.3(无保留) -
REPLICATE_WILD_IGNORE_TABLE
增加5.7.3(无保留) -
REPLICATION
-
REQUIRE
(R) -
RESET
-
RESIGNAL
(R) -
RESTORE
-
RESTRICT
(R) -
RESUME
-
RETURN
(R) -
RETURNED_SQLSTATE
-
RETURNS
-
REVERSE
-
REVOKE
(R) -
RIGHT
(R) -
RLIKE
(R) -
ROLLBACK
-
ROLLUP
-
ROTATE
加入5.7.11(无保留) -
ROUTINE
-
ROW
-
ROWS
-
ROW_COUNT
-
ROW_FORMAT
-
RTREE
-
SAVEPOINT
-
SCHEDULE
-
SCHEMA
(R) -
SCHEMAS
(R) -
SCHEMA_NAME
-
SECOND
-
SECOND_MICROSECOND
(R) -
SECURITY
-
SELECT
(R) -
SENSITIVE
(R) -
SEPARATOR
(R) -
SERIAL
-
SERIALIZABLE
-
SERVER
-
SESSION
-
SET
(R) -
SHARE
-
SHOW
(R) -
SHUTDOWN
-
SIGNAL
(R) -
SIGNED
-
SIMPLE
-
SLAVE
-
SLOW
-
SMALLINT
(R) -
SNAPSHOT
-
SOCKET
-
SOME
-
SONAME
-
SOUNDS
-
SOURCE
-
SPATIAL
(R) -
SPECIFIC
(R) -
SQL
(R) -
SQLEXCEPTION
(R) -
SQLSTATE
(R) -
SQLWARNING
(R) -
SQL_AFTER_GTIDS
-
SQL_AFTER_MTS_GAPS
-
SQL_BEFORE_GTIDS
-
SQL_BIG_RESULT
(R) -
SQL_BUFFER_RESULT
-
SQL_CACHE
-
SQL_CALC_FOUND_ROWS
(R) -
SQL_NO_CACHE
-
SQL_SMALL_RESULT
(R) -
SQL_THREAD
-
SQL_TSI_DAY
-
SQL_TSI_HOUR
-
SQL_TSI_MINUTE
-
SQL_TSI_MONTH
-
SQL_TSI_QUARTER
-
SQL_TSI_SECOND
-
SQL_TSI_WEEK
-
SQL_TSI_YEAR
-
SSL
(R) -
STACKED
-
START
-
STARTING
(R) -
STARTS
-
STATS_AUTO_RECALC
-
STATS_PERSISTENT
-
STATS_SAMPLE_PAGES
-
STATUS
-
STOP
-
STORAGE
-
STORED
(R)增加5.7.6(保留) -
STRAIGHT_JOIN
(R) -
STRING
-
SUBCLASS_ORIGIN
-
SUBJECT
-
SUBPARTITION
-
SUBPARTITIONS
-
SUPER
-
SUSPEND
-
SWAPS
-
SWITCHES
-
TABLE
(R) -
TABLES
-
TABLESPACE
-
TABLE_CHECKSUM
-
TABLE_NAME
-
TEMPORARY
-
TEMPTABLE
-
TERMINATED
(R) -
TEXT
-
THAN
-
THEN
(R) -
TIME
-
TIMESTAMP
-
TIMESTAMPADD
-
TIMESTAMPDIFF
-
TINYBLOB
(R) -
TINYINT
(R) -
TINYTEXT
(R) -
TO
(R) -
TRAILING
(R) -
TRANSACTION
-
TRIGGER
(R) -
TRIGGERS
-
TRUE
(R) -
TRUNCATE
-
TYPE
-
TYPES
-
UNCOMMITTED
-
UNDEFINED
-
UNDO
(R) -
UNDOFILE
-
UNDO_BUFFER_SIZE
-
UNICODE
-
UNINSTALL
-
UNION
(R) -
UNIQUE
(R) -
UNKNOWN
-
UNLOCK
(R) -
UNSIGNED
(R) -
UNTIL
-
UPDATE
(R) -
UPGRADE
-
USAGE
(R) -
USE
(R) -
USER
-
USER_RESOURCES
-
USE_FRM
-
USING
(R) -
UTC_DATE
(R) -
UTC_TIME
(R) -
UTC_TIMESTAMP
(R)
-
VALIDATION
增加5.7.5(无保留) -
VALUE
-
VALUES
(R) -
VARBINARY
(R) -
VARCHAR
(R) -
VARCHARACTER
(R) -
VARIABLES
-
VARYING
(R) -
VIEW
-
VIRTUAL
(R)增加5.7.6(保留)
-
WAIT
-
WARNINGS
-
WEEK
-
WEIGHT_STRING
-
WHEN
(R) -
WHERE
(R) -
WHILE
(R) -
WITH
(R) -
WITHOUT
增加5.7.5(无保留) -
WORK
-
WRAPPER
-
WRITE
(R)
-
X509
-
XA
-
XID
增加5.7.5(无保留) -
XML
-
XOR
(R)
-
YEAR
-
YEAR_MONTH
(R)
-
ZEROFILL
(R)
MySQL 5.7新关键字和保留词
下面的列表显示了MySQL5.7中添加的关键字和保留单词,而MySQL5.6中添加了这些关键字和保留单词。保留关键字用(R)标记。
A | C | E | F | G | I | J | M | N | O | P | R | S | V | W | X
-
ACCOUNT
-
ALWAYS
-
CHANNEL
-
COMPRESSION
-
ENCRYPTION
-
FILE_BLOCK_SIZE
-
FILTER
-
FOLLOWS
-
GENERATED
(R) -
GROUP_REPLICATION
-
INSTANCE
-
JSON
-
MASTER_TLS_VERSION
-
NEVER
-
OPTIMIZER_COSTS
(R)
-
PARSE_GCOL_EXPR
-
PRECEDES
-
REPLICATE_DO_DB
-
REPLICATE_DO_TABLE
-
REPLICATE_IGNORE_DB
-
REPLICATE_IGNORE_TABLE
-
REPLICATE_REWRITE_DB
-
REPLICATE_WILD_DO_TABLE
-
REPLICATE_WILD_IGNORE_TABLE
-
ROTATE
-
STACKED
-
STORED
(R)
-
VALIDATION
-
VIRTUAL
(R)
-
WITHOUT
-
XID
MySQL 5.7删除关键字和保留字
下面的列表显示MySQL5.7中删除的关键字和保留单词,而MySQL5.6。保留关键字用(R)标记。
-
OLD_PASSWORD
9.4用户定义变量
您可以在一个语句中的用户定义变量中存储一个值,然后在另一个语句中引用它。这使您能够将值从一个语句传递到另一个语句。
用户变量编写为@
,其中变量名var_name
var_name
由字母数字字符组成,.
, _
,和$
..如果将用户变量名引用为字符串或标识符(例如,@'my-var'
, @"my-var"
,或@`my-var`
).
用户定义的变量是会话特定的。一个客户端定义的用户变量不能被其他客户端看到或使用。(异常:访问性能架构的用户user_variables_by_thread
表可以查看所有会话的所有用户变量。)当客户端退出时,将自动释放给定客户端会话的所有变量。
用户变量名不区分大小写.名称的最大长度为64个字符。
设置用户定义变量的一种方法是发出SET
声明:
SET @var_name
=expr
[, @var_name
=expr
] ...
用户变量可以从有限的一组数据类型中分配一个值:整数、十进制、浮点、二进制或非二进制字符串,或者NULL
价值。小数和实值的赋值不保持值的精度或比例。将允许类型以外的类型的值转换为允许类型。例如,具有时间或空间数据类型的值被转换为二进制字符串。具有JSON
数据类型转换为字符串,其字符集为utf8mb4
和整理utf8mb4_bin
.
如果用户变量被分配为一个非二进制(字符)字符串值,则它具有与该字符串相同的字符集和排序规则。用户变量的矫顽力是隐式的。(这与表列值的矫顽力相同。)
分配给用户变量的十六进制或位值被视为二进制字符串。若要将十六进制或位值作为数字分配给用户变量,请在数字上下文中使用它。例如,添加0或使用CAST(... AS UNSIGNED)
:
mysql>SET @v1 = X'41';
mysql>SET @v2 = X'41'+0;
mysql>SET @v3 = CAST(X'41' AS UNSIGNED);
mysql>SELECT @v1, @v2, @v3;
+------+------+------+ | @v1 | @v2 | @v3 | +------+------+------+ | A | 65 | 65 | +------+------+------+ mysql>SET @v1 = b'1000001';
mysql>SET @v2 = b'1000001'+0;
mysql>SET @v3 = CAST(b'1000001' AS UNSIGNED);
mysql>SELECT @v1, @v2, @v3;
+------+------+------+ | @v1 | @v2 | @v3 | +------+------+------+ | A | 65 | 65 | +------+------+------+
如果在结果集中选择了用户变量的值,则它将作为字符串返回给客户端。
如果引用未初始化的变量,则该变量的值为NULL
和一种字符串。
用户变量可以在大多数允许表达式的上下文中使用。当前,这不包括显式要求文字值的上下文,如LIMIT
a的子句SELECT
语句,或IGNORE
a的子句N
LINESLOAD DATA
声明。
还可以在其他语句中将值赋值给用户变量。SET
..(此功能在MySQL8.0中不受欢迎,并可能在随后的版本中被删除。)在以这种方式进行赋值时,赋值运算符必须是:=
而不是=
因为后者被视为比较运算符。=
在其他声明中SET
:
mysql>SET @t1=1, @t2=2, @t3:=4;
mysql>SELECT @t1, @t2, @t3, @t4 := @t1+@t2+@t3;
+------+------+------+--------------------+ | @t1 | @t2 | @t3 | @t4 := @t1+@t2+@t3 | +------+------+------+--------------------+ | 1 | 2 | 4 | 7 | +------+------+------+--------------------+
作为一般规则,除SET
语句中,不应将值分配给用户变量并在同一语句中读取该值。例如,要增加一个变量,这是可以的:
SET @a = @a + 1;
对于其他语句,例如SELECT
,您可能会得到预期的结果,但这并不一定。在下面的语句中,您可能会认为MySQL将评估@a
先做作业,然后再做作业:
SELECT @a, @a:=@a+1, ...;
但是,涉及用户变量的表达式的计算顺序尚未定义。
另一个问题是将一个值赋值给一个变量,并在相同的非-SET
语句是变量的默认结果类型基于语句开头的类型。以下示例说明了这一点:
mysql>SET @a='test';
mysql>SELECT @a,(@a:=20) FROM
tbl_name
;
为了这个SELECT
语句时,MySQL向客户端报告第一列是一个字符串,并转换@a
到字符串,即使@a被设置为第二行的数字。在.之后SELECT
语句执行,@a
被视为下一次陈述的数字。
若要避免此行为出现问题,请不要将值赋值并在单个语句中读取相同变量的值,或者将变量设置为0
, 0.0
,或''
若要在使用前定义其类型,请执行以下操作。
在.SELECT
语句时,每个SELECT表达式仅在发送到客户端时才会进行计算。这意味着在HAVING
, GROUP BY
,或ORDER BY
子句,引用在SELECT表达式列表中赋值的变量不按预期开展工作:
mysql> SELECT (@aa:=id) AS a, (@aa+3) AS b FROM tbl_name
HAVING b=5;
引用b
在HAVING
子句引用选择列表中的表达式的别名,该表达式使用@aa
..这不像预期的那样有效:@aa
包含id
从上一个选定的行,而不是从当前行。
用户变量旨在提供数据值。它们不能直接在sql语句中用作标识符或标识符的一部分,例如在需要表或数据库名称的上下文中,也不能用作保留词,例如SELECT
..即使引用了变量,也是如此,如下面的示例所示:
mysql>SELECT c1 FROM t;
+----+ | c1 | +----+ | 0 | +----+ | 1 | +----+ 2 rows in set (0.00 sec) mysql>SET @col = "c1";
Query OK, 0 rows affected (0.00 sec) mysql>SELECT @col FROM t;
+------+ | @col | +------+ | c1 | +------+ 1 row in set (0.00 sec) mysql>SELECT `@col` FROM t;
ERROR 1054 (42S22): Unknown column '@col' in 'field list' mysql> SET @col = "`c1`"; Query OK, 0 rows affected (0.00 sec) mysql>SELECT @col FROM t;
+------+ | @col | +------+ | `c1` | +------+ 1 row in set (0.00 sec)
用户变量不能用于提供标识符这一原则的一个例外情况是,当您正在构造一个字符串以作为准备好的语句用于以后执行时。在这种情况下,用户变量可以用于提供语句的任何部分。下面的示例说明了如何做到这一点:
mysql>SET @c = "c1";
Query OK, 0 rows affected (0.00 sec) mysql>SET @s = CONCAT("SELECT ", @c, " FROM t");
Query OK, 0 rows affected (0.00 sec) mysql>PREPARE stmt FROM @s;
Query OK, 0 rows affected (0.04 sec) Statement prepared mysql>EXECUTE stmt;
+----+ | c1 | +----+ | 0 | +----+ | 1 | +----+ 2 rows in set (0.00 sec) mysql>DEALLOCATE PREPARE stmt;
Query OK, 0 rows affected (0.00 sec)
看见第13.5节,“准备好的SQL语句语法”,以获取更多信息。
在应用程序中也可以使用类似的技术来使用程序变量构造SQL语句,如下面使用PHP 5所示:
<?php $mysqli = new mysqli("localhost", "user", "pass", "test"); if( mysqli_connect_errno() ) die("Connection failed: %s\n", mysqli_connect_error()); $col = "c1"; $query = "SELECT $col FROM t"; $result = $mysqli->query($query); while($row = $result->fetch_assoc()) { echo "<p>" . $row["$col"] . "</p>\n"; } $result->close(); $mysqli->close(); ?>
以这种方式组装sql语句有时称为“动态SQL”.
9.5表达式
本节列出表达式在MySQL中必须遵循的语法规则,并提供有关表达式中可能出现的术语类型的其他信息。
表达式语法
以下语法规则定义MySQL中的表达式语法。这里显示的语法是基于sql/sql_yacc.yy
MySQL源代码发行版的文件。有关某些表达式术语的其他信息,请参阅表达式术语说明.
expr
:expr
ORexpr
|expr
||expr
|expr
XORexpr
|expr
ANDexpr
|expr
&&expr
| NOTexpr
| !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] BETWEENbit_expr
ANDpredicate
|bit_expr
SOUNDS LIKEbit_expr
|bit_expr
[NOT] LIKEsimple_expr
[ESCAPEsimple_expr
] |bit_expr
[NOT] REGEXPbit_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
DIVbit_expr
|bit_expr
MODbit_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
COLLATEcollation_name
|param_marker
|variable
|simple_expr
||simple_expr
| +simple_expr
| -simple_expr
| ~simple_expr
| !simple_expr
| BINARYsimple_expr
| (expr
[,expr
] ...) | ROW (expr
,expr
[,expr
] ...) | (subquery
) | EXISTS (subquery
) | {identifier
expr
} |match_expr
|case_expr
|interval_expr
有关运算符优先级,请参见第12.3.1节,“经营者优先”..某些运算符的优先级和含义取决于SQL模式:
-
默认情况下,
||
是合乎逻辑的OR
接线员。带着PIPES_AS_CONCAT
启用,||
是字符串连接,其优先级为^
以及一元运算符。 -
默认情况下,
!
比NOT
..带着HIGH_NOT_PRECEDENCE
启用,!
和NOT
有同样的优先权。
表达式术语说明
有关文字值语法,请参见第9.1节,“字面值”.
有关标识符语法,请参见第9.2节,“架构对象名称”.
变量可以是用户变量、系统变量或存储的程序局部变量或参数:
-
用户变量:第9.4节,“用户定义的变量”
-
系统变量:第5.1.8节,“使用系统变量”
-
存储程序局部变量:第13.6.4.1节,“局部变量申报语法”
-
存储程序参数:第13.1.16节,“创建过程和创建功能语法”
param_marker
是?
在为占位符准备的语句中使用。看见第13.5.1节,“准备句法”.
(
指示返回单个值的子查询;即标量子查询。看见第13.2.10.1节,“子查询作为标量操作数”.subquery
)
{
是ODBC转义语法,为ODBC兼容性所接受。值是identifier
expr
}expr
..这个{
和}
语法中的大括号应该按字面顺序写;它们不是语法描述中其他地方使用的元异步。
match_expr
指示MATCH
表情。看见第12.9节,“全文搜索功能”.
case_expr
指示CASE
表情。看见第12.4节,“控制流函数”.
interval_expr
表示时间间隔。看见时间间隔.
时间间隔
interval_expr
在表达式中表示时间间隔。间隔具有以下语法:
INTERVALexpr
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' |
中的任何标点符号分隔符。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
+ INTERVALexpr
unit
date
- INTERVALexpr
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()
函数使用相同类型的unit
说明符DATE_ADD()
或DATE_SUB()
,但是从日期中提取部分,而不是执行日期算术:
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假设您忽略了区间值的最左边部分。例如,如果指定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/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'
如果你加上MONTH
, YEAR_MONTH
,或YEAR
由此产生的日期有一个日期大于新月份的最大日,该日调整为新月份的最大天数:
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
9.6评论语法
MySQL Server支持三种注释样式:
-
从
#
字符到行尾。 -
从
--
序列到线的末尾。在MySQL中,--
(双破折号)注释样式要求第二个破折号后面至少有一个空格或控制字符(例如空格、制表符、换行符等)。此语法与标准sql注释语法略有不同,如第1.8.2.4节,“-”作为评论的开头“. -
从
/*
顺序如下*/
序列,如C语言中的。此语法使注释能够扩展到多行,因为开始序列和结束序列不需要在同一行上。
下面的示例演示了所有三种注释样式:
mysql>SELECT 1+1; # This comment continues to the end of line
mysql>SELECT 1+1; -- This comment continues to the end of line
mysql>SELECT 1 /* this is an in-line comment */ + 1;
mysql>SELECT 1+
/*
this is a
multiple-line comment
*/
1;
不支持嵌套注释。(在某些情况下,可能允许嵌套注释,但通常不允许嵌套注释,用户应该避免使用嵌套注释。)
MySQLServer支持一些C样式注释的变体。通过使用以下形式的注释,可以编写包含MySQL扩展的代码,但仍然是可移植的:
/*! MySQL-specific code
*/
在这种情况下,MySQL Server像执行任何其他SQL语句一样,在注释中解析和执行代码,但其他SQL服务器将忽略这些扩展。例如,MySQL服务器识别STRAIGHT_JOIN
关键字出现在以下语句中,但其他服务器不会:
SELECT /*! STRAIGHT_JOIN */ col1 FROM table1,table2 WHERE ...
如果在!
字符,只有当MySQL版本大于或等于指定的版本号时,才会执行注释中的语法。这个KEY_BLOCK_SIZE
以下注释中的关键字仅由MySQL 5.1.10或更高版本的服务器执行:
CREATE TABLE t1(a INT, KEY (a)) /*!50110 KEY_BLOCK_SIZE=1024 */;
刚才描述的注释语法适用于米舍尔德服务器解析SQL语句。这个MySQL客户端程序在将语句发送到服务器之前还会执行一些语句解析。(它这样做是为了确定多语句输入行中的语句边界。)
这种格式的评论,/*!12345 ... */
,而不是存储在服务器上。如果使用此格式对存储的例程进行注释,则不会将注释保留在服务器上。
C样式注释语法的另一个变体用于指定优化器提示。提示注释包括+
后面的字符/*
注释开头序列。例子:
SELECT /*+ BKA(t1) */ FROM ... ;
有关更多信息,请参见第8.9.2节,“优化器提示”.
简体用法MySQL命令,如\C
多行/* ... */
不支持注释。