zoukankan      html  css  js  c++  java
  • 排序规则

    一、什么是排序规则

    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; 
    
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    字符串转换日期,日期转换字符串
    List中的Map
    一维数组
    流程控制的基本语法和应用
    《代码阅读方法与实践》读书笔记1
    专业实训题目需求分析
    2015年秋季个人阅读计划
    《人件集 人性化的软件开发》阅读笔记03
    《人件集 人性化的软件开发》阅读笔记02
    《人件集 人性化的软件开发》阅读笔记01
  • 原文地址:https://www.cnblogs.com/klarck/p/15784148.html
Copyright © 2011-2022 走看看