0

0

MySQL中存储的数据查询的时候怎么区分大小写

王林

王林

发布时间:2023-05-31 16:26:31

|

5732人浏览过

|

来源于亿速云

转载

    场景描述

    今天在将 hive 表同步到 mysql 之后,其中有一列是唯一列,但是在 mysql 中查询的时候 countdistinct count 查询出来的数值是不一样的,这么来看的话是有重复的数据(按理说不应该的,因为在 hive 中,这两个数值是一样的),那么将重复的数据查出来看了一下,发现是大小写的问题,然后查了一下,发现 mysql 数据库默认情况下,字符串字段的所有相关运算是大小写"不敏感"的。

    这一点与其它流行的数据库都不相同。

    解决办法

    1. 查询时指定大小写敏感

    MySQL 允许在查询的时候指定以大小写敏感方式,需要使用关键字 BINARY,查询如下:

    SELECT * FROM student WHERE BINARY name = 'ZhangSan';
    --或者
    SELECT * FROM student WHERE name = BINARY 'ZhangSan';

    很多时候当发现 MySQL 数据库存在上述问题时,系统已经运行了一段时间,如果采用方法二或方法三的代价可能会很大。

    使用此方法最大的好处便是可以快速实现功能。

    但是这个方法也存在很大的限制:如此可能因为无法使用索引导致查询性能下降。

    原因很好理解,因为此时针对查询字段的索引也是按照大小写不敏感方式建立的。

    除非数据量不大,或者在你的应用中不在乎这点性能上的损失,那么只能选择方法二或方法三了。

    2. 定义表结构时指定字段大小写敏感

    在创建表时指定具体的字段大小写敏感,示例如下:

    CREATE TABLE student (
      ...
      name VARCHAR(64) BINARY NOT NULL,
      ...
    
    )

    关键字 BINARY 指定 name 字段大小写敏感。

    如此在查询时就算不使用 BINARY 关键字,查询语句也是大小写敏感的。

    在此基础上创建的 name 相关的索引也是大小写敏感的,也就能够使用索引来提高性能。

    MySQL 允许在大多数字符串类型上使用 BINARY 关键字,用于指明所有针对该字段的运算是大小写敏感的,更多信息请参见 MySQL 官方文档。

    这种方法使得设计者可以精确地控制每个字段是否大小写敏感。在许多系统的设计中,通常期望所有字段都是大小写敏感的,甚至大多数字段都是如此。MySQL 也提供了解决方案,这就要用到方法三。

    3. 修改排序规则(COLLATE)

    在 MySQL 中执行 show create table 指令,可以看到一张表的建表语句,example 如下:

    CREATE TABLE `table1` (
        `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
        `field1` text COLLATE utf8_general_ci NOT NULL COMMENT '字段1',
        `field2` varchar(128) COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '字段2',
        PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8_unicode_ci;

    大部分字段我们都能看懂,但是今天要看的是 COLLATE 关键字。这个值后面对应的 utf8_general_ci 是什么意思呢?下面我们就来了解一下。

    COLLATE是用来做什么的?

    使用 Navicat 开发的可能会比较眼熟,因为其中的选项中已经给出了答案:

    MySQL中存储的数据查询的时候怎么区分大小写

    所谓 utf8_general_ci,其实是用来排序的规则。对于 MySQL 中那些字符类型的列,如VARCHAR,CHAR,TEXT 类型的列,都需要有一个 COLLATE 类型来告知 MySQL 如何对该列进行排序和比较。简而言之,COLLATE 会影响到 ORDER BY 语句的顺序,会影响到 WHERE 条件中大于小于号筛选出来的结果,会影响 DISTINCTGROUP BYHAVING 语句的查询结果。另外,MySQL 建索引的时候,如果索引列是字符类型,也会影响索引创建,只不过这种影响我们感知不到。总之,凡是涉及到字符类型比较或排序的地方,都会和 COLLATE 有关

    涉及字符串的各种运算其核心必然涉及到采用何种字符排序规则(COLLATE,也有翻译为"核对")。MySQL的字符串运算是否区分大小写,本质上取决于它所使用的COLLATE排序规则。

    utf8_general_ci 是一个具体的 COLLATE 取值。每个具体的 COLLATE 都对应唯一的字符集,可以看出该 COLLATE 对应字符集为 utf8。而与大小写敏感问题相关的是其后缀 _ci,MySQL 官方文档对其的解释是 Case Ignore 的缩写,即大小写不敏感。由于 MySQL 将 utf8_general_ci 指定作为字符集 utf8 的默认 COLLATE,这也就导致文章开头所说的现象。与此同时,MySQL 也提供了其它的 COLLATE 取值选项,utf8_bin 就是大小写敏感的。事实上所有大小写敏感的 COLLATE 都以 _bin_cs 为后缀,前者是 Binary 的缩写,后者是 Case Sensitive 的缩写。

    各种COLLATE的区别

    COLLATE 通常是和数据编码(CHARSET)相关的,一般来说每种 CHARSET 都有多种它所支持的 COLLATE,并且每种 CHARSET 都指定一种 COLLATE 为默认值。例如 Latin1 编码的默认 COLLATE 为 latin1_swedish_ci,GBK 编码的默认 COLLATE 为 gbk_chinese_ci,utf8mb4 编码的默认值为 utf8mb4_general_ci

    这里顺便讲个题外话,MySQL 中有 utf8 和 utf8mb4 两种编码,在 MySQL 中请大家忘记 utf8,永远使用 utf8mb4。这是 MySQL 的一个遗留问题,MySQL 中的 utf8 最多只能支持 3bytes 长度的字符编码,对于一些需要占据 4bytes 的文字,MySQL 的 utf8 就不支持了,要使用 utf8mb4 才行。

    聚蜂消防BeesFPD
    聚蜂消防BeesFPD

    关注消防领域的智慧云平台

    下载

    很多 COLLATE 都带有 _ci 字样,这是 Case Insensitive 的缩写,即大小写无关,也就是说 "A""a" 在排序和比较的时候是一视同仁的。selection * from table1 where field1="a" 同样可以把 field1 为 "A" 的值选出来。与此同时,对于那些 _cs 后缀的 COLLATE,则是 Case Sensitive,即大小写敏感的。

    在 MySQL 中使用 show collation 指令可以查看到 MySQL 所支持的所有 COLLATE。以 utf8mb4 为例,该编码所支持的所有 COLLATE 如下图所示。

    MySQL中存储的数据查询的时候怎么区分大小写

    图中我们能看到很多国家的语言自己的排序规则。在国内比较常用的是 utf8mb4_general_ci(默认)、utf8mb4_unicode_ciutf8mb4_bin 这三个。我们来探究一下这三个的区别:

    UTF8mb4_bin的比较方式是将所有字符作为二进制串,然后从最高位到最低位进行比较。所以很显然它是区分大小写的。

    而 utf8mb4_unicode_ci 和 utf8mb4_general_ci 对于中文和英文来说,其实是没有任何区别的。对于我们开发的国内使用的系统来说,随便选哪个都行。只是对于某些西方国家的字母来说,utf8mb4_unicode_ci 会比 utf8mb4_general_ci 更符合他们的语言习惯一些,general 是 MySQL 一个比较老的标准了。例如,德语字母 "ß",在 utf8mb4_unicode_ci 中是等价于 "ss" 两个字母的(这是符合德国人习惯的做法),而在 utf8mb4_general_ci 中,它却和字母 "s" 等价。不过,这两种编码的那些微小的区别,对于正常的开发来说,很难感知到。本身我们也很少直接用文字字段去排序,退一步说,即使这个字母排错了一两个,真的能给系统带来灾难性后果么?从网上找的各种帖子讨论来说,更多人推荐使用 utf8mb4_unicode_ci,但是对于使用了默认值的系统,也并没有非常排斥,并不认为有什么大问题。结论:推荐使用 utf8mb4_unicode_ci,对于已经用了 utf8mb4_general_ci 的系统,也没有必要花时间改造。

    另外需要注意的一点是,从 MySQL 8.0 开始,MySQL 默认的 CHARSET 已经不再是 Latin1 了,改为了 utf8mb4 (参考链接),并且默认的 COLLATE 也改为了 utf8mb4_0900_ai_ci。utf8mb4_0900_ai_ci 大体上就是 unicode 的进一步细分,0900 指代 unicode 比较算法的编号( Unicode Collation Algorithm version),ai 表示 accent insensitive(发音无关),例如 e,è, é, ê 和 ë 是一视同仁的。相关参考链接1,相关参考链接2

    COLLATE 设置级别及其优先级

    MySQL 数据库允许在表 和 列 三个级别上指定 Collation。当同时指定时,优先关系是:列 > 表 > 库。

    设置 COLLATE 可以在实例级别库级别表级别列级别、以及 SQL 指定。当同时指定时,优先关系是:SQL 指定 > 列 > 表 > 库 > 实例级别。

    • 实例级别的 COLLATE 设置就是 MySQL 配置文件或启动指令中的 collation_connection 系统变量。

    • 库级别设置 COLLATE 的语句如下:

    CREATE DATABASE  DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

    如果库级别没有设置 CHARSET 和 COLLATE,则库级别默认的 CHARSET 和 COLLATE 使用实例级别的设置。在 MySQL 8.0 以下版本中,你如果什么都不修改,默认的 CHARSET 是 Latin1,默认的 COLLATE 是 latin1_swedish_ci。从 MySQL 8.0 开始,默认的 CHARSET 已经改为了 utf8mb4,默认的 COLLATE 改为了 utf8mb4_0900_ai_ci。

    • 表级别的 COLLATE 设置,则是在 CREATE TABLE 的时候加上相关设置语句,例如:

    CREATE TABLE table_name (
    ……
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT = '表注释';

    如果表级别没有设置 CHARSET 和 COLLATE,则表级别会继承库级别的 CHARSET 与 COLLATE。

    • 列级别的设置,则在 CREATE TABLE 中声明列的时候指定,例如

    CREATE TABLE (
    `field1` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '字段1',
    ……
    ) ……

    如果列级别没有设置 CHARSET 和 COLATE,则列级别会继承表级别的 CHARSET 与 COLLATE。

    • 最后,你也可以在写 SQL 查询的时候显示声明 COLLATE 来覆盖任何库表列的 COLLATE 设置,不太常用,了解即可:

    SELECT DISTINCT field1 COLLATE utf8mb4_general_ci FROM table1;
    
    SELECT field1, field2 FROM table1 ORDER BY field1 COLLATE utf8mb4_unicode_ci;

    如果全都显示设置了,那么优先级顺序是 SQL 语句 > 列级别设置 > 表级别设置 > 库级别设置 > 实例级别设置。

    也就是说列上所指定的 COLLATE可以覆盖表上指定的 COLLATE,表上指定的 COLLATE 可以覆盖库级别的 COLLATE。如果没有指定,则继承下一级的设置。

    即列上面没有指定 COLLATE,则该列的 COLLATE 和表上设置的一样。

    相关专题

    更多
    公务员递补名单公布时间 公务员递补要求
    公务员递补名单公布时间 公务员递补要求

    公务员递补名单公布时间不固定,通常在面试前,由招录单位(如国家知识产权局、海关等)发布,依据是原入围考生放弃资格,会按笔试成绩从高到低递补,递补考生需按公告要求限时确认并提交材料,及时参加面试/体检等后续环节。要求核心是按招录单位公告及时响应、提交材料(确认书、资格复审材料)并准时参加面试。

    0

    2026.01.15

    公务员调剂条件 2026调剂公告时间
    公务员调剂条件 2026调剂公告时间

    (一)符合拟调剂职位所要求的资格条件。 (二)公共科目笔试成绩同时达到拟调剂职位和原报考职位的合格分数线,且考试类别相同。 拟调剂职位设置了专业科目笔试条件的,专业科目笔试成绩还须同时达到合格分数线,且考试类别相同。 (三)未进入原报考职位面试人员名单。

    4

    2026.01.15

    国考成绩查询入口 国考分数公布时间2026
    国考成绩查询入口 国考分数公布时间2026

    笔试成绩查询入口已开通,考生可登录国家公务员局中央机关及其直属机构2026年度考试录用公务员专题网站http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/examResult/written_result.html,查询笔试成绩和合格分数线,点击“笔试成绩查询”按钮,凭借身份证及准考证进行查询。

    2

    2026.01.15

    Java 桌面应用开发(JavaFX 实战)
    Java 桌面应用开发(JavaFX 实战)

    本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

    63

    2026.01.14

    php与html混编教程大全
    php与html混编教程大全

    本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

    32

    2026.01.13

    PHP 高性能
    PHP 高性能

    本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

    73

    2026.01.13

    MySQL数据库报错常见问题及解决方法大全
    MySQL数据库报错常见问题及解决方法大全

    本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

    20

    2026.01.13

    PHP 文件上传
    PHP 文件上传

    本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

    25

    2026.01.13

    PHP缓存策略教程大全
    PHP缓存策略教程大全

    本专题整合了PHP缓存相关教程,阅读专题下面的文章了解更多详细内容。

    7

    2026.01.13

    热门下载

    更多
    网站特效
    /
    网站源码
    /
    网站素材
    /
    前端模板

    精品课程

    更多
    相关推荐
    /
    热门推荐
    /
    最新课程
    MySQL 教程
    MySQL 教程

    共48课时 | 1.7万人学习

    MySQL 初学入门(mosh老师)
    MySQL 初学入门(mosh老师)

    共3课时 | 0.3万人学习

    简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信

    共1课时 | 791人学习

    关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
    php中文网:公益在线php培训,帮助PHP学习者快速成长!
    关注服务号 技术交流群
    PHP中文网订阅号
    每天精选资源文章推送

    Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号