MySQL 字符集和排序规则

字符集是表示字符的一套规则,而排序规则则定义了字符集中字符的顺序。字符集用来存储数据。一个字符集中可以包含多种排序规则。

我们的世界是一个多元化的世界,包含了多种语言和不同的文字。为了让这些不同的文字更有效率地存储,出现了各种各样的字符集。

一个字符集定义了表示一组字符(并不一定是所有字符)规则。有的字符集只能表示单字节的字符,而有的字符集可以表示多字节的字符。有的字符集始终以多字节表示字符,而有的字符集使用单字节表示单字节字符,使用多字节表示多字节字符。

排序规则则是字符集中的字符的排序逻辑。比如在同一个字符集中的 Aa,在某个排序规则中是 A > a,在另一个排序规则中可能是 A = a 或者 A < a

同一个字符集支持多种排序规则,但是您必须使用其中的一个排序规则。

MySQL 字符集

MySQL 支持各种字符集,允许您将几乎所有字符存储在字符串中。

您可以使用 SHOW CHARACTER SET 语句获取当前的 MySQL 服务器支持的字符集和默认的排序规则。

SHOW CHARACTER SET;
+----------+---------------------------------+---------------------+--------+
| Charset  | Description                     | Default collation   | Maxlen |
+----------+---------------------------------+---------------------+--------+
| armscii8 | ARMSCII-8 Armenian              | armscii8_general_ci |      1 |
| ascii    | US ASCII                        | ascii_general_ci    |      1 |
| big5     | Big5 Traditional Chinese        | big5_chinese_ci     |      2 |
| binary   | Binary pseudo charset           | binary              |      1 |
| cp1250   | Windows Central European        | cp1250_general_ci   |      1 |
| cp1251   | Windows Cyrillic                | cp1251_general_ci   |      1 |
| cp1256   | Windows Arabic                  | cp1256_general_ci   |      1 |
| cp1257   | Windows Baltic                  | cp1257_general_ci   |      1 |
| cp850    | DOS West European               | cp850_general_ci    |      1 |
| cp852    | DOS Central European            | cp852_general_ci    |      1 |
| cp866    | DOS Russian                     | cp866_general_ci    |      1 |
| cp932    | SJIS for Windows Japanese       | cp932_japanese_ci   |      2 |
| dec8     | DEC West European               | dec8_swedish_ci     |      1 |
| eucjpms  | UJIS for Windows Japanese       | eucjpms_japanese_ci |      3 |
| euckr    | EUC-KR Korean                   | euckr_korean_ci     |      2 |
| gb18030  | China National Standard GB18030 | gb18030_chinese_ci  |      4 |
| gb2312   | GB2312 Simplified Chinese       | gb2312_chinese_ci   |      2 |
| gbk      | GBK Simplified Chinese          | gbk_chinese_ci      |      2 |
| geostd8  | GEOSTD8 Georgian                | geostd8_general_ci  |      1 |
| greek    | ISO 8859-7 Greek                | greek_general_ci    |      1 |
| hebrew   | ISO 8859-8 Hebrew               | hebrew_general_ci   |      1 |
| hp8      | HP West European                | hp8_english_ci      |      1 |
| keybcs2  | DOS Kamenicky Czech-Slovak      | keybcs2_general_ci  |      1 |
| koi8r    | KOI8-R Relcom Russian           | koi8r_general_ci    |      1 |
| koi8u    | KOI8-U Ukrainian                | koi8u_general_ci    |      1 |
| latin1   | cp1252 West European            | latin1_swedish_ci   |      1 |
| latin2   | ISO 8859-2 Central European     | latin2_general_ci   |      1 |
| latin5   | ISO 8859-9 Turkish              | latin5_turkish_ci   |      1 |
| latin7   | ISO 8859-13 Baltic              | latin7_general_ci   |      1 |
| macce    | Mac Central European            | macce_general_ci    |      1 |
| macroman | Mac West European               | macroman_general_ci |      1 |
| sjis     | Shift-JIS Japanese              | sjis_japanese_ci    |      2 |
| swe7     | 7bit Swedish                    | swe7_swedish_ci     |      1 |
| tis620   | TIS620 Thai                     | tis620_thai_ci      |      1 |
| ucs2     | UCS-2 Unicode                   | ucs2_general_ci     |      2 |
| ujis     | EUC-JP Japanese                 | ujis_japanese_ci    |      3 |
| utf16    | UTF-16 Unicode                  | utf16_general_ci    |      4 |
| utf16le  | UTF-16LE Unicode                | utf16le_general_ci  |      4 |
| utf32    | UTF-32 Unicode                  | utf32_general_ci    |      4 |
| utf8     | UTF-8 Unicode                   | utf8_general_ci     |      3 |
| utf8mb4  | UTF-8 Unicode                   | utf8mb4_0900_ai_ci  |      4 |
+----------+---------------------------------+---------------------+--------+

从 MySQL 8 开始,MySQL 默认的字符集为 utf8mb4,而早期版本的 MySQL 的默认字符集是 latin1latin1 字符集只能表示单字节字符,而 utf8mb4 字符集可以表示多字节字符包括表情符合。

MySQL 支持设置不同级别的字符集,包括: 服务器级,数据库级,表级,列级。您可以为不同的级别设置不同的字符集。

服务器级字符集和排序规则

服务器级字符集和排序规则是所有的数据库的默认的字符集和排序规则,若数据库不是指定,则采用服务器级的设置。

查看服务器字符集

要查看服务器级的字符集,请使用以下语句:

SHOW VARIABLES LIKE "character_set_server";
+----------------------+---------+
| Variable_name        | Value   |
+----------------------+---------+
| character_set_server | utf8mb4 |
+----------------------+---------+

要查看服务器级的排序规则,请使用以下语句:

