排序规则
一、什么是排序规则
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
查看实现接口的方法compareTo,其实该方法就是实现一下当两个Integer类型比较时,返回值及表达怎么比较。
而比较器Comparator是描述两个泛型类的实例怎么比较。
那么实现接口Comparable代表着类的实例本身就可以比较,比较器Comparator代表着两个实例使用比较器来比较。
方法compareTo的理解
compareTo就是一个比较的方式,比如class是人,那么身高是一种比较方式,体重也是,财产也是,都可以比较。只是实现compareTo的方式不同,比较的结果就不同。
数据库实现
数据库搞出来个排序规则,其实就是类似Java的String类的compareTo方法怎么实现的,即是排序规则
public final class String
implements java.io.Serializable, Comparable, 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/
本文版权归作者和云海天共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341