百木园-与人分享,
就是让自己快乐。

排序规则

一、什么是排序规则

mysql官网的说法

The collation is a set of rules (only one rule in this case): “compare the encodings.” We call this simplest of all possible collations a binary collation.
排序规则是一套规则(在这种情况下,只有一个规则):“比较编码。”我们把这种简单的所有可能的归类的二进制 排序规则。
https://dev.mysql.com/doc/refman/8.0/en/charset-general.html

《高性能mysql》中的说法

《mysql是怎样运行的》中的说法

没找到电子版,只能拍照了

二、我的理解

排序规则是针对字符串而言的,当有两个字符串想要比较大小时,排序规则才有意义。

类型对数据比较的影响

非字符串类型

要么天然就有排序规则(如:int,值的大小比较,就是他的排序规则;日期,日期及时间的早晚就是排序规则)
要么天然就没有办法比较(如二进制存储的图片,虽然二进制本身可以比较,但比较的结果对于图片而言没有意义)

字符串类型

也有一种天然的比较方式,类似于Java中字符串String类型的compareTo方法,即使用字符串中的字符的对应编码的大小来比较。

特殊情况

然而,有一些字符串比较的需求就很有意思了
如中文’一二三四’对应的unicode字符编码是19968,20108,19977,22235,【这里使用unicode编码仅仅是用来举例,就算是其他编码也可能会出现类似情况】
使用Java代码计算编码

System.out.println((int)\'一\');
System.out.println((int)\'二\');
System.out.println((int)\'三\');
System.out.println((int)\'四\');

中文

比较
如果想比较’一百二十’与’一百三十’两个中文字符串

结果
显而易见,正常人期待的结果都是:’一百二十’小于’一百三十’。
然而以字符串对比来说,
先比较第一个字符’一’,相等;
再比较第二个字符’百’,也相等;
再比较第三个字符’二’与’三’,结果二比三大;
那么’一百二十’大于’一百三十’,
这个结果是反人类的,至少是反中国人的。
可以使用Java代码计算比较结果

System.out.println(\"一百三十\".compareTo(\"一百二十\"));

执行结果是-131,
结果是负的,说明”一百三十”小于”一百二十”,这确实不是正常人期待的结果。

英语特殊情况举例

同理对比Apple和apple,正常人期待的结果是相等
使用Java代码

System.out.println(\"Apple\".compareTo(\"apple\"));

执行结果是-32
负的,说明”Apple”小于”apple”,这也不是正常人期待的结果。

他拉丁语系的特殊情况举例

希望大小写不敏感,雷同英语

日语的特殊情况

期待:平假名和片假名被视为相等,下面的链接是日语的情况。
https://www.it1352.com/1898650.html

三、实现方式

类似的在一个语言中,期望在文本比较时,针对某些大小写或者简繁体对应字符相等,我们需要专门制作一种规则
这种规则在文本比较时使用,就叫做校对规则,而大部分情况只有排序时才会比较字符的大小,所以也叫排序规则。

Java实现

当Java想排序时,要么你的泛型实现了接口Comparable,要么你实现一个Comparator接口的类。
类似的整数类型Integer天然的实现了接口Comparable,下面是类Integer的定义

public final class Integer extends Number implements Comparable<Integer>

查看实现接口的方法compareTo,其实该方法就是实现一下当两个Integer类型比较时,返回值及表达怎么比较。
而比较器Comparator是描述两个泛型类的实例怎么比较。
那么实现接口Comparable代表着类的实例本身就可以比较,比较器Comparator代表着两个实例使用比较器来比较。

方法compareTo的理解

compareTo就是一个比较的方式,比如class是人,那么身高是一种比较方式,体重也是,财产也是,都可以比较。只是实现compareTo的方式不同,比较的结果就不同。

数据库实现

数据库搞出来个排序规则,其实就是类似Java的String类的compareTo方法怎么实现的,即是排序规则

public final class String
implements java.io.Serializable, Comparable<String>, CharSequence

即,建表时字符串列必须指定个排序规则,否则没有办法order by 该列,如果不指定即默认逻辑上级的排序规则。
上下级关系是:库,表,列
所以建库时一定要指定排序规则,不能只指定编码。

四、用途

索引使用必须在排序规则相同的字段间
查看博客中:2020-08-02的文章《一次MySQL索引失效引发的思考》
https://www.cnblogs.com/klarck/p/13418706.html
排序规则不同索引会失效

select table_name,column_name,character_set_name,collation_name
from information_schema.columns where table_schema = \'库名\' and data_type = \'varchar\'

字符串本身带排序规则

测试代码如下

CREATE TABLE test1 (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(45) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci ;

SET @app_name = \"test-text\" COLLATE utf8mb4_unicode_ci ;
SELECT * FROM test1 WHERE name = @app_name

报错信息 Illegal mix of collations (utf8mb4_general_ci,IMPLICIT) and (utf8mb4_unicode_ci,IMPLICIT) for operation ‘=’
google翻译:操作’=’的排序规则(utf8mb4_general_ci,IMPLICIT)和(utf8mb4_unicode_ci,IMPLICIT)的非法混合
可见,变量@app_name携带了排序规则utf8mb4_unicode_ci。

mysql字符串可以比较大小

那么max可以计算字符串字段
例如以之前的表为例

SELECT MAX(name) FROM test1;

来源:https://www.cnblogs.com/klarck/p/15784148.html
图文来源于网络,如有侵权请联系删除。

未经允许不得转载:百木园 » 排序规则

相关推荐

  • 暂无文章