任何计算机存储数据,都需要字符集,因为计算机存储的数据其实都是二进制编码,将一个个字符,映射到对应的二进制编码的这个映射就是字符编码(字符集)。这些字符如何排序呢?决定字符排序的规则就是排序规则。

查看内置字符集与比较规则

通过show charset;命令,可以查看所有的字符集。

以下仅展示了我们常用的字符集:

+----------+---------------------------------+---------------------+--------+

| Charset | Description | Default collation | Maxlen |

+----------+---------------------------------+---------------------+--------+

| latin1 | cp1252 West European | latin1_swedish_ci | 1 |

| ascii | US ASCII | ascii_general_ci | 1 |

| gb2312 | GB2312 Simplified Chinese | gb2312_chinese_ci | 2 |

| cp1250 | Windows Central European | cp1250_general_ci | 1 |

| gbk | GBK Simplified Chinese | gbk_chinese_ci | 2 |

| utf8 | UTF-8 Unicode | utf8_general_ci | 3 |

| utf8mb4 | UTF-8 Unicode | utf8mb4_general_ci | 4 |

| utf16 | UTF-16 Unicode | utf16_general_ci | 4 |

| utf32 | UTF-32 Unicode | utf32_general_ci | 4 |

+----------+---------------------------------+---------------------+--------+

ascii:共收录128个字符,包括空格、标点符号、数字、大小写字母和一些不可见字符。由于总共才128个字符,所以可以使用1个字节来进行编码

latin1:共收录256个字符,是在ASCII字符集的基础上又扩充了128个西欧常用字符(包括德法两国的字母),也可以使用1个字节来进行编码。

gb2312: 收录了汉字以及拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母。其中收录汉字6763个,其他文字符号682个,兼容ASCII字符集。这是一个变长字符集,如果该字符在ascii字符集中,则采用1字节编码,否则采用两字节。

gbk: GBK是在gb2312基础上扩容后的标准。收录了所有的中文字符。同样的,这是一个变长字符集,如果该字符在ascii字符集中,则采用1字节编码,否则采用两字节。

utf8和utf8mb4: 收录地球上能想到的所有字符,而且还在不断扩充。这种字符集兼容ASCII字符集,采用变长编码方式,编码一个字符需要使用1~4个字节。MySQL为了节省空间,其中的utf8是标准 UTF8 阉割后的,只有1~3字节编码的字符集,基本包含了所有常用的字符。如果还要使用 enoji 表情,那么需要使用utf8mb4,这个是完整的 UTF8 字符集。

utf16: 不同于utf8,utf16用两个字节或者四个字节编码字符,可以理解为utf8的不节省空间的一种形式

utf32: 固定用四个字节编码字符,可以理解为utf8的不节省空间的一种形式

通过查看information_schema.character_sets表,也可以看到所有的字符集:

mysql> select * from information_schema.character_sets where character_set_name = "utf8";

+--------------------+----------------------+---------------+--------+

| CHARACTER_SET_NAME | DEFAULT_COLLATE_NAME | DESCRIPTION | MAXLEN |

+--------------------+----------------------+---------------+--------+

| utf8 | utf8_general_ci | UTF-8 Unicode | 3 |

+--------------------+----------------------+---------------+--------+

1 row in set (0.06 sec)

通过show collation;命令,可以查看所有的字符集,我们这里来查看utf8mb4的排序规则:

mysql> show collation like 'utf8mb4%';

+------------------------+---------+-----+---------+----------+---------+

| Collation | Charset | Id | Default | Compiled | Sortlen |

+------------------------+---------+-----+---------+----------+---------+

| utf8mb4_general_ci | utf8mb4 | 45 | Yes | Yes | 1 |

| utf8mb4_bin | utf8mb4 | 46 | | Yes | 1 |

| utf8mb4_unicode_ci | utf8mb4 | 224 | | Yes | 8 |

| utf8mb4_icelandic_ci | utf8mb4 | 225 | | Yes | 8 |

| utf8mb4_latvian_ci | utf8mb4 | 226 | | Yes | 8 |

| utf8mb4_romanian_ci | utf8mb4 | 227 | | Yes | 8 |

| utf8mb4_slovenian_ci | utf8mb4 | 228 | | Yes | 8 |

| utf8mb4_polish_ci | utf8mb4 | 229 | | Yes | 8 |

| utf8mb4_estonian_ci | utf8mb4 | 230 | | Yes | 8 |

| utf8mb4_spanish_ci | utf8mb4 | 231 | | Yes | 8 |

