MySQL字符串比较是否区分大小写取决于字段排序规则,utf8mb4_general_ci不区分,utf8mb4_bin或utf8mb4_0900_as_cs区分;可用BINARY前缀或COLLATE指定临时改变行为,但BINARY可能跳过索引。

MySQL 中用 BINARY 或 COLLATE 强制大小写敏感匹配
默认情况下,MySQL 的字符串比较是否区分大小写,取决于字段的排序规则(COLLATION)。比如 utf8mb4_general_ci 是不区分大小写的,而 utf8mb4_bin 或 utf8mb4_0900_as_cs 才是区分的。直接在查询里改行为更灵活,不用动表结构。
常见做法是临时加 BINARY 前缀或用 COLLATE 指定:
-
WHERE BINARY username = 'Admin'—— 简单粗暴,但会跳过索引(除非该列本身是BINARY类型) -
WHERE username COLLATE utf8mb4_0900_as_cs = 'Admin'—— 更规范,且在支持的 collation 下可能走索引 - 如果字段已有
utf8mb4_bincollation,=本身就区分大小写,无需额外修饰
PostgreSQL 默认区分大小写,但 ILIKE 和 LOWER() 容易误用
PostgreSQL 的 = 操作符天生区分大小写,这点和 MySQL 相反。很多人习惯性加 LOWER() 来“统一处理”,但要注意性能陷阱:
-
WHERE LOWER(name) = 'alice'—— 无法使用name上的普通 B-tree 索引,除非建函数索引:CREATE INDEX idx_name_lower ON users (LOWER(name)); -
WHERE name ILIKE 'alice'—— 语义等价于上面的LOWER(),但底层实现不同;同样不走普通索引,且ILIKE不支持前缀匹配优化(如ILIKE 'ali%'不能高效利用索引) - 真要模糊+大小写不敏感,优先考虑
pg_trgm扩展 +GIN索引,而不是硬套LOWER()
SQL Server 的 COLLATE 语法最显式,但也最容易漏掉隐式转换
SQL Server 允许在任意表达式后追加 COLLATE,例如:
WHERE username COLLATE SQL_Latin1_General_CP1_CS_AS = 'Admin'
注意两点:
-
CS_AS表示 Case-Sensitive + Accent-Sensitive;若只要大小写敏感、允许重音一致,用CS_AI - 如果比较的两边 collation 冲突(比如一列是
CI,另一侧硬写CS),SQL Server 会尝试隐式转换,可能报错Cannot resolve collation conflict;此时必须显式给两边都加COLLATE,或用CONVERT(VARCHAR, ...)绕过 - 临时表或变量的 collation 默认继承数据库级设置,容易和主表不一致,查不出数据时先检查这个
跨数据库可移植写法几乎不存在,别指望 UPPER() 能解决所有问题
有人想“统一用 UPPER(col) = UPPER('input')”,看似安全,实则埋雷:
- 某些字符在不同语言下大写规则不同(比如土耳其语的
i→İ),UPPER()结果不可靠 - 索引失效是通病:几乎所有主流数据库都无法对带函数的左值高效索引,除非你主动建函数索引(且各库语法不同)
- JSON 字段、XML 内容、全文检索场景下,大小写逻辑由解析器控制,SQL 层的
UPPER()可能根本没机会介入
真正关键的是:明确你的字段原始 collation / encoding,再决定是在建表时固化(推荐长期项目),还是在查询时动态干预(适合临时适配)。混用方式最容易在迁移或升级后突然失效。

















