字符集 CHARACTE SET

字符(character)是各种文字和符号的总称,包括各国文字、标点符号、图形符号、数字等。

字符集(character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同。

常见字符集:ASCII、GBK、UTF8、Unicode 等等。

MySQL 字符集转换过程

  • MySQL Server 收到请求时,将请求数据从 character_set_client 转换为 character_set_connection

  • 然后,character_set_connection 转换为 MySQL 内部操作字符集。MySQL 内部操作字符集:

    • 如果 column 指定了字符集,则使用 column 指定的字符集
    • 如果 column 没有指定字符集,则使用 table 的字符集
    • 如果 table 也没有指定字符集,则使用 database 的字符集
    • 如果 database 也没有指定字符集,则使用 character_set_server 的值
  • 最后,将操作结果从内部操作字符集转换为 character_set_results

常见问题

  • 乱码

    • 当 character_set_client 与事实不符的时候。比如,character_set_client 明明是 utf8 的,但是,将它当成 GBK 去转换。
    • 当 character_set_results 与客户端页面的字符集不一致的时候。
    • 当数据保存到数据库之后,改变了内部操作字符集或者 character_set_connection。比如:

    数据表字符集设置为 utf8,插入时使用 MySQL 的默认设置(character_set_client、character_set_connectiong 和 character_set_results 都为 latin1)。插入之后,改变 character_set_connection 为 utf8.

    插入时,转换过程:latin1 -> latin1 -> utf8。3 字节的 latin1 转换为 6 字节的utf8。

    查询时,转换过程:utf8 -> utf8 -> latin1。6 字节的 utf8 原封不动返回。因此,肯定是会乱码的。

所以,如果插入数据到查询数据过程中没有更改过 MySQL 字符集,但是出现了乱码,一般情况都是页面字符集和 character_set_results 不一致造成的。

  • 数据丢失

    字符集也有大小的,当 character_set_client < character_set connection 或者 character_set_connectino < 内部字符集(数据保存的字符集格式) 时,字符转换过程中,除了乱码,还可能会出现字符丢失。

字符集乱码还可以调回来,但是数据丢失是找不回来的。

MySQL 字符集设置

  • column

    1
    2
    3
    4
    CREATE TABLE `member` (
    `name` varchar CHARACTER SET utf8
    );
    ALTER TABLE `member` CHANGE `name` varchar(25) CHARACTER SET utf8;
  • table

    1
    2
    3
    4
    CREATE TABLE `member` (
    ...
    ) DEFAULT CHARSET utf8;
    ALTER TABLE `member` DEFAULT CHARSET utf8;

CHARSETCHARACTER SET 一样,CHARSET 是简写。

  • database

    1
    set character_set_database = utf8;
  • character_set_server

    1
    set character_set_server = utf8;
  • character_set_connection

    1
    set character_set_contion = utf8;
  • character_set_results

    1
    set character_set_results = utf8;

如果 character_set_clientcharacter_set_connectioncharacter_set_results 都一样时,可以用 set names 语句来代替:

1
set names utf8;


校对规则/校对集 COLLATE

  • 校对规则,字符集内用于比较字符的规则。
  • 一个字符集可以有多个校对规则。如,字符集 utf8 的校对规则:utf8_general_ci、utf8_bin 等等。
  • 不同的校对规则,字符集内的字符排序不一样。如,utf8 字符集用 utf8_general_ci 校对规则,A 排在 b 前面。但是如果用 utf8_bin 校对规则, b 会排在 A 前面。
  • 每个字符集有一个默认校对规则。如,utf8 默认校对规则为 utf8_general_ci。
  • 校对规则命名约定:以字符集名称开头,以 ci(大小写不敏感)、cs(大小写敏感)、或 bin(二元) 结尾。

MySQL 校对规则设置

  • column

    1
    2
    3
    4
    CREATE TABLE `member` (
    `name` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci
    );
    ALTER TABLE `member` CHANGE COLUMN `name` CHARACTER SET utf8 COLLATE utf8_general_ci;
  • table

    1
    2
    3
    4
    CREATE TABLE `member` (
    ...
    ) DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
    ALTER TABLE `member` DEFAULT CHARSET utf8 COLLATE utf8_general_ci;