upper/lower在where中无效,根本原因是mysql默认collation大小写不敏感,且函数导致索引失效;它们仅转换ascii字母,对中文、emoji等无影响。

UPPER 和 LOWER 函数在 WHERE 条件中为什么没效果?
直接在 WHERE 子句里对字段用 UPPER() 或 LOWER() 做匹配,看似合理,但可能触发全表扫描——尤其当字段没函数索引时。数据库无法利用原始列上的普通索引,因为索引是按原始大小写存储的。
常见错误写法:WHERE UPPER(name) = 'JOHN',这会让 name 列上已有的索引失效。
- 若需频繁做不区分大小写的等值查询,优先建函数索引(如 PostgreSQL 的
CREATE INDEX idx_name_upper ON users (UPPER(name));MySQL 8.0+ 支持函数索引,5.7 不支持) - 若只是偶尔转换显示,
SELECT UPPER(name) FROM users安全且无性能代价 - SQLite 默认不区分大小写,
WHERE name = 'john'就能匹配 'John',此时无需显式调用LOWER()
MySQL 中 LOWER() 对中文、数字或 Emoji 有没有副作用?
LOWER() 和 UPPER() 只作用于 ASCII 字母(A–Z / a–z),对中文、数字、标点、Emoji 完全无影响,返回原值。不是“转换失败”,而是设计如此——它们不是通用字符处理函数,只是字母大小写映射。
例如:SELECT LOWER('你好123?'); 结果仍是 你好123?,不会报错也不会改变。
- 别指望它处理带重音的西欧字符(如
é→É),MySQL 默认 collation(如utf8mb4_general_ci)不保证这类转换,改用utf8mb4_0900_as_cs也无效——UPPER()仍只动 ASCII - 需要真正 Unicode 感知的大小写转换?得靠应用层(如 Python 的
.upper()配合unicodedata)或数据库外处理
PostgreSQL 的 lower() 为何有时返回 NULL?
PostgreSQL 的 lower() 和 upper() 对 NULL 输入严格返回 NULL,不是空字符串。这是标准 SQL 行为,但容易被忽略,导致前端显示异常或条件判断出错。
比如:SELECT lower(NULL); → NULL,而非 ''。
- 安全写法:用
COALESCE(lower(name), '')显式转为空字符串 - 在
ORDER BY中混用:如ORDER BY lower(name) NULLS LAST,避免NULL排最前干扰排序逻辑 - 连接多个字段时更危险:
lower(first_name) || ' ' || lower(last_name)——任一为NULL,整个结果变NULL,得用CONCAT()(自动跳过NULL)或嵌套COALESCE
SQL Server 的 UPPER/LOWER 在排序规则(collation)下会怎样?
SQL Server 的 UPPER() / LOWER() 行为受列或数据库的 collation 控制。某些 Turkish 或 Lithuanian 排序规则中,字母映射关系和英语不同(如土耳其语的 i 大写是 İ,不是 I),可能导致意外结果。
例如:SELECT UPPER('istanbul') COLLATE SQL_Latin1_General_CP1254_CI_AS; 返回 İSTANBUL(带点的 İ),而默认英文 collation 返回 ISTANBUL。
- 生产环境别依赖隐式 collation,显式用
COLLATE DATABASE_DEFAULT锁定行为 - 跨库 JOIN 时,若两边 collation 不同,
UPPER(a.col) = UPPER(b.col)可能因 collation 冲突报错,需统一指定 collation - 注意:
COLLATE子句不能用于函数参数内部,只能加在字段或表达式末尾,如UPPER(name) COLLATE SQL_Latin1_General_CP1254_CI_AS










