字面值

TiDB 字面值包括字符字面值、数值字面值、时间日期字面值、十六进制、二进制字面值和 NULL 字面值。以下分别对这些字面值进行一一介绍。

String Literals

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

  1. 'example string'
  2. "example string"

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

  1. 'a string'
  2. 'a' ' ' 'string'
  3. "a" ' ' "string"

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

字符串分为以下两种:

  • 二进制字符串 (binary string):由字节序列构成,它的 charset 和 collation 都是 binary,在互相比较时利用字节作为单位。
  • 非二进制字符串:由字符序列构成,有除 binary 以外的多种 charset 和 collation,在相互比较时用字符(一个字符可能包含多个字节,取决于 charset 的选择)作为单位。

一个 String Literal 可以拥有一个可选的 character set introducerCOLLATE clause,可以用来指定特定的 charset 和 collation。

  1. [_charset_name]'string' [COLLATE collation_name]

例如:

  1. SELECT _latin1'string';
  2. SELECT _binary'string';
  3. SELECT _utf8'string' COLLATE utf8_bin;

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

  1. SELECT N'some text';
  2. SELECT n'some text';
  3. SELECT _utf8'some text';

要在字符串中表示某些特殊字符,可以利用转义字符进行转义:

转义字符 含义
\0 ASCII NUL (X’00’) 字符
\‘ 单引号
\“ 双引号
\b 退格符号
\n 换行符
\r 回车符
\t tab 符(制表符)
\z ASCII 26 (Ctrl + Z)
\\ 反斜杠 \
\% \%
\_ _

如果要在 ' 包围的字符串中表示 ",或者在 " 包围的字符串中表示 ',可以不使用转义字符。

更多细节见 MySQL 官方文档

Numeric Literals

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

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

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

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

更多细节见 MySQL 官方文档

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 位),用小数点 . 分隔。

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

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

更多细节见 MySQL 官方文档

Boolean Literals

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

  1. SELECT TRUE, true, tRuE, FALSE, FaLsE, false;
  1. +------+------+------+-------+-------+-------+
  2. | TRUE | true | tRuE | FALSE | FaLsE | false |
  3. +------+------+------+-------+-------+-------+
  4. | 1 | 1 | 1 | 0 | 0 | 0 |
  5. +------+------+------+-------+-------+-------+
  6. 1 row in set (0.00 sec)

Hexadecimal Literals

十六进制字面值是有 X0x 前缀的字符串,后接表示十六进制的数字。注意 0x 是大小写敏感的,不能表示为 0X

例:

  1. X'ac12'
  2. X'12AC'
  3. x'ac12'
  4. x'12AC'
  5. 0xac12
  6. 0x12AC

以下是不合法的十六进制字面值:

  1. X'1z' (z 不是合法的十六进制值)
  2. 0X12AC (0X 必须用小写的 0x)

对于使用 X'val' 格式的十六进制字面值,val 必须要有一个数字,可以在前面补一个 0 来避免语法错误。

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

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

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

  1. SELECT HEX('TiDB');
  1. +-------------+
  2. | HEX('TiDB') |
  3. +-------------+
  4. | 54694442 |
  5. +-------------+
  6. 1 row in set (0.01 sec)
  1. SELECT X'54694442';
  1. +-------------+
  2. | X'54694442' |
  3. +-------------+
  4. | TiDB |
  5. +-------------+
  6. 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()

  1. CREATE TABLE t (b BIT(8));
  2. INSERT INTO t SET b = b'00010011';
  3. INSERT INTO t SET b = b'1110';
  4. INSERT INTO t SET b = b'100101';
  1. SELECT b+0, BIN(b), HEX(b) FROM t;
  1. +------+--------+--------+
  2. | b+0 | BIN(b) | HEX(b) |
  3. +------+--------+--------+
  4. | 19 | 10011 | 13 |
  5. | 14 | 1110 | E |
  6. | 37 | 100101 | 25 |
  7. +------+--------+--------+
  8. 3 rows in set (0.00 sec)

NULL Values

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

注意:

NULL0 并不一样,跟空字符串 '' 也不一样。