MySQL报错Illegal mix of collations是因参与比较/连接/UNION的列collation不一致触发的硬性报错,必须使它们使用完全相同的排序规则,否则错误必现。

生产环境报错而测试环境正常,90% 是数据库级排序规则(collation)或字符集(character set)不一致导致的隐式转换失败,不是代码写错了,而是环境“悄悄变了”。
查清当前会话与库表的真实字符集和排序规则
别只看 SHOW VARIABLES LIKE 'character\_set\_%'——它只反映连接层配置。真正起作用的是数据库、表、列三级定义,以及存储过程里变量继承的默认规则。
- 执行
SELECT DATABASEPROPERTYEX('your_db', 'Collation')(SQL Server)或SELECT DEFAULT_COLLATION_NAME FROM sys.databases WHERE name = 'your_db'确认数据库默认排序规则 - 查关键字段:
SELECT column_name, collation_name, character_set_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = 'your_db' AND table_name = 'your_table' AND column_name IN ('param_col', 'join_col') - MySQL 存储过程中变量的 collation 默认继承所在数据库的
DEFAULT COLLATION,不是连接参数;SQL Server 中变量类型(VARCHARvsNVARCHAR)和字面量是否带N前缀,直接决定编码路径
WHERE 条件中字符串比较报错(如 ERROR 1267)的本质是两边 collation 不兼容
错误信息 Illegal mix of collations (utf8mb4_0900_bin,IMPLICIT) and (utf8mb4_bin,IMPLICIT) 表示 MySQL 在做 = 比较时,左右操作数用了不同排序规则,且无法自动 coercible(隐式转换)对齐。
- 常见组合:表字段是
utf8mb4_0900_bin,但存储过程变量(如DECLARE v_id VARCHAR(32))在utf8mb4_bin的库中创建,就天然不匹配 - 不能靠
COLLATE utf8mb4_0900_bin强制右侧值对齐——这会让索引失效,查询变慢甚至全表扫描 - 安全做法是统一源头:要么把变量声明为
DECLARE v_id VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin,要么把字段改到和库默认一致(需ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin)
SQL Server 存储过程里中文乱码,大概率不是字符集问题,而是 collation 隐式转换踩坑
即使你用了 NVARCHAR 参数和列,只要字符串字面量没加 N 前缀,或者数据库/列用的是 SQL_Latin1_General_CP1_CI_AS 这类非 Unicode 友好规则,WHERE name = N'张三' 也可能返回空——因为比较前 SQL Server 把 N'张三' 转成了 CP1252 编码再比,早丢字了。
- 所有含中文的字符串字面量必须写成
N'张三',动态 SQL 拼接时每个片段都要加,漏一个就退化 -
ALTER DATABASE ... COLLATE Latin1_General_100_CI_AS_SC_UTF8只改默认值,已有列的collation_name不变,必须单独ALTER TABLE ... ALTER COLUMN ... COLLATE ... - 函数如
REPLACE(@col, 'a', N'b')中,若@col是VARCHAR,整个表达式按VARCHAR规则处理,N'b'会被转成非 Unicode 再参与运算
最易被忽略的点:MySQL 存储过程变量的排序规则由创建时所在的数据库决定,迁移或克隆库时如果没显式指定 CREATE DATABASE ... COLLATE,新库可能沿用实例默认(比如 utf8mb4_bin),而旧库是 utf8mb4_0900_ai_ci——此时哪怕表结构一模一样,过程一跑就报错。










