【MySQL】字符集与排序规则
1. 字符集
1.1 一些重要的字符集
1.1.1 ASCII
共收录128个字符,包括空格、标点符号、数字、大小写字母和一些不可见字符。由于总共才128个字符,所以可以使用1个字节来进行编码
1.1.2ISO-8859-1
共收录 256 个字符,是在 ASCII 字符集的基础上又扩充了 128个 西欧常用字符(包括德法两国的字母),也可以使用1个字节来进行编码。这个字符集也有一个别名 latin1。
1.1.3GB2312
收录了汉字以及拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母。其中收录汉字6763个,其他文字符号682个。同时这种字符集又兼容 ASCII 字符集,所以有以下规则:
- 如果该字符在 ASCII 字符集中,则采用 1 字节编码。
- 否则采用 2 字节编码。
1.1.4GBK
GBK 字符集只是在收录字符范围上对GB2312 字符集作了扩充,编码方式上兼容GB2312 。
1.1.5UTF8
收录地球上能想到的所有字符,而且还在不断扩充。这种字符集兼容 ASCII 字符集,采用变长编码方式,编码一个字符需要使用1~4个字节
UTF8 只是 Unicode 字符集的一种编码方案,Unicode字符集可以采用UTF8、UTF16、UTF32 这几种编码方案,UTF8 使用1~4个字节编码一个字符,UTF16 使用 2 个或 4 个字节编码一个字符,UTF32使用 4 个字节编码一个字符。
1.2 MySQL 中的 utf8 和 utf8mb4
- utf8(utf8mb3):阉割过的 utf8 字符集,使用1~3个字节表示字符。
- utf8mb4:正宗的 utf8 字符集,使用1~4个字节表示字符。
1.3 查看字符集
1.3.1 语法
SHOW (CHARACTER SET | CHARSET)[LIKE 匹配的模式]
Charset
Description
Default collation
Maxlen
big5
Big5 Traditional Chinese
big5_chinese_ci
2
dec8
DEC West European
dec8_swedish_ci
1
cp850
DOS West European
cp850_general_ci
1
hp8
HP West European
hp8_english_ci
1
koi8r
KOI8-R Relcom Russian
koi8r_general_ci
1
latin1
cp1252 West European
latin1_swedish_ci
1
latin2
ISO 8859-2 Central European
latin2_general_ci
1
swe7
7bit Swedish
swe7_swedish_ci
1
ascii
US ASCII
ascii_general_ci
1
ujis
EUC-JP Japanese
ujis_japanese_ci
3
sjis
Shift-JIS Japanese
sjis_japanese_ci
2
hebrew
ISO 8859-8 Hebrew
hebrew_general_ci
1
tis620
TIS620 Thai
tis620_thai_ci
1
euckr
EUC-KR Korean
euckr_korean_ci
2
koi8u
KOI8-U Ukrainian
koi8u_general_ci
1
gb2312
GB2312 Simplified Chinese
gb2312_chinese_ci
2
greek
ISO 8859-7 Greek
greek_general_ci
1
cp1250
Windows Central European
cp1250_general_ci
1
gbk
GBK Simplified Chinese
gbk_chinese_ci
2
latin5
ISO 8859-9 Turkish
latin5_turkish_ci
1
armscii8
ARMSCII-8 Armenian
armscii8_general_ci
1
utf8
UTF-8 Unicode
utf8_general_ci
3
ucs2
UCS-2 Unicode
ucs2_general_ci
2
cp866
DOS Russian
cp866_general_ci
1
keybcs2
DOS Kamenicky Czech-Slovak
keybcs2_general_ci
1
macce
Mac Central European
macce_general_ci
1
macroman
Mac West European
macroman_general_ci
1
cp852
DOS Central European
cp852_general_ci
1
latin7
ISO 8859-13 Baltic
latin7_general_ci
1
utf8mb4
UTF-8 Unicode
utf8mb4_general_ci
4
cp1251
Windows Cyrillic
cp1251_general_ci
1
utf16
UTF-16 Unicode
utf16_general_ci
4
utf16le
UTF-16LE Unicode
utf16le_general_ci
4
cp1256
Windows Arabic
cp1256_general_ci
1
cp1257
Windows Baltic
cp1257_general_ci
1
utf32
UTF-32 Unicode
utf32_general_ci
4
binary
Binary pseudo charset
binary
1
geostd8
GEOSTD8 Georgian
geostd8_general_ci
1
cp932
SJIS for Windows Japanese
cp932_japanese_ci
2
eucjpms
UJIS for Windows Japanese
eucjpms_japanese_ci
3
gb18030
China National Standard GB18030
gb18030_chinese_ci
4
我使用的 MySQL 这个版本一共支持 41 种字符集,其中的 Default collation 列表示这种字符集中一种默认的比较规则。大家注意返回结果中的最后一列 Maxlen,它代表该种字符集表示一个字符最多需要几个字节。以下几个字符集的 Maxlen 需要重点关注:
- ascii:1
- latin1:1
- gb2312:2
- gbk:2
- utf8:3
- utf8mb4:4
2. 比较规则
一种字符集可能对应着若干种比较规则,不同的比较规则对于相同字符产生的结果可能不同,比如说在字符集为 latin1,比较规则为 latin1_general_ci 的情况下,A 和 a 是相等的,如果将比较规则改为latin1_general_cs,则不相等。
2.1 举例演示
2.1.1 创建一个比较规则为 latin1_general_ci 的表,插入一些数据,然后查询出来
通过现象可以表明对于比较规则为 latin1_general_ci 的表,小写和小写是不区分的
2.1.2 将比较规则改为 latin1_general_cs,查看现象
通过现象可以表明对于比较规则为 latin1_general_cs的表,小写和小写是区分的
2.2查看比较规则
2.2.1 语法
SHOW COLLATION [LIKE 匹配的模式]
2.2.2 查看比较规则
查看 utf8 相关比较规则
SHOW COLLATION LIKE ‘utf8_%’;
Collation
Charset
Id
Default
Compiled
Sortlen
utf8_general_ci
utf8
33
Yes
Yes
1
utf8_bin
utf8
83
Yes
1
utf8_unicode_ci
utf8
192
Yes
8
utf8_icelandic_ci
utf8
193
Yes
8
utf8_latvian_ci
utf8
194
Yes
8
utf8_romanian_ci
utf8
195
Yes
8
utf8_slovenian_ci
utf8
196
Yes
8
utf8_polish_ci
utf8
197
Yes
8
utf8_estonian_ci
utf8
198
Yes
8
utf8_spanish_ci
utf8
199
Yes
8
utf8_swedish_ci
utf8
200
Yes
8
utf8_turkish_ci
utf8
201
Yes
8
utf8_czech_ci
utf8
202
Yes
8
utf8_danish_ci
utf8
203
Yes
8
utf8_lithuanian_ci
utf8
204
Yes
8
utf8_slovak_ci
utf8
205
Yes
8
utf8_spanish2_ci
utf8
206
Yes
8
utf8_roman_ci
utf8
207
Yes
8
utf8_persian_ci
utf8
208
Yes
8
utf8_esperanto_ci
utf8
209
Yes
8
utf8_hungarian_ci
utf8
210
Yes
8
utf8_sinhala_ci
utf8
211
Yes
8
utf8_german2_ci
utf8
212
Yes
8
utf8_croatian_ci
utf8
213
Yes
8
utf8_unicode_520_ci
utf8
214
Yes
8
utf8_vietnamese_ci
utf8
215
Yes
8
utf8_general_mysql500_ci
utf8
223
Yes
1
比较规则有以下规则:
-
比较规则名称以与其关联的字符集的名称开头。如上图的查询结果的比较规则名称都是以utf8开头的。
-
后边紧跟着该比较规则主要作用于哪种语言,比如utf8_polish_ci 表示以波兰语的规则比较,utf8_spanish_ci是以西班牙语的规则比较,utf8_general_ci 是一种通用的比较规则。
-
名称后缀意味着该比较规则是否区分语言中的重音、大小写啥的,具体可以用的值如下:
后缀
英文释义
描述
_ai
accent insensitive
不区分重音
_as
accent sensitive
区分重音
_ci
case insensitive
不区分大小写
_cs
case sensitive
区分大小写
_bin
binary
以二进制方式比较
3. 字符集和比较规则的级别
- 服务器级别
- 数据库级别
- 表级别
- 列级别
3.1 服务器级别
- character_set_server:服务器级别字符集
- collation_server:服务器级别比较规则
3.1.1 查看服务器级别的字符集和比较规则
show variables like ‘character_set_server’;
show variables like ‘collation_server’;
3.1.2 修改服务器的默认值
在类 UNIX 操作系统中,MySQL 会按照下列路径来寻找配置文件:
- /etc/my.cnf
- /etc/mysql/my.cnf
- SYSCONFDIR/my.cnf
- $MYSQL_HOME/my.cnf:特定于服务器的选项(仅限服务器)
- defaults-extra-file:命令行指定的额外配置文件路径
- ~/.my.cnf:用户特定选项
- ~/.mylogin.cnf:用户特定的登录路径选项(仅限客户端)
我们以修改 /etc/mysql/my.cnf 为例
[server]
character_set_server=latin1
collation_server=latin1_general_cs
修改完重启服务,再次执行查询语句
PS : 有可能修改完不生效,可以执行 chmod 644 my.cnf 修改权限
3.2数据库级别
3.2.1 语法
我们在创建和修改数据库的时候可以指定该数据库的字符集和比较规则,具体语法如下:
CREATE DATABASE 数据库名
[[DEFAULT] CHARACTER SET 字符集名称]
[[DEFAULT] COLLATE 比较规则名称];
ALTER DATABASE 数据库名
[[DEFAULT] CHARACTER SET 字符集名称]
[[DEFAULT] COLLATE 比较规则名称];
3.2.2查看数据库级别的字符集和比较规则
SHOW VARIABLES LIKE ‘character_set_database’;
SHOW VARIABLES LIKE ‘collation_database’;
可以看到这个 demo_db 数据库的字符集和比较规则就是我们在创建语句中指定的。需要注意的一点是:character_set_database 和 collation_database 这两个系统变量是只读的,我们不能通过修改这两个变量的值而改变当前数据库的字符集和比较规则。
如果未指定数据库级别的字符集和比较规则,则使用服务器级别的字符集和比较规则
3.3 表级别
3.3.1 语法
我们也可以在创建和修改表的时候指定表的字符集和比较规则,语法如下:
CREATE TABLE 表名 (列的信息)
[[DEFAULT] CHARACTER SET 字符集名称]
[COLLATE 比较规则名称]]ALTER TABLE 表名
[[DEFAULT] CHARACTER SET 字符集名称]
[COLLATE 比较规则名称]
3.3.2查看表级别的字符集和比较规则
SHOW TABLE STATUS LIKE ‘table_name’;
如果创建表的语句中没有指明字符集和比较规则,将使用该表所在数据库的字符集和比较规则作为该表的字符集和比较规则。
3.4 列级别
3.4.1 语法
CREATE TABLE 表名( 列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称], 其他列… );
ALTER TABLE 表名 MODIFY 列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称];
3.4.2 修改列的字符集和比较规则
可以看出修改完,表的字符集是gb2312,列的字符集是utf8
如果在创建和修改的语句中没有指明字符集和比较规则,将使用该列所在表的字符集和比较规则作为该列的字符集和比较规则。
PS :在转换列的字符集时需要注意,如果转换前列中存储的数据不能用转换后的字符集进行表示会发生错误。比方说原先列使用的字符集是utf8,列中存储了一些汉字,现在把列的字符集转换为ascii的话就会出错,因为ascii字符集并不能表示汉字字符。
4 仅修改字符集或仅修改比较规则
由于字符集和比较规则是互相有联系的,如果我们只修改了字符集,比较规则也会跟着变化,如果只修改了比较规则,字符集也会跟着变化,具体规则如下:
- 只修改字符集,则比较规则将变为修改后的字符集默认的比较规则。
- 只修改比较规则,则字符集将变为修改后的比较规则对应的字符集。
5.MySQL中字符集的转换
5.1 相关变量
系统变量
描述
character_set_client
服务器解码请求时使用的字符集
character_set_connection
服务器处理请求时会把请求字符串从character_set_client转为character_set_connection
character_set_results
服务器向客户端返回数据时使用的字符集
5.2 转换过程
5.3修改相关变量的值
SET NAMES 字符集名;
等价于
SET character_set_client = 字符集名;
SET character_set_connection = 字符集名;
SET character_set_results = 字符集名;