| utf8mb4_swedish_ci | utf8mb4 | 232 | | Yes | 8 |

| utf8mb4_turkish_ci | utf8mb4 | 233 | | Yes | 8 |

| utf8mb4_czech_ci | utf8mb4 | 234 | | Yes | 8 |

| utf8mb4_danish_ci | utf8mb4 | 235 | | Yes | 8 |

| utf8mb4_lithuanian_ci | utf8mb4 | 236 | | Yes | 8 |

| utf8mb4_slovak_ci | utf8mb4 | 237 | | Yes | 8 |

| utf8mb4_spanish2_ci | utf8mb4 | 238 | | Yes | 8 |

| utf8mb4_roman_ci | utf8mb4 | 239 | | Yes | 8 |

| utf8mb4_persian_ci | utf8mb4 | 240 | | Yes | 8 |

| utf8mb4_esperanto_ci | utf8mb4 | 241 | | Yes | 8 |

| utf8mb4_hungarian_ci | utf8mb4 | 242 | | Yes | 8 |

| utf8mb4_sinhala_ci | utf8mb4 | 243 | | Yes | 8 |

| utf8mb4_german2_ci | utf8mb4 | 244 | | Yes | 8 |

| utf8mb4_croatian_ci | utf8mb4 | 245 | | Yes | 8 |

| utf8mb4_unicode_520_ci | utf8mb4 | 246 | | Yes | 8 |

| utf8mb4_vietnamese_ci | utf8mb4 | 247 | | Yes | 8 |

+------------------------+---------+-----+---------+----------+---------+

26 rows in set (0.13 sec)

同样的,通过查询information_schema.collations也可以:

mysql> select * from information_schema.collations where character_set_name = "utf8mb4";

+------------------------+--------------------+-----+------------+-------------+---------+

| COLLATION_NAME | CHARACTER_SET_NAME | ID | IS_DEFAULT | IS_COMPILED | SORTLEN |

+------------------------+--------------------+-----+------------+-------------+---------+

| utf8mb4_general_ci | utf8mb4 | 45 | Yes | Yes | 1 |

| utf8mb4_bin | utf8mb4 | 46 | | Yes | 1 |

| utf8mb4_unicode_ci | utf8mb4 | 224 | | Yes | 8 |

| utf8mb4_icelandic_ci | utf8mb4 | 225 | | Yes | 8 |

| utf8mb4_latvian_ci | utf8mb4 | 226 | | Yes | 8 |

| utf8mb4_romanian_ci | utf8mb4 | 227 | | Yes | 8 |

| utf8mb4_slovenian_ci | utf8mb4 | 228 | | Yes | 8 |

| utf8mb4_polish_ci | utf8mb4 | 229 | | Yes | 8 |

| utf8mb4_estonian_ci | utf8mb4 | 230 | | Yes | 8 |

| utf8mb4_spanish_ci | utf8mb4 | 231 | | Yes | 8 |

| utf8mb4_swedish_ci | utf8mb4 | 232 | | Yes | 8 |

| utf8mb4_turkish_ci | utf8mb4 | 233 | | Yes | 8 |

| utf8mb4_czech_ci | utf8mb4 | 234 | | Yes | 8 |

| utf8mb4_danish_ci | utf8mb4 | 235 | | Yes | 8 |

| utf8mb4_lithuanian_ci | utf8mb4 | 236 | | Yes | 8 |

| utf8mb4_slovak_ci | utf8mb4 | 237 | | Yes | 8 |

| utf8mb4_spanish2_ci | utf8mb4 | 238 | | Yes | 8 |

| utf8mb4_roman_ci | utf8mb4 | 239 | | Yes | 8 |

| utf8mb4_persian_ci | utf8mb4 | 240 | | Yes | 8 |

| utf8mb4_esperanto_ci | utf8mb4 | 241 | | Yes | 8 |

| utf8mb4_hungarian_ci | utf8mb4 | 242 | | Yes | 8 |

| utf8mb4_sinhala_ci | utf8mb4 | 243 | | Yes | 8 |

| utf8mb4_german2_ci | utf8mb4 | 244 | | Yes | 8 |

| utf8mb4_croatian_ci | utf8mb4 | 245 | | Yes | 8 |

| utf8mb4_unicode_520_ci | utf8mb4 | 246 | | Yes | 8 |

| utf8mb4_vietnamese_ci | utf8mb4 | 247 | | Yes | 8 |

+------------------------+--------------------+-----+------------+-------------+---------+

