今天在看项目后台日志时看到了一个报错“Illegal mix of collations
”非法混合排序,然后看了数据库的默认排序为utf8mb4_general_ci
,而数据库中的有些表的表字段排序为utf8mb4_general_ci
,有些为utf8mb4_unicode_ci
有看了我的数据库表建表语句,发现有些建表语句的表字段指定了utf8mb4_unicode_ci
,而有些表的建表语句的表字段未指定排序规则,而使用了默认的,导致不同表的字段排序规则不同,导致一些关联SQL查询的时候就报错了
SQL错误1267(Illegal mix of collations
)是一个在MySQL数据库中常见的错误,它表示在执行查询时,尝试比较或操作使用了**不兼容字符集(charset)或排序规则(collation)**的字符串数据。
简单来说,就是你想把“苹果”和“🍎”放在一起比大小,但它们来自不同的“语言体系”,系统不知道怎么比,就报错了。
错误原因
这个错误通常发生在以下几种情况:
表与表之间JOIN时字段的排序规则不同
- 比如
table1.name
使用utf8mb4_unicode_ci
,而table2.name
使用utf8mb4_general_ci
。
WHERE子句中比较不同排序规则的字段或字面量
- 比如
WHERE table1.name = '中文'
,但'中文'
的排序规则与table1.name
不同。
UNION操作合并结果集时,对应列的排序规则不一致
函数参数或表达式中混合了不同排序规则的字符串
如何解决?
✅ 方法一:统一字段的排序规则(推荐)
修改表结构,使相关字段使用相同的字符集和排序规则。
-- 修改某个字段的排序规则
ALTER TABLE your_table MODIFY column_name VARCHAR(255)
COLLATE utf8mb4_unicode_ci;
-- 或者同时指定字符集
ALTER TABLE your_table MODIFY column_name VARCHAR(255)
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
建议统一使用 utf8mb4
字符集 和 utf8mb4_unicode_ci
排序规则,以支持完整的UTF-8(包括emoji)。
✅ 方法二:在查询中临时转换排序规则(快速修复)
在SQL语句中使用 COLLATE
关键字强制转换其中一个字段或字符串的排序规则。
-- 在JOIN中使用
SELECT *
FROM table1 t1
JOIN table2 t2 ON t1.name = t2.name COLLATE utf8mb4_unicode_ci;
-- 在WHERE中使用
SELECT * FROM users
WHERE username = '张三' COLLATE utf8mb4_unicode_ci;
-- 统一两边的排序规则
SELECT * FROM table1
WHERE name COLLATE utf8mb4_unicode_ci = 'test' COLLATE utf8mb4_unicode_ci;
✅ 方法三:检查并统一数据库/表的默认排序规则
确保数据库和表的默认设置一致:
-- 查看数据库的排序规则
SHOW CREATE DATABASE your_db;
-- 查看表的排序规则
SHOW CREATE TABLE your_table;
-- 修改数据库默认排序规则
ALTER DATABASE your_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
✅ 方法四:避免隐式转换(开发规范)
- 确保应用程序连接数据库时也使用一致的字符集:
-- 连接时设置
SET NAMES 'utf8mb4';
- 在创建表时明确指定字符集和排序规则,不要依赖默认值。
如何诊断?
使用以下命令查看具体是哪些字段导致冲突:
-- 查看字段的排序规则
SHOW FULL COLUMNS FROM your_table;
-- 查看两个字段的排序规则是否一致
SELECT
COLUMN_NAME,
COLLATION_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'your_database'
AND TABLE_NAME = 'your_table'
AND COLUMN_NAME IN ('column1', 'column2');
错误信息本身也会告诉你具体的冲突,例如:
Illegal mix of collations (utf8mb4_general_ci,IMPLICIT) and (utf8mb4_unicode_ci,IMPLICIT)
这说明一个是 general_ci
,另一个是 unicode_ci
。
最佳实践: 在项目初期就统一使用 utf8mb4
+ utf8mb4_unicode_ci
,避免后期踩坑。