背景
在MySQL中常见的utf8mb4排序规则有:
- utf8mb4_0900_ai_ci
- utf8mb4_unicode_ci
- utf8mb4_general_ci
当设置表的默认字符集为utf8mb4字符集但未明确指定排序规则时:
- 在MvSQL5.7版本中,默认排序规则为
utf8mb4_general_ci
- 在MySQL8.0版本中,默认排序规则为
utf8mb4_0900_ai_ci
由于utf8mb4_0900_ai_ci排序规则时MySQL80引入的排序规则,因此将MySQL80版本的表导入到MySQL5.7或MySQL5.6版本时,会存在字符集无法识别的问题。
[Err]1273-Unknown collation: utf8mb4_0900_ai_ci
COLLATE设置级别及其优先级
设置COLLATE
可以在示例级别、库级别、表级别、列级别、以及SQL指定。实例级别的COLLATE
设置就是mysql配置文件或启动指令中的collation_connection
系统变量。
库级别设置COLLATE
的语句如下:
CREATE DATABASE <db_name> DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
如果库级别没有设置
CHARSET
和COLLATE
,则库级别默认的CHARSET
和COLLATE
使用实例级别的设置。
在mysql8.0以下版本中,你如果什么都不修改,默认的CHARSET
是Latin1
,默认的COLLATE
是latin1_swedish_ci
。
从mysql8.0开始,默认的CHARSET
已经改为了utf8mb4
,默认的COLLATE
改为了utf8mb4_0900_ai_ci
。
表级别的COLLATE
设置,则是在CREATE TABLE
的时候加上相关设置语句,例如:
CREATE TABLE (
……
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
如果表级别没有设置CHARSET
和COLLATE
,则表级别会继承库级别的CHARSET
与COLLATE
。
列级别的设置,则在CREATE TABLE
中声明列的时候指定,例如
CREATE TABLE (
`field1` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
……
) ……
如果列级别没有设置CHARSET
和COLATE
,则列级别会继承表级别的CHARSET
与COLLATE
。
最后,你也可以在写SQL查询的时候显示声明COLLATE
来覆盖任何库表列的COLLATE
设置,不太常用,了解即可:
SELECT DISTINCT field1 COLLATE utf8mb4_general_ci FROM table1;
SELECT field1, field2 FROM table1 ORDER BY field1 COLLATE utf8mb4_unicode_ci;
如果全都显示设置了,那么优先级顺序是 SQL语句 > 列级别设置 > 表级别设置 > 库级别设置 > 实例级别设置。
也就是说列上所指定的COLLATE
可以覆盖表上指定的COLLATE
,表上指定的COLLATE
可以覆盖库级别的COLLATE
。
如果没有指定,则继承下一级的设置。即列上面没有指定COLLATE
,则该列的COLLATE
和表上设置的一样。
调整规范
库级别设置
COLLATE
CREATE DATABASE <db_name> DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
注意:通常情况这里由数据库工具统一设置,需要注意的是外部第三方应用或手动创建库时要按规范调整。
表与字段级别不设置
COLLATE
CREATE TABLE ( `field1` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '', …… ) ENGINE=InnoDB COMMENT=''
字段不设置 CHARACTER SET xxx COLLATE xxx
表不设置 CHARACTER SET xxx DEFAULT CHARSET=xxx COLLATE=xxx
另外表默认 ROW_FORMAT 就是 DYNAMIC, 也把 ROW_FORMAT=DYNAMIC 去掉