26 rows in set (0.11 sec)

每个字符集都有一个默认的排序规则:IS_DEFAULT 为 Yes。

比较规则名称以与其关联的字符集的名称开头,可以用通过这个开头查询所有的字符集,也可以查询information_schema.collations精确指定字符集

字符集后面跟着的是语言编码,因为utf8mb4包含了所有字符,不同国家的文字语言排序肯定不一样。

最后末尾的ci代表case insensitive,大小写不敏感,所有可能的后缀如下所示:

ai: accent insensitive 不区分重音

as: accent sensitive 区分重音

ci: case insensitive 不区分大小写

cs: case sensitive 区分大小写

bin: binary 以二进制方式比较

应用字符集与比较规则

字符集与比较规则配置有四个级别:

MySQL实例级别

库级别

表级别

字段级别

指定的级别粒度越小,则以粒度越小的字符集还有比较规则优先。例如指定MySQL实例级别字符集是utf8mb4,指定某个表字符集是latin1,那么这个表的所有字段如果不指定的话,编码就是latin1

由于字符集和比较规则是互相有联系的,如果我们只修改了字符集,比较规则也会跟着变化,如果只修改了比较规则,字符集也会跟着变化,具体规则如下:

只修改字符集,则比较规则将变为修改后的字符集默认的比较规则。

只修改比较规则,则字符集将变为修改后的比较规则对应的字符集。

实例级别

通过两个系统变量来指定实例级别的字符集与排序规则。

配置文件:

[server]

character_set_server=utf8mb4

collation_server=utf8mb4_general_ci

启动之后,可以查看并修改这两个变量。

mysql> show variables like 'character_set_server';

+----------------------+---------+

| Variable_name | Value |

+----------------------+---------+

| character_set_server | utf8mb4 |

+----------------------+---------+

1 row in set (0.06 sec)

mysql> show variables like 'collation_server';

+------------------+--------------------+

| Variable_name | Value |

+------------------+--------------------+

| collation_server | utf8mb4_general_ci |

+------------------+--------------------+

1 row in set (0.05 sec)

mysql> set character_set_server = 'utf8mb4';

Query OK, 0 rows affected (0.00 sec)

mysql> set collation_server = 'utf8mb4_general_ci';

Query OK, 0 rows affected (0.00 sec)

库级别

创建数据库的时候,可以指定字符集还有排序规则。

mysql> create database test_db character set utf8mb4 collate utf8mb4_general_ci;

Query OK, 1 row affected (0.01 sec)

不指定的话,就用实例级别的字符集还有排序规则。

查看当前数据库的字符集还有排序规则则是通过use命令指定数据库之后,查看character_set_database变量以及collation_database来实现:

mysql> show variables like 'character_set_database';

+------------------------+---------+

| Variable_name | Value |

+------------------------+---------+

| character_set_database | utf8mb4 |

+------------------------+---------+

1 row in set (0.07 sec)

mysql> show variables like 'collation_database';

+--------------------+--------------------+

| Variable_name | Value |

+--------------------+--------------------+

| collation_database | utf8mb4_general_ci |

+--------------------+--------------------+

1 row in set (0.09 sec)

就算设置这两个变量,也是无效的:

mysql> set character_set_database = 'utf8';

Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'character_set_database';

+------------------------+---------+

| Variable_name | Value |

+------------------------+---------+

| character_set_database | utf8mb4 |

+------------------------+---------+

1 row in set (0.09 sec)

修改数据库的字符集还有排序规则的方式:

mysql> alter database test_db character set = 'utf8';

Query OK, 1 row affected (0.01 sec)

mysql> show variables like 'character_set_database';

+------------------------+-------+

| Variable_name | Value |

+------------------------+-------+

| character_set_database | utf8 |

+------------------------+-------+

1 row in set (0.08 sec)

这个更新只会对新建的表如果没指定字符集和排序规则的生效,并不会更新老表的字符集还有排序规则。

表级别

可以在创建时指定字符集合排序规则,不指定的话,用数据库的字符集还有排序规则,也可以修改字符集和排序规则。

mysql> create table test (name varchar(32)) character set utf8mb4 collate utf8mb4_bin;

Query OK, 0 rows affected (0.04 sec)

mysql> show create table test;

+-------+---------------------------------------------------------------------------------------------------------------------------------------+

| Table | Create Table |

+-------+---------------------------------------------------------------------------------------------------------------------------------------+

