row_number()本身无字符集问题,真正出错的是order by或partition by字段collation不一致:order by混用不同collation字符串会报illegal mix of collations;partition by使用_ci导致隐式转换和分组不准;cte中拼接不同collation字段会中断窗口计算;根因在字段定义与上下文collation未对齐。

ROW_NUMBER() 本身不涉及字符集,所谓“字符集冲突”实际是误判——真正出问题的永远是 ORDER BY 或 PARTITION BY 字段的 collation 不一致,导致排序失败或结果不可靠。
ORDER BY 字段 collation 不匹配直接报错
当 ORDER BY 后跟的是字符串列(如 name),而该列 collation 与连接上下文或临时表默认 collation 冲突时,MySQL 会拒绝执行窗口函数,报类似错误:Illegal mix of collations。
- 典型场景:JOIN 两张表,
a.name是utf8mb4_0900_as_cs,b.tag是utf8mb4_general_ci,却在OVER(PARTITION BY a.name ORDER BY b.tag)中混用 - 解决方法不是改
ROW_NUMBER(),而是统一排序字段的 collation:ORDER BY b.tag COLLATE utf8mb4_0900_as_cs - 更稳妥的做法是建索引时显式指定 collation,例如:
ALTER TABLE b ADD INDEX idx_tag_cs (tag) COLLATE utf8mb4_0900_as_cs;
PARTITION BY 字符串字段隐式转换引发性能抖动
即使没报错,PARTITION BY dept_name 若字段 collation 为 _ci(大小写不敏感),MySQL 在分组时会做隐式转换,导致无法使用索引、EXPLAIN 显示 Using temporary,且相同名称不同大小写(如 "HR" 和 "hr")被分到同一组——这不是 bug,是 collation 语义决定的。
- 检查当前字段 collation:
SHOW FULL COLUMNS FROM emp LIKE 'dept_name'; - 若业务要求严格区分大小写,应改用
_cs或_bincollation:ALTER TABLE emp MODIFY dept_name VARCHAR(50) COLLATE utf8mb4_0900_as_cs; - 注意:修改 collation 可能触发全表重建,大表需评估停机时间
CTE 或子查询中跨字符集字段导致窗口计算中断
在 CTE 中 SELECT 多个来源的字符串字段(比如从视图 + 临时表拼接),若 collation 优先级不一致,MySQL 可能在计算 ROW_NUMBER() 前就卡在字段合并阶段,报 Cannot create a consistent collation for result。
- 避免在 CTE 的 SELECT 列表里直接拼接不同 collation 的字符串,例如:
CONCAT(v.name, t.alias) - 统一强制转换:
CONCAT(v.name COLLATE utf8mb4_0900_as_cs, t.alias COLLATE utf8mb4_0900_as_cs) - 临时表建表时显式声明 collation:
CREATE TEMPORARY TABLE tmp (label VARCHAR(100) COLLATE utf8mb4_0900_as_cs);
ROW_NUMBER() 函数体内,而在它依赖的排序和分组字段的 collation 定义与上下文一致性上。最容易被忽略的是:你看到的报错位置在窗口函数调用行,但根因往往藏在上游表结构或 JOIN 条件里。











