UPPER和LOWER函数在WHERE子句中必须两端同时转换才能实现大小写不敏感匹配,如WHERE UPPER(name) = UPPER('john');单边转换无效且会导致索引失效、全表扫描。

UPPER 和 LOWER 函数在 WHERE 子句中必须成对使用
直接写 WHERE name = 'John' 是大小写敏感的,多数数据库(如 PostgreSQL、SQL Server 默认)会区分大小写;但你不能只把字段转大写、而把字面量保持小写——这会导致逻辑错误。正确做法是两边统一转换:
WHERE UPPER(name) = UPPER('john')WHERE LOWER(name) = LOWER('JOHN')
两者等价,选哪个取决于团队习惯或可读性。注意:如果字段有索引,UPPER(name) 会跳过索引,查询变慢——这是最常被忽略的性能坑。
MySQL 用户要注意默认校对规则(collation)已隐式忽略大小写
MySQL 的 utf8mb4_general_ci 或 utf8mb4_0900_as_cs(注意后缀 _ci 表示 case-insensitive)会让 WHERE name = 'John' 自动匹配 'john'、'JOHN'。此时显式用 UPPER 反而多余,还可能干扰优化器。
- 查当前字段校对规则:
SHOW FULL COLUMNS FROM users LIKE 'name'; - 若显示
Collation列含_ci,就不用函数 - 若为
_cs(case-sensitive)或_bin,才需UPPER/LOWER
PostgreSQL 中大小写敏感是默认行为,且 UPPER/LOWER 不走索引
PostgreSQL 没有默认的 case-insensitive 校对规则,WHERE name = 'John' 严格匹配。用 UPPER(name) = UPPER('john') 能查到结果,但执行计划里会出现 Seq Scan(全表扫描)。
- 解决办法是建函数索引:
CREATE INDEX idx_users_name_upper ON users (UPPER(name)); - 之后查询必须严格写成
WHERE UPPER(name) = UPPER('john')才能命中索引 - 别写成
WHERE UPPER(name) = 'JOHN'——字面量大写虽等价,但某些旧版本 PostgreSQL 可能不复用索引
更安全的替代方案:使用 ILIKE(PostgreSQL)或 COLLATE(SQL Server)
比起硬套函数,原生不区分大小写的操作符或子句更清晰、也更容易优化。
- PostgreSQL:
WHERE name ILIKE 'john'—— 支持通配符,且可配合text_pattern_ops索引加速前缀查询 - SQL Server:
WHERE name COLLATE SQL_Latin1_General_CP1_CI_AS = 'john'——CI表示 case-insensitive - SQLite:
WHERE name = 'john' COLLATE NOCASE
这些写法语义明确,且数据库引擎更可能利用已有索引——前提是索引本身没带 COLLATE 冲突。实际用哪一种,得先看你的数据库类型和字段定义是否允许动态 collation 覆盖。

















