alter database只设新表默认值,不修改已有表和字段的collate,而排序行为由字段级collate决定,优先级为字段>表>库,因此中文order by仍乱序;必须用alter table modify或convert to直接修改字段或表的collate才能生效。

改 MySQL 默认排序规则,不能只改数据库级别——那对已有表和字段完全无效,中文 ORDER BY 依然乱序。真正起作用的是字段级 COLLATE,优先级:字段 > 表 > 库。
为什么 ALTER DATABASE 不影响已有排序行为
执行 ALTER DATABASE your_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci 后,SHOW CREATE DATABASE 确实会显示新值,但 SHOW CREATE TABLE existing_table 里所有字段的 COLLATION 仍是旧的(比如 utf8mb4_0900_ai_ci 或 utf8mb4_general_ci)。MySQL 排序时查的是字段定义,不是库设置。
- 该命令只设“新表默认值”,不触碰任何现有结构
- MySQL 8.0+ 中,即使库设成
utf8mb4_unicode_ci,新建表仍可能用utf8mb4_0900_ai_ci(由character_set_server绑定的硬编码默认值决定) - 常见错误现象:
SELECT * FROM users ORDER BY name中文仍乱序,“王五”排在“李四”前
如何让已有表的中文排序正确
必须直接修改表或字段的 COLLATE。推荐优先改字段,精准可控:
- 查当前字段排序规则:
SHOW FULL COLUMNS FROM your_table,看Collation列 - 改单个字段(最安全):
ALTER TABLE your_table MODIFY name VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci—— 会重写该字段,排序立即生效 - 批量改整张表(慎用):
ALTER TABLE your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci—— 所有字符类型字段都会被更新,大表会锁表、耗时长 - 注意:
ALTER TABLE your_table DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci是无效操作,它只改表级默认,不改字段
服务器配置中 collation-server 在 8.0+ 是只读变量
别再试 SET GLOBAL collation_server = 'utf8mb4_unicode_ci',MySQL 8.0+ 直接报错:Variable 'collation_server' is a read only variable。
- 配置文件里写
[mysqld] collation-server = utf8mb4_unicode_ci能生效,但仅用于连接初始化参考,不决定新建库/表的默认COLLATE - 真正决定新库默认值的是
character_set_server:设为utf8mb4,默认就用utf8mb4_0900_ai_ci,无法通过配置改成utf8mb4_unicode_ci(硬编码绑定) - 想让新库默认用
utf8mb4_unicode_ci?只能建库时显式指定:CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
字段级 COLLATE 才是排序行为的实际控制点
哪怕你把服务器、库、表全设成 utf8mb4_unicode_ci,只要某个 VARCHAR 字段定义里写着 COLLATE utf8mb4_0900_ai_ci,它参与比较或 ORDER BY 就按那个规则来。
- 字段优先级最高,覆盖表和库设置
- 业务敏感字段可差异化设置:如
email VARCHAR(255) COLLATE utf8mb4_bin(区分大小写),nike_name VARCHAR(50) COLLATE utf8mb4_unicode_ci(中文友好排序) - 隐式转换易引发错误:
ERROR 1267 (HY000): Illegal mix of collations常因 JOIN 或函数中字段COLLATE不一致触发 - 修改字段
COLLATE后,记得检查相关索引是否仍有效——排序规则变更可能使索引失效