SHOW VARIABLES LIKE "collation_server";
+------------------+--------------------+
| Variable_name    | Value              |
+------------------+--------------------+
| collation_server | utf8mb4_0900_ai_ci |
+------------------+--------------------+

设置服务器字符集和排序规则

您可以通过以下 3 中方法设置服务器的字符集。

  1. 在配置文件中设置 MySQL 服务器的字符集和排序规则:

    [mysqld]
    character-set-server = utf8mb4
    collation-server = utf8mb4_0900_ai_ci
    

    这是推荐的设置方式,它是永久的。在修改配置文件后,请记得重启 MySQL 服务器。

  2. 启动 MySQL 服务器时指定字符集和排序规则:

    mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_0900_ai_ci
    
  3. 在命令行修改字符集和排序规则。

    SET character_set_server = utf8mb4;
    SET collation_server = utf8mb4_0900_ai_ci;
    

    这只对当前会话有效。

数据库级的字符集和排序规则

数据库级的字符集和排序规则只对当前数据库生效,这也是数据库中的表的默认的字符集和排序规则。

要查看数据库的字符集和排序规则

要查看当前数据库的字符集和排序规则,请使用如下语句:

SELECT @@character_set_database, @@collation_database;
+--------------------------+----------------------+
| @@character_set_database | @@collation_database |
+--------------------------+----------------------+
| utf8mb4                  | utf8mb4_0900_ai_ci   |
+--------------------------+----------------------+

要查看指定数据库的字符集和排序规则,请使用如下语句:

SHOW CREATE DATABASE testdb;
+----------+----------------------------------------------------------------------------------------------------------------------------------+
| Database | Create Database                                                                                                                  |
+----------+----------------------------------------------------------------------------------------------------------------------------------+
| testdb   | CREATE DATABASE `testdb` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */ |
+----------+----------------------------------------------------------------------------------------------------------------------------------+

设置数据库级字符集和排序规则

您可以在创建数据库的时候通过 CHARACTER SETCOLLATE 子句指定字符集、排序规则,如下:

CREATE DATABASE database_name
[CHARACTER SET charset_name]
[COLLATE collation_name];

您也可以通过以下 ALTER DATABASE 修改数据库的字符集、排序规则:

ALTER DATABASE database_name
[CHARACTER SET charset_name]
[COLLATE collation_name];

表级字符集和排序规则

MySQL 支持为表设置不同的字符集和排序规则。如果没有设置,则继承数据库级的字符集和排序规则。

设置表级字符集和排序规则

要在创建表时为一个表设置字符集和排序规则,请使用如下 CREATE TABLE 语句:

CREATE TABLE table_name (column_list)
    [CHARACTER SET charset_name]
    [COLLATE collation_name]

要修改一个表的字符集和排序规则,请使用如下 ALTER TABLE 语句:

ALTER TABLE table_name
    [CHARACTER SET charset_name]
    [COLLATE collation_name]

查看表级字符集和排序规则

有 3 中方法查看一个表的字符集和排序规则:

  1. 使用 SHOW CREATE TABLE 语句查看一个表的字符集和排序规则:

    SHOW CREATE TABLE t1;
    
    *************************** 1. row ***************************
          Table: t1
    Create Table: CREATE TABLE `t1` (
      `c1` int DEFAULT NULL,
      `c2` char(1) DEFAULT NULL,
      `c3` json DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
  2. 使用 SHOW TABLE STATUS 语句查看一个表的字符集和排序规则:

    SHOW TABLE STATUS FROM testdb LIKE 't1'\G;
    
    *************************** 1. row ***************************
              Name: t1
            Engine: InnoDB
            Version: 10
        Row_format: Dynamic
              Rows: 5
    Avg_row_length: 3276
        Data_length: 16384
    Max_data_length: 0
      Index_length: 0
          Data_free: 0
    Auto_increment: NULL
        Create_time: 2022-04-20 02:31:42
        Update_time: NULL
        Check_time: NULL
          Collation: utf8mb4_0900_ai_ci
          Checksum: NULL
    Create_options:
            Comment:

    这里, Collation 列为排序规则, utf8mb4_0900_ai_ci 对应了字符集 utf8mb4

  3. information_schema.TABLES 表中查看一个表的字符集和排序规则:

    SELECT TABLE_COLLATION
    FROM information_schema.TABLES
    WHERE TABLE_SCHEMA = "testdb"
      AND TABLE_NAME = "t1"\G
    
    +--------------------+
    | TABLE_COLLATION    |
    +--------------------+
    | utf8mb4_0900_ai_ci |
    +--------------------+

    这里, TABLE_COLLATION 列为排序规则, utf8mb4_0900_ai_ci 对应了字符集 utf8mb4

列级字符集和排序规则

列默认的字符集和排序规则继承自表,但是 MySQL 支持为列设置不同的字符集和排序规则。

要为列设置独立的字符集和排序规则,请使用如下列定义:

col_name data_type
    [CHARACTER SET charset_name]
    [COLLATE collation_name]

您可以在 CREATE TABLEALTER TABLE 语句中使用上述的列定义,为列设置单独的字符集和排序规则。比如:

ALTER TABLE t1
MODIFY c4 VARCHAR(20)
    CHARACTER SET 'utf8'
    COLLATE 'utf8_bin';

要查看列的字符集和排序规则,请使用如下语句:

SELECT CHARACTER_SET_NAME,
  COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = "testdb"
  AND TABLE_NAME = "t1"
  AND COLUMN_NAME = "c4";

结论

MySQL 提供了各种字符集以有效地存储各种字符。您可以为服务器、数据库、表、和列设置不同的字符级和排序规则。

如果您需要在不同的字符集之间转换字符串,请使用 MySQL 提供的两个函数: CONVERTCAST