title | summary | aliases | ||
---|---|---|---|---|
字面值 |
本文介绍了 TiDB SQL 语句的字面值。 |
|
TiDB 字面值包括字符字面值、数值字面值、时间日期字面值、十六进制、二进制字面值和 NULL 字面值。以下分别对这些字面值进行一一介绍。
String Literals 是一个 bytes 或者 characters 的序列,两端被单引号 '
或者双引号 "
包围,例如:
'example string'
"example string"
如果字符串是连续的,会被合并为一个独立的 string。以下表示是一样的:
'a string'
'a' ' ' 'string'
"a" ' ' "string"
如果开启了 ANSI_QUOTES
SQL MODE,那么只有单引号内的会被认为是 String Literals,对于双引号内的字符串,会被认为是一个 identifier。
字符串分为以下两种:
- 二进制字符串 (binary string):由字节序列构成,它的 charset 和 collation 都是
binary
,在互相比较时利用字节作为单位。 - 非二进制字符串:由字符序列构成,有除
binary
以外的多种 charset 和 collation,在相互比较时用字符(一个字符可能包含多个字节,取决于 charset 的选择)作为单位。
一个 String Literal 可以拥有一个可选的 character set introducer
和 COLLATE clause
,可以用来指定特定的 charset 和 collation。
[_charset_name]'string' [COLLATE collation_name]
例如:
{{< copyable "sql" >}}
SELECT _latin1'string';
SELECT _binary'string';
SELECT _utf8'string' COLLATE utf8_bin;
你可以使用 N'literal'
或者 n'literal'
来创建使用 national character set 的字符串,下列语句是一样的:
{{< copyable "sql" >}}
SELECT N'some text';
SELECT n'some text';
SELECT _utf8'some text';
要在字符串中表示某些特殊字符,可以利用转义字符进行转义:
转义字符 | 含义 |
---|---|
\0 | ASCII NUL (X'00') 字符 |
\' | 单引号 |
\" | 双引号 |
\b | 退格符号 |
\n | 换行符 |
\r | 回车符 |
\t | tab 符(制表符) |
\z | ASCII 26 (Ctrl + Z) |
\\ | 反斜杠 \ |
\% | % |
\_ | _ |
如果要在 '
包围的字符串中表示 "
,或者在 "
包围的字符串中表示 '
,可以不使用转义字符。
更多细节见 MySQL 官方文档。
数值字面值包括 integer 跟 Decimal 类型跟浮点数字面值。
integer 可以包括 .
作为小数点分隔,数字前可以有 -
或者 +
来表示正数或者负数。
精确数值字面值可以表示为如下格式:1, .2, 3.4, -5, -6.78, +9.10
.
科学记数法也是被允许的,表示为如下格式:1.2E3, 1.2E-3, -1.2E3, -1.2E-3
。
更多细节见 MySQL 官方文档。
Date 跟 Time 字面值有几种格式,例如用字符串表示,或者直接用数字表示。在 TiDB 里面,当 TiDB 期望一个 Date 的时候,它会把 '2017-08-24'
, '20170824'
,20170824
当做是 Date。
TiDB 的 Date 值有以下几种格式:
-
'YYYY-MM-DD'
或者'YY-MM-DD'
,这里的-
分隔符并不是严格的,可以是任意的标点符号。比如'2017-08-24'
,'2017&08&24'
,'2012@12^31'
都是一样的。唯一需要特别对待的是 '.' 号,它被当做是小数点,用于分隔整数和小数部分。Date 和 Time 部分可以被 'T' 分隔,它的作用跟空格符是一样的,例如
2017-8-24 10:42:00
跟2017-8-24T10:42:00
是一样的。 -
'YYYYMMDDHHMMSS'
或者'YYMMDDHHMMSS'
,例如'20170824104520'
和'170824104520'
被当做是'2017-08-24 10:45:20'
,但是如果你提供了一个超过范围的值,例如'170824304520'
,那这就不是一个有效的 Date 字面值。需要注意YYYYMMDD HHMMSS
,YYYYMMDD HH:MM:DD
,YYYY-MM-DD HHMMSS
等不正确的格式会插入失败。 -
YYYYMMDDHHMMSS
或者YYMMDDHHMMSS
,注意这里没有单引号或者双引号,是一个数字。例如20170824104520
表示为'2017-08-24 10:45:20'
。
DATETIME 或者 TIMESTAMP 值可以接一个小数部分,用来表示微秒(精度最多到小数点后 6 位),用小数点 .
分隔。
如果 Date 的 year 部分只有两个数字,这是有歧义的(推荐使用四个数字的格式),TiDB 会尝试用以下的规则来解释:
- year 值如果在
70-99
范围,那么被转换成1970-1999
。 - year 值如果在
00-69
范围,那么被转换成2000-2069
。
对于小于 10 的 month 或者 day 值,'2017-8-4'
跟 '2017-08-04'
是一样的。对于 Time 也是一样,比如 '2017-08-24 1:2:3'
跟 '2017-08-24 01:02:03'
是一样的。
在需要 Date 或者 Time 的语境下, 对于数值,TiDB 会根据数值的长度来选定指定的格式:
- 6 个数字,会被解释为
YYMMDD
。 - 12 个数字,会被解释为
YYMMDDHHMMSS
。 - 8 个数字,会解释为
YYYYMMDD
。 - 14 个数字,会被解释为
YYYYMMDDHHMMSS
。
对于 Time 类型,TiDB 用以下格式来表示:
'D HH:MM:SS'
,或者'HH:MM:SS'
,'HH:MM'
,'D HH:MM'
,'D HH'
,'SS'
,这里的 D 表示 days,合法的范围是0-34
。- 数值
HHMMSS
,例如231010
被解释为'23:10:10'
。 - 数值
SS
,MMSS
,HHMMSS
都是可以被当做 Time。
Time 类型的小数点也是 .
,精度最多小数点后 6 位。
更多细节见 MySQL 官方文档。
常量 TRUE
和 FALSE
等于 1 和 0,它是大小写不敏感的。
{{< copyable "sql" >}}
SELECT TRUE, true, tRuE, FALSE, FaLsE, false;
+------+------+------+-------+-------+-------+
| TRUE | true | tRuE | FALSE | FaLsE | false |
+------+------+------+-------+-------+-------+
| 1 | 1 | 1 | 0 | 0 | 0 |
+------+------+------+-------+-------+-------+
1 row in set (0.00 sec)
十六进制字面值是有 X
和 0x
前缀的字符串,后接表示十六进制的数字。注意 0x
是大小写敏感的,不能表示为 0X
。
例:
X'ac12'
X'12AC'
x'ac12'
x'12AC'
0xac12
0x12AC
以下是不合法的十六进制字面值:
X'1z' (z 不是合法的十六进制值)
0X12AC (0X 必须用小写的 0x)
对于使用 X'val'
格式的十六进制字面值,val
必须包含偶数个字符,如果 val
的长度是奇数(比如 X'A'、X'11A'),可以在前面补一个 0 来避免语法错误。
{{< copyable "sql" >}}
select X'aff';
ERROR 1105 (HY000): line 0 column 13 near ""hex literal: invalid hexadecimal format, must even numbers, but 3 (total length 13)
{{< copyable "sql" >}}
select X'0aff';
+---------+
| X'0aff' |
+---------+
| 0x0aff |
+---------+
1 row in set (0.00 sec)
默认情况,十六进制字面值是一个二进制字符串。
如果需要将一个字符串或者数字转换为十六进制字面值,可以使用内建函数 HEX()
:
{{< copyable "sql" >}}
SELECT HEX('TiDB');
+-------------+
| HEX('TiDB') |
+-------------+
| 54694442 |
+-------------+
1 row in set (0.01 sec)
{{< copyable "sql" >}}
SELECT X'54694442';
+-------------+
| X'54694442' |
+-------------+
| TiDB |
+-------------+
1 row in set (0.00 sec)
位值字面值用 b
或者 0b
做前缀,后接以 0 和 1 组成的二进制数字。其中 0b
是区分大小写的,0B
则会报错。
合法的 Bit-value:
- b'01'
- B'01'
- 0b01
非法的 Bit-value:
- b'2' (2 不是二进制数值, 必须为 0 或 1)
- 0B01 (0B 必须是小写 0b)
默认情况,位值字面值是一个二进制字符串。
Bit-value 是作为二进制返回的,所以输出到 MySQL Client 可能会无法显示,如果要转换为可打印的字符,可以使用内建函数 BIN()
或者 HEX()
:
{{< copyable "sql" >}}
CREATE TABLE t (b BIT(8));
INSERT INTO t SET b = b'00010011';
INSERT INTO t SET b = b'1110';
INSERT INTO t SET b = b'100101';
{{< copyable "sql" >}}
SELECT b+0, BIN(b), HEX(b) FROM t;
+------+--------+--------+
| b+0 | BIN(b) | HEX(b) |
+------+--------+--------+
| 19 | 10011 | 13 |
| 14 | 1110 | E |
| 37 | 100101 | 25 |
+------+--------+--------+
3 rows in set (0.00 sec)
NULL
代表数据为空,它是大小写不敏感的,与 \N
(大小写敏感)同义。
注意:
NULL
跟0
并不一样,跟空字符串''
也不一样。