字面值

String Literals

String Literals 是一个 bytes 或者 characters 的序列,两端被单引号 ' 或者双引号 " 包围,例如:

'example string' "example string"

如果字符串是连续的,会被合并为一个独立的 string。以下表示是一样的:

'a string' 'a' ' ' 'string' "a" ' ' "string"

如果 ANSI_QUOTES SQL MODE 开启了,那么只有单引号内的会被认为是 String Literals,对于双引号内的字符串,会被认为是一个 identifier。

binary string 是一串 bytes 组成的字符串,每一个 binary string 有一个叫做 binary 的 character set 和 collation。一个非二进制的字符串是一个由字符组成的字符串,它有除 binary 外的 character set和与之兼容的 collation。

对于两种字符串类型,比较都是基于每个字符的数值。对于 binary string 而言,比较单元就是字节,对于非二进制的字符串,那么单元就是字符,而有的字符集支持多字节字符。

一个 String Literal 可以拥有一个可选的 character set introducerCOLLATE clause,可以用来指派特定的字符集跟 collation(TiDB 对此只是做了语法上的兼容,并不实质做处理)。

[_charset_name]'string' [COLLATE collation_name]

例如:

SELECT _latin1'string'; SELECT _binary'string'; SELECT _utf8'string' COLLATE utf8_bin;

你可以使用 N'literal' 或者 n'literal' 来创建使用 national character set 的字符串,下列语句是一样的:

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)
  • \\: 反斜杠 \
  • \%: \%
  • \_: _

如果要在 string literal 中使用 ' 或者 ",有以下几种办法:

  • ' 引用的字符串中,可以用 '' 来表示单引号。
  • " 引用的字符串中,可以用 "" 来表示双引号。
  • 前面接转义符\
  • ' 中表示 " 或者在 " 中表示 ' 都不需要特别的处理。

更多细节

Numeric Literals

数值字面值包括 integer 跟 Decimal 类型跟浮点数字面值。

integer 可以包括 . 作为小数点分隔,数字前可以有 - 或者 + 来表示正数或者负数。

精确数值字面值可以表示为如下格式:1, .2, 3.4, -5, -6.78, +9.10.

科学记数法也是被允许的,表示为如下格式:1.2E3, 1.2E-3, -1.2E3, -1.2E-3

更多细节

NULL Values

NULL 代表数据为空,它是大小写不敏感的,与 \N(大小写敏感) 同义。

Hexadecimal Literals

十六进制字面值是有 X0x 前缀的字符串,后接表示十六进制的数字。注意 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 来避免语法错误。

mysql> select X'aff'; ERROR 1105 (HY000): line 0 column 13 near ""hex literal: invalid hexadecimal format, must even numbers, but 3 (total length 13) mysql> select X'0aff'; +---------+ | X'0aff' | +---------+ | | +---------+ 1 row in set (0.00 sec)

默认情况,十六进制字面值是一个二进制字符串。

如果需要将一个字符串或者数字转换为十六进制字面值,可以使用内建函数 HEX()

mysql> SELECT HEX('TiDB'); +-------------+ | HEX('TiDB') | +-------------+ | 54694442 | +-------------+ 1 row in set (0.01 sec) mysql> SELECT X'54694442'; +-------------+ | X'54694442' | +-------------+ | TiDB | +-------------+ 1 row in set (0.00 sec)

Date and Time Literals

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:002017-8-24T10:42:00 是一样的。
  • 'YYYYMMDDHHMMSS' 或者 'YYMMDDHHMMSS',例如 '20170824104520''170824104520' 被当做是 '2017-08-24 10:45:20',但是如果你提供了一个超过范围的值,例如'170824304520',那这就不是一个有效的 Date 字面值。
  • YYYYMMDDHHMMSS 或者 YYMMDDHHMMSS 注意这里没有单引号或者双引号,是一个数字。例如 20170824104520表示为 '2017-08-24 10:45:20'

DATETIME 或者 TIMESTAMP 值可以接一个小数部分,用来表示微秒(精度最多到小数点后 6 位),用小数点 . 分隔。

Dates 如果 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'
  • 数值 SSMMSSHHMMSS 都是可以被当做 Time。

Time 类型的小数点也是 .,精度最多小数点后 6 位。

更多细节

Boolean Literals

常量 TRUEFALSE 等于 1 和 0,它是大小写不敏感的。

mysql> 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)

Bit-Value Literals

位值字面值用 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()

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'; mysql> 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)