直接用字符串字段join会漏匹配,除非两边collation明确一致且不区分大小写;最稳妥的现场修复方式是on upper(t1.col) = upper(t2.col),必须两边都转。

直接用字符串字段 JOIN 一定会漏匹配,除非两边 collation 明确一致且不区分大小写;最稳妥的现场修复方式是 ON UPPER(t1.col) = UPPER(t2.col),但必须两边都转、不能只转一边。
为什么只写 UPPER(t1.col) = t2.col 会丢数据
这种写法看似“把左表转大写去匹配右表”,实际比较逻辑仍是:数据库先计算 UPPER(t1.col),再拿结果和原始 t2.col(含大小写)做字节比对。如果 t2.col 存的是 'alice',而 UPPER(t1.col) 是 'ALICE',那 'ALICE' = 'alice' 为 false——根本不会命中。真正起作用的是两端形态统一:UPPER(t1.col) = UPPER(t2.col) 才能确保所有变体归一后对齐。
- NULL 值天然安全:
UPPER(NULL)返回NULL,NULL = NULL仍为 unknown,该行不参与匹配(符合预期) - 若字段含全角空格或不可见字符,得先
TRIM()再UPPER():ON UPPER(TRIM(t1.col)) = UPPER(TRIM(t2.col)) - MySQL 5.7 及更早版本对中文/emoji 的
UPPER()行为不稳定,建议先确认字符集为utf8mb4
什么时候不该用 UPPER(),该改 COLLATE
如果右表字段已有索引,且查询高频,硬套 UPPER() 会让索引完全失效——优化器无法下推查找,只能全表扫描。这时优先查该列的排序规则:SHOW FULL COLUMNS FROM table_name LIKE 'col_name'。若显示 Collation 是 utf8mb4_0900_ai_ci(MySQL)或 SQL_Latin1_General_CP1_CI_AS(SQL Server),就直接在 ON 或 WHERE 中临时指定:ON t1.col COLLATE utf8mb4_0900_ai_ci = t2.col COLLATE utf8mb4_0900_ai_ci。
- PostgreSQL 不支持在
ON或WHERE中用COLLATE做等值比较,必须用ILIKE或函数索引 - SQL Server 中若原列是
_CS规则,不加COLLATE就无法匹配'Alice'和'alice' -
_ci表示 case-insensitive,_as表示 accent-sensitive;别混用_cs和_ci,否则行为不可控
想提速?建函数索引比硬套函数更有效
在 PostgreSQL 或 MySQL 8.0+ 中,与其每次 JOIN 都算一遍 UPPER(),不如提前把转换结果固化进索引。例如:
CREATE INDEX idx_upper_name ON users (UPPER(name));
之后写 ON UPPER(u.name) = UPPER(o.customer_name) 就能走索引。注意 MySQL 8.0+ 的函数索引语法必须带双括号:CREATE INDEX idx ON t ((UPPER(col))),漏掉内层括号会建失败。
- SQL Server 推荐加计算列:
ALTER TABLE users ADD name_upper AS UPPER(name); CREATE INDEX IX_name_upper ON users(name_upper); - 避免用
CRC32(name)做哈希加速——32 位太短,百万级数据碰撞率超 5% - 如果字段平均长度 > 50 字节,普通前缀索引效果差,函数索引或哈希列(如
CONV(LEFT(MD5(name), 16), 16, 10))更可靠
跨库或混合 collation 场景下,UPPER() 是唯一确定性方案
当左表来自 MySQL(utf8mb4_0900_as_cs),右表来自 PostgreSQL(默认区分大小写),或者同一库中两表 collation 明确不同(如一个 _ci、一个 _cs),COLLATE 切换会失效或报错。此时 UPPER() 不依赖底层配置,行为跨库一致,是唯一可落地的方案。
最容易被忽略的是:SHOW FULL COLUMNS 看到的 Collation 值,未必就是 JOIN 实际生效的规则——如果字段定义没显式指定 collation,它可能继承自表或数据库级默认值,而 JOIN 时又受连接参数影响。真要验证,得用 EXPLAIN ANALYZE 看执行计划里是否出现 Using where; Using join buffer 这类退化提示。










