焦点

mysql不区分大小写设置

时间:2010-12-5 17:23:32  作者:焦点   来源:焦点  查看:  评论:0
内容摘要: MySQL 的默认排序规则是 utf8mb4_general_ci,那个 ci 就是 case insensitive,不区分大小写。但很多人建表时用了 utf8mb4_bin 或者 utf8mb4

MySQL 的区分默认排序规则是 utf8mb4_general_ci,那个 ci 就是写设 case insensitive,不区分大小写。区分但很多人建表时用了 utf8mb4_bin 或者 utf8mb4_0900_ai_ci,写设结果查询时发现 WHERE name = 'abc' 和 'ABC' 返回的区分结果不一样,一脸懵。写设

这事我踩过坑。区分去年接手一个老项目,写设用户表里存了邮箱,区分登录时用户输入 Test@Example.com,写设但库里存的区分是 test@example.com。代码里写的写设是 WHERE email = ?,因为表的区分排序规则是 utf8mb4_bin,死活匹配不上。写设用户反馈登录失败,区分排查了半天才发现是大小写问题。

解决办法有几种,看你的场景。

第一种,改表级别排序规则。最简单粗暴:

ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; 

这会重建整张表,数据量大时锁表时间长,线上操作要谨慎。但一劳永逸,之后所有字符串比较都忽略大小写。

第二种,只改某一列的排序规则。比如你只想让 email 字段不区分大小写,其他字段保持原样:

ALTER TABLE users MODIFY email VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; 

注意,改了列级别,索引也会跟着重建。如果这张表已经有针对 email 的索引,改完排序规则后,索引会失效,需要重新创建。

第三种,查询时临时指定。如果你不想动表结构,就在 SQL 里强制指定:

SELECT * FROM users WHERE email = 'Test@Example.com' COLLATE utf8mb4_general_ci; 

但这样会导致索引失效,全表扫描。数据量小无所谓,万一表里有几百万行,那查询慢得能让你喝杯咖啡回来还在跑。

还有个细节容易忽略——连接层的排序规则。你的 MySQL 客户端连接时可能默认用了 utf8mb4_bin,即使表是 _ci 的,某些操作还是区分大小写。比如 ORDER BY 排序时,如果连接排序规则是 _bin,排序结果就是先大写后小写。检查一下你的连接参数,SET NAMES utf8mb4 COLLATE utf8mb4_general_ci 能解决大部分问题。

说到这,得提一个反直觉的情况:唯一索引也会受排序规则影响。如果表是 _ci,那你插入 abc@gmail.com 后再插入 ABC@gmail.com 会报重复键错误。这其实是好事,防止脏数据。但如果你业务上需要区分这两个邮箱(虽然很少见),那必须用 _bin。

最后说个经验之谈——建表时就定好规则。新项目别偷懒,直接在建表语句里写清楚:

CREATE TABLE users ( email VARCHAR(255) COLLATE utf8mb4_general_ci NOT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; 

比事后改来改去省心一百倍。

哦对了,MySQL 8.0 默认排序规则变成了 utf8mb4_0900_ai_ci,它也是不区分大小写的,但和 _general_ci 的排序逻辑略有差异。如果你从 5.7 迁移到 8.0,注意对比一下查询结果,特别是涉及特殊字符(比如德语变音、法语重音)时,_0900_ai_ci 的忽略规则更复杂。别问我怎么知道的——测试环境跑得好好的,生产环境一换版本,排序结果全变了。

最近更新
热门排行
copyright © 2026 powered by 力不从心网   sitemap