| test | CREATE TABLE `test` (

`name` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin |

+-------+---------------------------------------------------------------------------------------------------------------------------------------+

1 row in set (0.09 sec)

mysql> alter table test character set = 'utf8';

Query OK, 0 rows affected (0.02 sec)

Records: 0 Duplicates: 0 Warnings: 0

mysql> show create table test;

+-------+--------------------------------------------------------------------------------------------------------------------------------------+

| Table | Create Table |

+-------+--------------------------------------------------------------------------------------------------------------------------------------+

| test | CREATE TABLE `test` (

`name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

+-------+--------------------------------------------------------------------------------------------------------------------------------------+

1 row in set (0.06 sec)

可以看出,仅仅是表的字符集还有排序规则变了,对于已有字段,并没有改变编码和排序规则。

列级别

可以在创建表的时候,指定不同的列有不同的字符集和排序规则,也可以修改列的字符集和排序规则:

mysql> create table test (name varchar(32) character set utf8 collate utf8_bin) character set utf8mb4 collate utf8mb4_bin;

Query OK, 0 rows affected (0.03 sec)

mysql> show create table test;

+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------+

| Table | Create Table |

+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------+

| test | CREATE TABLE `test` (

`name` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin |

+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------+

1 row in set (0.09 sec)

mysql> alter table test modify column name varchar(32) COLLATE latin1_bin;

Query OK, 0 rows affected (0.09 sec)

Records: 0 Duplicates: 0 Warnings: 0

mysql> show create table test;

+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+

| Table | Create Table |

+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+

| test | CREATE TABLE `test` (

`name` varchar(32) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin |

+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+

1 row in set (0.09 sec)

MySQL客户端字符编码问题

有时候,我们会遇到字符编码不一致导致的程序问题。例如我们的 Java 程序,使用 jdbc 链接。读取的数据,打印出来是乱码。或者是,MySQL 无法识别我们客户端发来的命令。这涉及到字符编码问题。我们需要保持 Java 程序的字符编码与 JDBC 链接指定的字符编码一致,这样才不会有乱码的问题。

指定 Java 程序编码:通过启动参数:-Dfile.encoding=UTF-8 设置默认的字符编码(java.nio.charset.Charset.defaultCharset();)是utf-8(对应 MySQL 的utf8还有utf8mb4)。

指定 JDBC 链接编码:

jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8

mysql客户端命令行指定字符集

mysql -h 127.0.0.1 -P 3306 -u root --default-character-set=utf8mb4 -p

之后查看有关编码的环境变量,都是和设置的这个字符集一样。

mysql> SHOW VARIABLES LIKE 'character_set_client';

+----------------------+---------+

| Variable_name | Value |

+----------------------+---------+

| character_set_client | utf8mb4 |

+----------------------+---------+

1 row in set, 1 warning (0.00 sec)

mysql> SHOW VARIABLES LIKE 'character_set_connection';

+--------------------------+---------+

| Variable_name | Value |

+--------------------------+---------+

| character_set_connection | utf8mb4 |

+--------------------------+---------+

1 row in set, 1 warning (0.00 sec)

mysql> SHOW VARIABLES LIKE 'character_set_results';

+-----------------------+---------+

| Variable_name | Value |

+-----------------------+---------+

| character_set_results | utf8mb4 |

+-----------------------+---------+

1 row in set, 1 warning (0.00 sec)

其中:

character_set_client: 服务器解码请求时使用的字符集

character_set_connection:服务器处理请求时将字符集转换成这个字符集处理。操作具体列时,在转换为具体列的编码。

character_set_results:服务器向客户端返回数据时使用的字符集

MySQL 设计这三个编码的时候,出于以下考虑:

一个 MySQL,可能有多种不同语言和操作系统或者国家的客户端,所以通过设置character_set_client还有character_set_results进行兼容。

由于操作具体列数据的时候需要编码转换,如果character_set_connection和字段一致的话,就不用转换了,所以设置character_set_connection可以让 MySQL 用一种编码理解命令统一处理,同时设置character_set_connection为最常用的可以减少转换。

一般情况下,保持这三个一致就好。我们就设置好连接使用的字符集就行了。

mysql字符集排序规则_MySQL原理 - 字符集与排序规则相关推荐

  1. mysql 汉字一排序规则_MySQL 的字符集与排序规则

    今天突然被同事问到,MySql 里的 uft8 与 utf8mb4 究竟有什么区别,当时我也是一脸问号,因此特地去了解了一下. 字符集 uft8 与 utf8mb4 其实指的是 MySQL 中的字符集 ...

  2. mysql8.0字符集排序规则_MySQL 的字符集与排序规则

    今天突然被同事问到,MySql 里的 uft8 与 utf8mb4 究竟有什么区别,当时我也是一脸问号,因此特地去了解了一下. 字符集 uft8 与 utf8mb4 其实指的是 MySQL 中的字符集 ...

  3. mysql 中文字符排序规则_mysql中字符集和排序规则说明

    数据库需要适应各种语言和字符就需要支持不同的字符集(Character Set),每种字符集也有各自的排序规则(Collation). 一.字符集 字符集,即用于定义字符在数据库中的编码的集合. 常见 ...

  4. MySQL多字段排序乱_Mysql ORDER BY 中文排序错乱问题

    1. 在MySQL中,我们经常会对一个字段进行排序查询,但进行中文排序和查找的时候,对汉字的排序和查找结果往往都是错误的. 这种情况在MySQL的很多版本中都存在. 如果这个问题不解决,那么MySQL ...

  5. mysql 查看校对集_mysql 查看字符集和校对规则

    MySQL 服务器可以支持多种字符集,在同一台服务器.同一个数据库.甚至同一个表的不同字段都可以指定使用不同的字符集,相比Oracle 等其他数据库管理系统,在同一个 数据库只能使用相同的字符集,My ...

  6. mysql按范围查找_Mysql实现按距离排序、范围查找

    现在几乎所有的O2O应用中都会存在"按范围搜素.离我最近.显示距离"等等基于位置的交互,那这样的功能是怎么实现的呢?本文提供的实现方式,适用于所有数据库. 实现 实现过程主要分为四 ...

  7. mysql字符集设置方案_MySQL的字符集配置

    utf8的锅: 场景 : 之前在给客户做微商城时,需要保存微信的授权信息,此时就有一个nickname字段,在设计数据表时,潜意识的将表的存储格式设置为utf8,生产上线一段时间后偶尔出现保存异常.经 ...

  8. mysql varchar 长度限制_MySQL数据库varchar的限制规则说明

    MySQL数据库中varchar最大长度是多少?其实这不是一个固定的数字,varchar的长度是有限制规则的.本文我们就来介绍一下MySQL数据库中varchar的限制规则,并以一个实际的例子对限制规 ...

  9. mysql 关键字搜索 排名_mysql 的 查找 与 排序

    mysql 的 查找 : SELECT name,age FROM mytable; # 在mytable 中所有的name,age 数据 SELECT name,age FROM mytable W ...

最新文章

  1. 启动Tomcat一闪而过解决
  2. Druid 连接池 JDBCUtils 工具类的使用
  3. JAVA基础知识系列---进程、线程安全
  4. 什么时候会用到拷贝构造函数?
  5. android和emui的版本对应,同为Android 操作系统的小米MIUI和华为EMUI, 谁更优秀?
  6. python笔记3:依次输入3个数排序打印(升序)
  7. Entity Framework 学习高级篇2—改善EF代码的方法(下)(转)
  8. 20200714每日一句
  9. 科学绘图与数据分析软件SigmaPlot
  10. 前端导出 xlsx文件
  11. 【菜鸟练习】用Java实现高尔顿瓶
  12. 【Latex学习】在IEEEtran模板中使用algorithm环境
  13. 基于jsp+mysql+Spring+SpringMVC+mybatis的大学生缴费系统-计算机毕业设计
  14. 电脑上打开chm文件时系统提示:不能打开文件:mk:@MSITStore:(文件路径)
  15. 2023高薪前端面试题(一、前端基础——css)
  16. 大阪第83天——可怕的日本(转贴)
  17. Terraform 系列-什么是 IaC?
  18. 快速解读Nor Flash Datasheet
  19. puzzle(004.1)日历拼图
  20. 国外android内存清理工具,小内存手机有救了,这款清理神器,瞬间多出几个G的内存...

热门文章

  1. 数字图像处理:四连通域与八连通域
  2. 利用tensorflow构建AlexNet模型,实现小数量级的猫狗分类(只有train)
  3. 安卓逆向_22( 二 ) --- Xposed 学习记录
  4. Java8 Stream详解~Stream 创建
  5. SessionHelper
  6. java第一阶段知识_第一阶段 Java语言(下)
  7. 滤波器开发之一:基于算数平均的平滑滤波器
  8. CoreAnimation编程指南(十)KVC
  9. linux shell 0403-011,shell脚本出现 test:0403-004 Specify a paramater with this command
  10. python while循环if_20170403Python控制流if、while、for语句学习