背景

在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;

如果库级别没有设置CHARSETCOLLATE,则库级别默认的CHARSETCOLLATE使用实例级别的设置。
mysql8.0以下版本中,你如果什么都不修改,默认的CHARSETLatin1,默认的COLLATElatin1_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;

如果表级别没有设置CHARSETCOLLATE,则表级别会继承库级别的CHARSETCOLLATE
列级别的设置,则在CREATE TABLE中声明列的时候指定,例如

CREATE TABLE (
  `field1` VARCHAR64CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
  ……
) ……

如果列级别没有设置CHARSETCOLATE,则列级别会继承表级别的CHARSETCOLLATE

最后,你也可以在写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` VARCHAR64NOT 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 去掉

文档更新时间: 2024-03-25 11:24   作者:姚连洲