正确写法是where upper(name) = upper('john'),必须两端同步转换才能实现大小写不敏感精确匹配;只转一边会导致漏匹配或索引失效,而collate方案跨库兼容性差、行为不一致。

UPPER 和 LOWER 在 WHERE 子句中必须成对使用
直接写 WHERE name = 'John' 是大小写敏感的,不同数据库行为不一致(比如 MySQL 默认不敏感,PostgreSQL 默认敏感)。要确保跨库兼容、逻辑明确,必须显式统一大小写。常见错误是只转换字段却不转换查询值,比如 WHERE UPPER(name) = 'john' —— 这会永远不匹配,因为 'john' 没转大写。
正确做法是两边都用同一函数处理:
WHERE UPPER(name) = UPPER('John')WHERE LOWER(name) = LOWER('JOHN')
选 UPPER 还是 LOWER 本质没区别,但建议统一用 LOWER,因为部分字符集(如带重音符号的拉丁字母)在某些旧版 PostgreSQL 中 UPPER 可能有边界 case 问题。
LIKE 匹配时大小写转换要包裹整个模式
用 LIKE 做模糊搜索时,不能只转字段或只转字面量。比如 WHERE LOWER(name) LIKE 'joh%' 是错的——'joh%' 没转小写,而通配符本身不受大小写影响,但前缀部分必须和字段转换后一致。
正确写法是把整个模式也过一遍函数:
WHERE LOWER(name) LIKE LOWER('Joh%')WHERE UPPER(name) LIKE UPPER('joh%')
注意:如果模式里含变量(比如从参数拼接),必须确保该变量也经过相同转换,否则索引可能失效或结果出错。
性能隐患:函数调用会让索引失效
一旦对列使用 UPPER() 或 LOWER(),大多数数据库无法走普通 B-tree 索引(除非建函数索引)。例如 CREATE INDEX idx_name_lower ON users (LOWER(name)) 在 PostgreSQL 和 MySQL 8.0+ 支持,但 SQLite 不支持函数索引。
替代方案更实用:
- MySQL:确认排序规则是
_ci(case-insensitive),比如utf8mb4_unicode_ci,则普通=和LIKE自动不区分大小写 - PostgreSQL:用
ILIKE替代LIKE,或用::citext类型(需启用citext扩展) - SQL Server:默认排序规则通常不敏感,但显式用
COLLATE SQL_Latin1_General_CP1_CI_AS更可靠
别为了“看起来通用”硬套 UPPER/LOWER,先查清当前库的排序规则和索引能力。
特殊字符和 Unicode 的坑
UPPER 和 LOWER 在非 ASCII 字符上表现不稳定。比如德语 'ß' 转大写是 'SS',但 UPPER('ß') 在 SQLite 返回空,在 PostgreSQL 返回 'SS',在 SQL Server 可能报错。
更麻烦的是土耳其语:'i' 的大写不是 'I',而是 'İ'(带点)。如果业务涉及多语言用户,仅靠 UPPER/LOWER 匹配会漏数据。
稳妥做法:
- 避免在 WHERE 中依赖
UPPER/LOWER处理非英文字符 - 用数据库原生不敏感操作(如 PostgreSQL 的
ILIKE或citext) - 实在要函数转换,先测试目标数据库对关键字符的实际输出,别假设行为一致
大小写无关匹配看着简单,真正踩进 Unicode 和索引细节里,很容易在上线后才发现查不到土耳其用户名或中文拼音首字母搜不出来。










