Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 85 additions & 85 deletions literal-values.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
---
title: 字面值
category: reference
summary: 本文介绍了 TiDB SQL 语句的字面值。
aliases: ['/docs-cn/v3.0/reference/sql/language-structure/literal-values/','/docs-cn/sql/literal-values/']
---

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

# 字面值

## String Literals
Expand All @@ -25,11 +28,12 @@ String Literals 是一个 bytes 或者 characters 的序列,两端被单引号

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

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

对于两种字符串类型,比较都是基于每个字符的数值。对于 binary string 而言,比较单元就是字节,对于非二进制的字符串,那么单元就是字符,而有的字符集支持多字节字符。
+ 二进制字符串 (binary string):由字节序列构成,它的 charset 和 collation 都是 `binary`,在互相比较时利用**字节**作为单位。
+ 非二进制字符串:由字符序列构成,有除 `binary` 以外的多种 charset 和 collation,在相互比较时用**字符**(一个字符可能包含多个字节,取决于 charset 的选择)作为单位。

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

```
[_charset_name]'string' [COLLATE collation_name]
Expand All @@ -55,26 +59,23 @@ 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 中使用 `'` 或者 `"`,有以下几种办法:
| 转义字符 | 含义 |
| :------ | :---- |
| \\0 | ASCII NUL (X'00') 字符 |
| \\' | 单引号 |
| \\" | 双引号 |
| \\b | 退格符号 |
| \\n | 换行符 |
| \\r | 回车符 |
| \\t | tab 符(制表符) |
| \\z | ASCII 26 (Ctrl + Z) |
| \\\\ | 反斜杠 \\ |
| \\% | \% |
| \\_ | \_ |

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

更多[细节](https://dev.mysql.com/doc/refman/5.7/en/string-literals.html)。

Expand All @@ -90,13 +91,61 @@ integer 可以包括 `.` 作为小数点分隔,数字前可以有 `-` 或者 `

更多[细节](https://dev.mysql.com/doc/refman/5.7/en/number-literals.html)。

## NULL Values
## Date and Time Literals

`NULL` 代表数据为空,它是大小写不敏感的,与 `\N`(大小写敏感) 同义
Date 跟 Time 字面值有几种格式,例如用字符串表示,或者直接用数字表示。在 TiDB 里面,当 TiDB 期望一个 Date 的时候,它会把 `'2017-08-24'`, `'20170824'`,`20170824` 当做是 Date

> **注意:**
>
> `NULL` 跟 `0` 并不一样,跟空字符串 `''` 也不一样。
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 字面值。
* `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 位。

更多[细节](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-literals.html)。

## Boolean Literals

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

{{< copyable "sql" >}}

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

## Hexadecimal Literals

Expand Down Expand Up @@ -142,8 +191,7 @@ select X'0aff';
+---------+
| X'0aff' |
+---------+
|
|
| 0x0aff |
+---------+
1 row in set (0.00 sec)
```
Expand Down Expand Up @@ -182,65 +230,9 @@ SELECT X'54694442';
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:00` 跟 `2017-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'`。
* 数值 `SS`,`MMSS`,`HHMMSS` 都是可以被当做 Time。

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

更多[细节](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-literals.html)。

## Boolean Literals

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

{{< copyable "sql" >}}

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

## Bit-Value Literals

位值字面值用 `b` 或者 `0b` 做前缀,后接以 0 跟 1 组成的二进制数字。其中 `0b` 是区分大小写的,`0B` 是会报错的
位值字面值用 `b` 或者 `0b` 做前缀,后接以 0 跟 1 组成的二进制数字。其中 `0b` 是区分大小写的,`0B` 则会报错

合法的 Bit-value:

Expand Down Expand Up @@ -282,3 +274,11 @@ SELECT b+0, BIN(b), HEX(b) FROM t;
+------+--------+--------+
3 rows in set (0.00 sec)
```

## NULL Values

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

> **注意:**
>
> `NULL` 跟 `0` 并不一样,跟空字符串 `''` 也不一样。