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
88 changes: 86 additions & 2 deletions character-set-and-collation.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,41 @@ aliases: ['/docs-cn/dev/character-set-and-collation/','/docs-cn/dev/reference/sq

## 字符集和排序规则的概念

字符集 (character set) 是符号与编码的集合。
字符集 (character set) 是符号与编码的集合。TiDB 中的默认字符集是 utf8mb4,与 MySQL 8.0 及更高版本中的默认字符集匹配。

排序规则 (collation) 是在字符集中比较字符的规则。
排序规则 (collation) 是在字符集中比较字符以及字符排序顺序的规则。例如,在二进制排序规则中,比较“A”和“a”的结果是不一样的:

{{< copyable "sql" >}}

```sql
SET NAMES utf8mb4 COLLATE utf8mb4_bin;
SELECT 'A' = 'a';
SET NAMES utf8mb4 COLLATE utf8mb4_general_ci;
SELECT 'A' = 'a';
```

```sql
mysql> SELECT 'A' = 'a';
+-----------+
| 'A' = 'a' |
+-----------+
| 0 |
+-----------+
1 row in set (0.00 sec)

mysql> SET NAMES utf8mb4 COLLATE utf8mb4_general_ci;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT 'A' = 'a';
+-----------+
| 'A' = 'a' |
+-----------+
| 1 |
+-----------+
1 row in set (0.00 sec)
```

TiDB 默认使用二进制排序规则。这一点与 MySQL 不同,MySQL 默认使用不区分大小写的排序规则。

## 支持的字符集和排序规则

Expand Down Expand Up @@ -52,6 +84,22 @@ mysql> show collation;
5 rows in set (0.01 sec)
```

TiDB 支持以下排序规则:

```sql
mysql> show collation;
+-------------+---------+------+---------+----------+---------+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+-------------+---------+------+---------+----------+---------+
| utf8mb4_bin | utf8mb4 | 46 | Yes | Yes | 1 |
| latin1_bin | latin1 | 47 | Yes | Yes | 1 |
| binary | binary | 63 | Yes | Yes | 1 |
| ascii_bin | ascii | 65 | Yes | Yes | 1 |
| utf8_bin | utf8 | 83 | Yes | Yes | 1 |
+-------------+---------+------+---------+----------+---------+
5 rows in set (0.01 sec)
```

> **注意:**
>
> TiDB 中的默认排序规则(后缀为 `_bin` 的二进制排序规则)与 [MySQL 中的默认排序规则](https://dev.mysql.com/doc/refman/8.0/en/charset-charsets.html)不同,后者通常是一般排序规则,后缀为 `_general_ci`。当用户指定了显式字符集,但依赖于待选的隐式默认排序规则时,这个差异可能导致兼容性问题。
Expand All @@ -74,6 +122,42 @@ SHOW COLLATION WHERE Charset = 'utf8mb4';
2 rows in set (0.00 sec)
```

## TiDB 中的 `utf8` 和 `ut8mb4`

MySQL 限制字符集 `utf8` 为最多 3 个字节。这足以存储在基本多语言平面 (BMP) 中的字符,但不足以存储表情符号等字符。因此,建议改用字符集`utf8mb4`。

默认情况下,TiDB 同样限制字符集 `utf8` 为最多 3 个字节,以确保 TiDB 中创建的数据可以在 MySQL 中顺利恢复。你可以禁用此功能,方法是在 TiDB 配置文件中将 `check-mb4-value-in-utf8` 的值更改为 `FALSE`。

以下示例演示了在表中插入 4 字节的表情符号字符时的默认行为。`utf8` 字符集下 `INSERT` 语句不能执行,`ut8mb4` 字符集下可以执行 `INSERT` 语句:

```sql
mysql> CREATE TABLE utf8_test (
-> c char(1) NOT NULL
-> ) CHARACTER SET utf8;
Query OK, 0 rows affected (0.09 sec)

mysql> CREATE TABLE utf8m4_test (
-> c char(1) NOT NULL
-> ) CHARACTER SET utf8mb4;
Query OK, 0 rows affected (0.09 sec)

mysql> INSERT INTO utf8_test VALUES ('😉');
ERROR 1366 (HY000): incorrect utf8 value f09f9889(😉) for column c
mysql> INSERT INTO utf8m4_test VALUES ('😉');
Query OK, 1 row affected (0.02 sec)

mysql> SELECT char_length(c), length(c), c FROM utf8_test;
Empty set (0.01 sec)

mysql> SELECT char_length(c), length(c), c FROM utf8m4_test;
+----------------+-----------+------+
| char_length(c) | length(c) | c |
+----------------+-----------+------+
| 1 | 4 | 😉 |
+----------------+-----------+------+
1 row in set (0.00 sec)
```

## 不同范围的字符集和排序规则

字符集和排序规则可以在设置在不同的层次。
Expand Down