MySQL字符集与校对集
Table of Contents
创建数据库
创建数据库的时候,除了数据库名,还有两个参数:字符集(Character Set)和校对集(Collation)。
下图是我用“Sequel Pro”创建数据库时的界面(Sequel Pro只有macOS有),它需要选Encoding和Collation
用“Navicat Premium”创建数据库,它需要选Character Set和Collation
用命令创建数据库也可以指定编码(CHARSET)和校对集(COLLATE)
CREATE DATABASE `wordpress` DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
编码与字符集的区别
以上两个软件中,数据库名我们就不用看了,另外的参数共有三个:
- Encoding:编码,由于编码者是一个集合,我们一般叫它“编码集”;
- Character Set:字符集;
- Collation:Collation是校对的意思,但由于它其实就是一组规则的集合,所以我们一般叫它“校对集”,但“校对集”让人比较难理解,其实它就是“一组排序规则”。
从创建数据库里的两个工具的对应上来看,Sequel Pro里的Encoding与Navicat Premium里的Character Set是一个意思,也就是说,从这两个软件上来看,编码与字符集是一个意思。
但事实上,编码和字符集是有区别的,对于ASCII字符集,它只有一种编码,那就是ASCII码,所以ASCII的编码集和字符集是一样的,但Unicode字符集就不止一种编码了,它有UTF-8、UTF-16、UTF-32三种编码。但我们平时说,都说字符集,不说编码集。
编码是什么,我想就不需要解释了吧,所有的文字、符号、表情要保存到硬盘中,最终肯定要变成一个数字,毕竟电脑的本名叫计算机,计算机计算机,当然就是计算数字用的,它的所有数据都是二进制的,只有数字才能变成二进制,所以字符必须编码成数字,最经典的就是ASCII码,在ASCII中,大写A是十进制的65,而小写a则是十进制的97,即65对应A,97对应a,这就是最基础的“编码”。
当然,ASCII只能表示26个英文字母+10个数字+常见的标点符号+少量的其它符号,但世界上有很多语言,每种语言的文字都不一样,所以每种文字都有自己的编码,比如中文常见的有GB2312和GBK(GB是国标的拼音首字母,K是扩展的“扩”字的拼音首字母,表示“扩展字符集”的意思)。
MySQL8.0默认的字符集(charset)是utfmb4编码的(Chapter 10 Character Sets, Collations, Unicode),我们建库的时候用这个编码就可以(文本中存emoji表情需要这个编码),mb是multibytes(多字节)的意思,4就是4个字节的意思,其实在mysql添加utf8mb4之前的那个“utf8”是“utf8mb3”,只不过没有把mb3写出来呗了。
校对集(Collation)
校对集,其实就是比较规则、排序规则,比如,按字母顺序排序,小写b肯定排在小写a后面,那为什么数据库会知道b排在a后面呢?因为b的ASCII是98,a的ASCII是97,从小到大排,98肯定排在97的后面。
然而,实际的排序,比a和b排序复杂的多,比如中文排序按拼音首字母、按声调、德语法语之类的也是有声调的,排序的时候,决定哪个字排前面,哪个字排后面的一组规则,就叫“校对集(Collation)”。
utf8mb4_0900_ai_ci解释:
- 0900是排序算法的版本号;
- ai表示accent insensitive(音调不敏感),比如在排序时,认为e, è, é, ê, ë是一样的;
- as表示accent sensitive(音调敏感),比如在排序时,认为e, è, é, ê, ë是不同的;
- ci表示case insensitive(大小写不敏感),即不区分大小写;
- cs表示case sensitive(大小写敏感),表示区分大小写;
- mysql8.0.1之后默认都是utf8mb4字符集以及utf8mb4_0900_ai_ci校对集(也就是排序时,不区分口音及大小写),在8.0.1之前默认校对集是utf8mb4_0900_general_ci。
查看当前数据库的字符集与校对集
SELECT @@character_set_database, @@collation_database;
# 或者用这个,手打起来更方便
show create database <数据库名>;
查看mysql中的所有字符集
mysql> show variables like "%character%";
+--------------------------+------------------------------------------------------+
| Variable_name | Value |
+--------------------------+------------------------------------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8mb3 |
| character_sets_dir | /usr/local/Cellar/mysql/8.0.29/share/mysql/charsets/ |
+--------------------------+------------------------------------------------------+
8 rows in set (0.00 sec)
+--------------------------+-----------------------------------------------------+
| 变量名 | 含义 |
+--------------------------+-----------------------------------------------------+
| character_set_client | 客户端字符集 |
| character_set_connection | 连接字符集 |
| character_set_database | 数据库字符集 |
| character_set_filesystem | 文件系统字符集 |
| character_set_results | 查询结果字符集 |
| character_set_server | 服务器字符集 |
| character_set_system | 系统字符集 |
| character_sets_dir | 字符集文件夹 |
+--------------------------+------------------------------------------------------+
其中character_set_system是指mysql用来存储标识符(identifiers)用的,比如存储数据库名、表名、字段名、索引名等用的字符集。
而character_set_server则是mysql服务器内部操作字符集,比如查询表中的数据,暂存在内存中,这个数据也是要有字符集的。
MySQL中使用set names
来设置字符集(单引号可省略不写)
SET NAMES 'utf8mb4';
相当于同时设置以下三个字符集
set character_set_client = utf8;
set character_set_results = utf8;
set character_set_connection = utf8;
如果你设置utf8,其实就是设置了utf8mb3,因为mb3是utf8默认的,所以就没把mb3写出来,即以下两个语句是等效的
SET NAMES 'utf8';
SET NAMES 'utf8mb3';