utf8字符集下的比较规则

本文涉及的产品
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 在MySQL中,比较常用的字符集是utf8和utf8mb4。这两个字符集是类似的,utf8是utf8mb3的别名,所以之后在MySQL中提到utf8就意味着使用1~3个字节来表示一个字符,如果大家有使用4字节编码一个字符的情况,比如存储一些emoji表情啥的,需要使用utf8mb4。其实每个字符集下对应着若干个比较规则(也可以翻译为排序规则或校对规则,英文是COLLATE),同一字符集下,使用不同的比较规则会影响字符字段的比较和排序。本文以utf8为例,介绍下常用的几个比较规则的不同。

1.utf8下比较规则概览


我们先查看下utf8字符集下支持的所有比较规则:

mysql> 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 以二进制方式比较

比如utf8_general_ci这个比较规则是以ci结尾的,说明不区分大小写

每种字符集都有一种默认的比较规则,SHOW COLLATION的返回结果中的Default列的值为YES的就是该字符集的默认比较规则,比方说utf8字符集默认的比较规则就是utf8_general_ci


比较规则可以作用于四个级别,分别是:服务器级别、数据库级别、表级别、列级别。服务器级别的比较规则由collation_server参数控制,如果创建数据库、表、列时没有显式的指定比较规则,则会继承上一级的比较规则。下面给出创建及修改库、表、列的比较规则的示例语句:

# 创建数据库指定比较规则 修改数据库的比较规则
CREATE DATABASE 数据库名
    [[DEFAULT] CHARACTER SET 字符集名称]
    [[DEFAULT] COLLATE 比较规则名称];
ALTER DATABASE 数据库名
    [[DEFAULT] CHARACTER SET 字符集名称]
    [[DEFAULT] COLLATE 比较规则名称];
# 创建表时指定比较规则 修改表的比较规则
CREATE TABLE 表名 (列的信息)
    [[DEFAULT] CHARACTER SET 字符集名称]
    [COLLATE 比较规则名称]]
ALTER TABLE 表名
    [[DEFAULT] CHARACTER SET 字符集名称]
    [COLLATE 比较规则名称]
# 创建时指定列的比较规则 修改列的比较规则
CREATE TABLE 表名(
    列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称],
    其他列...
);
ALTER TABLE 表名 MODIFY 列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称];


2.几种比较规则对比


utf8字符集下默认的比较规则是utf8_general_ci,日常中会用到的有utf8_general_ci,utf8_unicode_ci,utf8_bin三种比较规则,其他比较规则基本很少会用,下面简单了解下这三种比较规则的异同。


首先utf8_bin的比较方法其实就是直接将所有字符看作二进制串,然后从最高位往最低位比对。所以很显然它是区分大小写的。而utf8_general_ci和utf8_unicode_ci是不区分大小写的。


utf8_general_ci和utf8_unicode_ci对中、英文来说没有实质的差别。utf8_unicode_ci的最主要的特色是支持扩展,即当把一个字母看作与其它字母组合相等时。例如,在德语和一些其它语言中‘ß'等于‘ss'。utf8_general_ci是一个遗留的比较规则,不支持扩展。它仅能够在字符之间进行逐个比较。这意味着utf8_general_ci比较规则进行的比较速度很快,但是与utf8_unicode_ci相比,比较正确性较差。


下面我们来实践下三种比较规则的异同:

# 创建表 指定列为不同的比较规则
mysql> create table utf8_test (
    -> col_general varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci,
    -> col_unicode varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci,
    -> col_bin varchar(20) CHARACTER SET utf8 COLLATE utf8_bin
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 # 插入数据 每行数据各个字段值一样
 mysql> select * from utf8_test;
+-------------+-------------+---------+
| col_general | col_unicode | col_bin |
+-------------+-------------+---------+
| MySQL       | MySQL       | MySQL   |
| mysql       | mysql       | mysql   |
| A           | A           | A       |
| a           | a           | a       |
| aA          | aA          | aA      |
+-------------+-------------+---------+
# 查询 验证utf8_bin比较规则区分大小写
mysql> select * from utf8_test where col_general='mysql';
+-------------+-------------+---------+
| col_general | col_unicode | col_bin |
+-------------+-------------+---------+
| MySQL       | MySQL       | MySQL   |
| mysql       | mysql       | mysql   |
+-------------+-------------+---------+
mysql> select * from utf8_test where col_unicode='MySQL';
+-------------+-------------+---------+
| col_general | col_unicode | col_bin |
+-------------+-------------+---------+
| MySQL       | MySQL       | MySQL   |
| mysql       | mysql       | mysql   |
+-------------+-------------+---------+
mysql> select * from utf8_test where col_bin='mysql';       
+-------------+-------------+---------+
| col_general | col_unicode | col_bin |
+-------------+-------------+---------+
| mysql       | mysql       | mysql   |
+-------------+-------------+---------+
# 排序 发现不同排序规则对顺序有影响
mysql> select * from utf8_test order by col_general;
+-------------+-------------+---------+
| col_general | col_unicode | col_bin |
+-------------+-------------+---------+
| A           | A           | A       |
| a           | a           | a       |
| aA          | aA          | aA      |
| MySQL       | MySQL       | MySQL   |
| mysql       | mysql       | mysql   |
+-------------+-------------+---------+
mysql> select * from utf8_test order by col_bin;
+-------------+-------------+---------+
| col_general | col_unicode | col_bin |
+-------------+-------------+---------+
| A           | A           | A       |
| MySQL       | MySQL       | MySQL   |
| a           | a           | a       |
| aA          | aA          | aA      |
| mysql       | mysql       | mysql   |
+-------------+-------------+---------+


3.关于比较规则的选择与建议


对于MySQL 5.7版本,一般情况下建议将字符集改为utf8,比较规则选择默认的utf8_general_ci。utf8_general_ci相对于utf8_unicode_ci来说校对速度快,但是如果你的应用有德语、法语或者俄语,建议使用utf8_unicode_ci。如果某个表或列字段要求区分大小写,可以单独指定该表或字段使用utf8_bin比较规则

最后以思维导图的方式总结下本文的主要内容:

image.png

image.png

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
3月前
|
存储 SQL 关系型数据库
字符集(Charset)
字符集(Charset)
93 3
|
3月前
|
数据处理
自定义字符集
自定义字符集
49 2
|
3月前
|
存储 自然语言处理 关系型数据库
字符集详解
字符集详解
50 0
|
SQL 存储 关系型数据库
字符集和比较规则
字符集和比较规则
369 0
|
关系型数据库 MySQL Shell
latin1字符集的数据转换为utf8字符集
latin1字符集的数据转换为utf8字符集
897 0
|
存储 JavaScript 程序员
【字符编码详解】ASCII、GB2312、GBK、UTF-8、UTF-16编码与Unicode字符集
【字符编码详解】ASCII、GB2312、GBK、UTF-8、UTF-16编码与Unicode字符集
649 0
C++ 过滤出字符串的中文(GBK,UTF-8)
C++ 过滤出字符串的中文(GBK,UTF-8)最近在处理游戏敏感词之类的东西,为了加强屏蔽处理,所以需要过滤掉字符串中的除汉字之外的是其他东西如数字,符号,英文字母等。 首先我查阅资料并写了个函数: 示例:返回输入字符串中汉字的个数: 复制代码std::string StrWithOutSymb...
4676 0
|
JavaScript 自然语言处理