查MySQL列字符集和排序规则应优先查询information_schema.columns,因SHOW CREATE TABLE仅显示建表默认值,实际列可能已被单独修改;character_set_name和collation_name需同时检查,NULL值表示该列为二进制类型。
查 MySQL 表中某列的字符集和排序规则
直接看 information_schema.columns 最可靠,别依赖 show create table 的输出——它只显示建表时的默认值,实际列可能被单独改过。
SELECT character_set_name, collation_name FROM information_schema.columns WHERE table_schema = 'your_db' AND table_name = 'your_table' AND column_name = 'your_column';- 注意
character_set_name和collation_name是两个独立字段,不能只看其中一个;比如utf8mb4字符集下,utf8mb4_0900_ai_ci和utf8mb4_bin行为差异极大 - 如果查出来是
NULL,说明该列是二进制类型(如BLOB、VARBINARY),不参与字符集解析
为什么 COLLATE 比字符集更容易引发乱码
字符集决定能存什么字,排序规则决定怎么比较、怎么索引、怎么排序。乱码常发生在隐式转换时,而触发点往往是排序规则不一致。
- 当 JOIN 两张表的同名字段字符集相同但
collation不同(比如一边是utf8mb4_unicode_ci,一边是utf8mb4_general_ci),MySQL 会报Illegal mix of collations -
WHERE条件里对列用函数(如UPPER(col))后,若函数返回值 collation 与列不匹配,也可能触发隐式转换失败 - 临时表字段默认继承连接的 collation,如果客户端连接用的是
latin1_swedish_ci,即使原表是utf8mb4,写入临时表时也可能截断或转义
ALTER COLUMN 修改 collation 的实操要点
改列的排序规则不是加个 COLLATE 就完事,必须明确是否要转换数据,以及是否影响索引行为。
- 安全写法:
ALTER TABLE t MODIFY COLUMN c VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;—— 这会重写整列数据,确保编码一致 - 如果只想改定义不转数据(极少见),用
CHANGE COLUMN并显式指定CONVERT TO或省略,但 MySQL 通常会拒绝不一致的组合 - 修改后务必检查索引:如果原列上有前缀索引(如
INDEX(c(10))),而新 collation 导致单字符字节数变大(如从utf8mb3到utf8mb4),可能触发Specified key was too long
连接层 collation 对查询结果的隐形影响
客户端连接的 collation_connection 会影响字符串字面量、函数返回值、临时表字段的默认排序规则,进而改变比较逻辑。
- 执行
SELECT @@collation_connection;看当前连接设定,常见错误是应用连上库后没执行SET NAMES utf8mb4; - 字面量如
'中文'的 collation 默认继承collation_connection,如果它是latin1_swedish_ci,跟utf8mb4列比较就会出错 - Django/SQLAlchemy 等 ORM 通常会在连接初始化时自动设好,但 raw SQL 或 shell 工具(如
mysqlCLI)容易漏掉,建议在 my.cnf 的[client]段加default-character-set = utf8mb4
SELECT @@xxx 排查,不能只盯一个地方。

















