结论:LOWER()和UPPER()仅转换ASCII字母,WHERE中滥用导致索引失效、查询变慢;适用于展示标准化或临时大小写不敏感比对,但对中文、emoji、重音字符无效。

直接说结论:用 LOWER() 和 UPPER() 最快,但它们只改英文字母,且在 WHERE 里滥用会拖慢查询。
什么时候该用 LOWER() 或 UPPER()
这两个函数适合做「展示层标准化」或「临时比对」,比如导出报表时统一用户名为小写,或者查一个用户输入的邮箱(大小写混杂)是否已存在:
- SELECT
LOWER(email)FROM users WHERE id = 123; - SELECT * FROM users WHERE
LOWER(username)= 'admin';
注意:第二条只有在 username 字段本身存储了大小写混合值(如 'AdMiN'、'ADMIN'、'admin' 共存),且你又不能改表结构时才真有用。如果字段本就全小写,加 LOWER() 纯属多余。
WHERE 里用 LOWER() 查不到数据?先看排序规则
常见现象:写了 WHERE LOWER(name) = 'john' 却没结果,但 WHERE name = 'john' 又能查到——不是函数错了,是你的字段用了不区分大小写的排序规则(比如 utf8mb4_0900_ai_ci)。这种情况下,name = 'john' 本身就匹配 'JOHN'、'John',根本轮不到函数出场。
- 查当前字段排序规则:
SHOW CREATE TABLE users;看name列定义里的COLLATE值 - 想让
LOWER()在WHERE中真正起作用,得配大小写敏感规则(如utf8mb4_0900_as_cs) - 否则,更高效的做法是把条件值转成字段实际存储格式:
WHERE name = 'JOHN'(前提是字段存的就是大写)
为什么 LOWER(name) 会让查询变慢?
因为 LOWER(name) 是表达式,MySQL 无法直接命中 name 字段上的普通索引。即使字段有索引,这条语句也会触发全表扫描。
- MySQL 8.0+ 支持函数索引,可显式创建:
CREATE INDEX idx_lower_name ON users ((LOWER(name))); - 旧版本只能靠冗余字段:加一列
username_lower VARCHAR(64),插入/更新时用LOWER()写入,并给它建索引 - 中文、emoji、带重音字符(如 é, ñ)完全不受
LOWER()/UPPER()影响,函数返回原值——这不是 bug,是 MySQL 的设计限制
别指望它们处理非 ASCII 文本
LOWER('café') 返回 'café',不是 'café';UPPER('你好') 还是 '你好'。MySQL 的大小写转换逻辑只覆盖 A–Z / a–z,其他 Unicode 字符一律透传。
如果你的业务要支持多语言用户名或邮箱标准化(比如统一小写后去重),别依赖这两个函数——得在应用层用 ICU 或对应语言的 locale-aware 方法处理,再存入数据库。


















