MySQL查询居然不区分大小写
- 事故现场
- 真实原因
- BINARY 关键字
- 总结
- MySQL 为什么要这样设计呢?
- 解决方案
- 修改排序规则
- binary
!!!!!懵逼了,
MySQL
查询居然不区分大小写,第一次听到这么陌生的概念 😵😵😵
事故现场
查询用户姓名是大写
Y
开头的用户。理所当然的写出SQL
。
select * from t_user where real_name like 'Y%';
一看结果我懵逼了,这个时候我还不太相信 😵,我就又把大写
y
改成了小写。
select * from t_user where real_name like 'y%'
再一看结果我彻底懵了,(这个时候脑子已经闪现过无数过画面,之前好像完全没有注意到这个问题)
这个时候我还感觉是我自己的 SQL
写的有问题(没有想过 MySQL 天生就这样),我又把 like
换成了 =
select * from t_user where real_name = 'Yuen Wai Man'
看到结果的那一刻陷入了沉思
这个时候又想到一个问题,是不是配置有问题(当前环境 lower_case_table_names=2
,但一想这个只跟表有关系没字段没半毛钱关系。),我还去其他环境的数据库中去验证了一下都是一样的结果。越发觉得奇怪了。
真实原因
表和字段的排序规则!!!!!
在 innodb
引擎下,字符集为:utf8mbf
下默认排序规则是 utf8mb4_0900_ai_ci
,而 utf8
默认的排序规则是 utf8_general_ci
。这里的 ci
代表不区分大小写(case-insensitive
)。
区分大小写的排序规则 **utf8mbf:utf8mb4_bin**
, **utf8:utf8_bin**
。
破案了 👏👏👏,修改排序规则为 utf8mb4_bin
。再查询。
🤢🤢 吐了,为什么还不行??
观察 varchar
类型的字段后发现。字段的排序规则没改过了。
这里修改后。一切正常了。(这里因为是建表的时候没有修改排序规则导致的,所以在建表后的字段需要单独修改)
BINARY 关键字
按字面量进行比较,是区分大小写的。将表的配置与字段的配置还原默认。
select * from t_user where BINARY real_name = 'Yuen Wai Man'
可以区分大小写了。
总结
MySQL 为什么要这样设计呢?
- 提高灵活性:用户在输入数据时可能不会注意大小写,不区分大小写的查询可以更好地匹配用户的输入,提供更灵活的搜索体验。
- 增强用户体验:对于用户来说,不区分大小写的查询可以减少输入错误带来的搜索问题,用户不需要记住确切的大小写格式。
- 避免重复:不区分大小写的查询可以避免因大小写差异而产生的数据重复问题,确保数据库中的数据唯一性。
解决方案
修改排序规则
优点:
- 统一性:可以在数据库级别、表级别或列级别设置默认排序规则,从而确保数据的一致性。
- 适用性:适合处理特定语言或文化环境中的文本数据,可以按照语言习惯进行排序和比较。
缺点:
- 性能影响:区分大小写,尤其是在进行全文搜索或大量数据比较时。
- 复杂性:对于不了解的程序员,上手可能是懵的,为什么在其他环境下可以查询,当前表不行呢?
- 数据迁移:如果排序规则不一样迁移数据的时候回导致数据丢失、
binary
优点:
- 简单性:使用
BINARY
关键字可以避免更改现有的排序规则,简化了操作。(其他程序员一看就可以是用了区分大小写) - 性能:在某些情况下,使用
BINARY
可能比修改排序规则更高效,因为它避免了排序规则的复杂性。
缺点:
- 限制性:只能在查询中通过 SQL 使用,没有办法为数据库做统一修改 。
- 可读性: 在 SQL 较为复杂的情况下,额外的关键字会给阅读带来不小的难度
选择哪种方式取决于具体的应用需求、性能考虑以及开发和维护的便利性。在实际应用中,可能需要根据具体情况灵活选择或结合使用这两种方法。