第10章字符集,排序规则,Unicode

目录

10.1一般的字符集和排序规则
10.2 MySQL中的字符集和排序规则
10.2.1字符集保留节目
10.2.2元数据的UTF-8
10.3指定字符集和排序规则
10.3.1归类命名约定
10.3.2服务器字符集和校对
10.3.3数据库字符集和校对
10.3.4表字符集和校对
10.3.5列字符集和校对
10.3.6字符串文字字符集和校对
10.3.7国家字符集
10.3.8字符集介绍人
10.3.9字符集和校对分配示例
10.3.10与其他DBMS的兼容性
10.4连接字符集和排序规则
10.5配置应用程序字符集和排序规则
10.6错误消息字符集
10.7列字符集转换
10.8整理问题
10.8.1在SQL语句中使用COLLATE
10.8.2 COLLATE子句优先顺序
10.8.3字符集和校对兼容性
10.8.4表达式中的整理强制性
10.8.5二进制排序与_bin排序相比
10.8.6整理效果的例子
10.8.7在INFORMATION_SCHEMA搜索中使用排序规则
10.9 Unicode支持
10.9.1 utf8mb4字符集(4字节UTF-8 Unicode编码)
10.9.2 utf8mb3字符集(3字节UTF-8 Unicode编码)
10.9.3 utf8字符集(utf8mb3的别名)
10.9.4 ucs2字符集(UCS-2 Unicode编码)
10.9.5 utf16字符集(UTF-16 Unicode编码)
10.9.6 utf16le字符集(UTF-16LE Unicode编码)
10.9.7 utf32字符集(UTF-32 Unicode编码)
10.9.8在3字节和4字节Unicode字符集之间进行转换
10.10支持的字符集和排序规则
10.10.1 Unicode字符集
10.10.2西欧字符集
10.10.3中欧字符集
10.10.4南欧和中东字符集
10.10.5波罗的海字符集
10.10.6西里尔字符集
10.10.7亚洲字符集
10.10.8二进制字符集
10.11设置错误消息语言
10.12添加字符集
10.12.1字符定义数组
10.12.2复杂字符集的字符串整理支持
10.12.3复杂字符集的多字节字符支持
10.13为字符集添加排序规则
10.13.1归类实施类型
10.13.2选择归类ID
10.13.3将简单排序规则添加到8位字符集
10.13.4将UCA归类添加到Unicode字符集
10.14字符集配置
10.15 MySQL服务器区域设置支持

MySQL包括字符集支持,使您可以使用各种字符集存储数据,并根据各种排序规则进行比较。 您可以在服务器,数据库,表和列级别指定字符集。

本章讨论以下主题:

字符集问题不仅影响数据存储,还影响客户端程序和MySQL服务器之间的通信。 如果您希望客户端程序使用与默认字符集不同的字符集与服务器通信,则需要指明哪一个。 例如,要使用 utf8 Unicode字符集,请在连接到服务器后发出以下语句:

SET NAMES'utf8';

有关在客户端/服务器通信中 配置应用 程序使用的字符集和与字符集相关的问题的更多信息,请参见 第10.5节“配置应用程序字符集和排序规则” 第10.4节“连接字符集和排序规则”

10.1一般的字符集和排序规则

字符集 是一组符号和编码。 归类 为在一个字符集的字符进行比较的一组规则。 让我们用虚构字符集的例子来区分清楚。

假设我们有四个字母的字母表: A B a b 我们给每个字母的数: A = 0, B = 1, a = 2, b = 3信 A 是一个符号,数字0是 编码 A ,并且所有四个字母和它们的编码的组合是一个 字符集

假设我们要比较两个字符串值, A 并且 B 最简单的方法是查看编码:0表示 A 和1表示 编码 B 因为0小于1,我们说 A 小于 B 我们刚刚完成的是对我们的字符集应用排序规则。 排序规则是一组规则(在这种情况下只有一个规则): 比较编码。 我们将所有可能的归类中最简单的称为 二进制 排序规则。

但是如果我们想说小写和大写字母是等价的呢? 然后我们将至少有两个规则:(1)处理小写字母 a b 等同于 A B ; (2)然后比较编码。 我们称之为 不区分大小写的 排序规则。 它比二进制校对稍微复杂一点。

在现实生活中,大多数字符集有许多字符:不仅仅是 A B ,但整个字母,有时多个字母或数千个字符的东部书写系统,具有许多特殊符号和标点符号一起。 同样在现实生活中,大多数排序都有很多规则,不仅仅是为了区分字母,还要区分是否区分重音( 重音 是附加到字符的标记,如德语 Ö ),以及多字符映射(如该规则 Ö = OE 在两个德国归类之一)。

MySQL可以为您做这些事情:

  • 使用各种字符集存储字符串。

  • 使用各种排序规则比较字符串。

  • 在同一服务器,同一数据库甚至同一个表中混合使用不同字符集或排序规则的字符串。

  • 在任何级别启用字符集和排序规范。

要有效地使用这些功能,您必须知道可用的字符集和排序规则,如何更改默认值以及它们如何影响字符串运算符和函数的行为。

10.2 MySQL中的字符集和排序规则

MySQL Server支持多种字符集,包括多个Unicode字符集。 要显示可用的字符集,请使用 INFORMATION_SCHEMA CHARACTER_SETS 表或 SHOW CHARACTER SET 语句。 部分列表如下。 有关更完整的信息,请参见 第10.10节“支持的字符集和排序”

MySQL的> SHOW CHARACTER SET;
+ ---------- + --------------------------------- + ---- ----------------- + -------- +
| Charset | 说明| 默认排序规则| Maxlen |
+ ---------- + --------------------------------- + ---- ----------------- + -------- +
| big5 | Big5繁体中文| big5_chinese_ci | 2 |
| 二进制| 二进制伪字符集| 二进制| 1 |
...
| 拉丁1 | cp1252西欧| latin1_swedish_ci | 1 |
...
| ucs2 | UCS-2 Unicode | ucs2_general_ci | 2 |
...
| utf8 | UTF-8 Unicode | utf8_general_ci | 3 |
| utf8mb4 | UTF-8 Unicode | utf8mb4_0900_ai_ci | 4 |
...

默认情况下,该 SHOW CHARACTER SET 语句显示所有可用的字符集。 它需要一个可选的 LIKE WHERE 子句来指示要匹配的字符集名称。 以下示例显示了一些Unicode字符集(基于Unicode转换格式的字符集):

MySQL的> SHOW CHARACTER SET LIKE 'utf%';
+ --------- + ------------------ + -------------------- + -------- +
| Charset | 说明| 默认排序规则| Maxlen |
+ --------- + ------------------ + -------------------- + -------- +
| utf16 | UTF-16 Unicode | utf16_general_ci | 4 |
| utf16le | UTF-16LE Unicode | utf16le_general_ci | 4 |
| utf32 | UTF-32 Unicode | utf32_general_ci | 4 |
| utf8 | UTF-8 Unicode | utf8_general_ci | 3 |
| utf8mb4 | UTF-8 Unicode | utf8mb4_0900_ai_ci | 4 |
+ --------- + ------------------ + -------------------- + -------- +

给定的字符集始终至少有一个排序规则,大多数字符集都有几个排序规则。 要列出字符集的显示排序规则,请使用 INFORMATION_SCHEMA COLLATIONS 表或 SHOW COLLATION 语句。

默认情况下,该 SHOW COLLATION 语句显示所有可用的排序规则。 它需要一个可选的 LIKE WHERE 子句来指示要显示的归类名称。 例如,要查看默认字符集的排序规则 utf8mb4 ,请使用以下语句:

MySQL的> SHOW COLLATION WHERE Charset = 'utf8mb4';
+ ---------------------------- + --------- + ----- + ---- ----- + ---------- + --------- + --------------- +
| 整理| Charset | Id | 默认| 编译| Sortlen | Pad_attribute |
+ ---------------------------- + --------- + ----- + ---- ----- + ---------- + --------- + --------------- +
| utf8mb4_0900_ai_ci | utf8mb4 | 255 | 是的| 是的| 0 | 没有PAD |
| utf8mb4_0900_as_ci | utf8mb4 | 305 | | 是的| 0 | 没有PAD |
| utf8mb4_0900_as_cs | utf8mb4 | 278 | | 是的| 0 | 没有PAD |
| utf8mb4_0900_bin | utf8mb4 | 309 | | 是的| 1 | 没有PAD |
| utf8mb4_bin | utf8mb4 | 46 | | 是的| 1 | PAD SPACE |
| utf8mb4_croatian_ci | utf8mb4 | 245 | | 是的| 8 | PAD SPACE |
| utf8mb4_cs_0900_ai_ci | utf8mb4 | 266 | | 是的| 0 | 没有PAD |
| utf8mb4_cs_0900_as_cs | utf8mb4 | 289 | | 是的| 0 | 没有PAD |
| utf8mb4_czech_ci | utf8mb4 | 234 | | 是的| 8 | PAD SPACE |
| utf8mb4_danish_ci | utf8mb4 | 235 | | 是的| 8 | PAD SPACE |
| utf8mb4_da_0900_ai_ci | utf8mb4 | 267 | | 是的| 0 | 没有PAD |
| utf8mb4_da_0900_as_cs | utf8mb4 | 290 | | 是的| 0 | 没有PAD |
| utf8mb4_de_pb_0900_ai_ci | utf8mb4 | 256 | | 是的| 0 | 没有PAD |
| utf8mb4_de_pb_0900_as_cs | utf8mb4 | 279 | | 是的| 0 | 没有PAD |
| utf8mb4_eo_0900_ai_ci | utf8mb4 | 273 | | 是的| 0 | 没有PAD |
| utf8mb4_eo_0900_as_cs | utf8mb4 | 296 | | 是的| 0 | 没有PAD |
| utf8mb4_esperanto_ci | utf8mb4 | 241 | | 是的| 8 | PAD SPACE |
| utf8mb4_estonian_ci | utf8mb4 | 230 | | 是的| 8 | PAD SPACE |
| utf8mb4_es_0900_ai_ci | utf8mb4 | 263 | | 是的| 0 | 没有PAD |
| utf8mb4_es_0900_as_cs | utf8mb4 | 286 | | 是的| 0 | 没有PAD |
| utf8mb4_es_trad_0900_ai_ci | utf8mb4 | 270 | | 是的| 0 | 没有PAD |
| utf8mb4_es_trad_0900_as_cs | utf8mb4 | 293 | | 是的| 0 | 没有PAD |
| utf8mb4_et_0900_ai_ci | utf8mb4 | 262 | | 是的| 0 | 没有PAD |
| utf8mb4_et_0900_as_cs | utf8mb4 | 285 | | 是的| 0 | 没有PAD |
| utf8mb4_general_ci | utf8mb4 | 45 | | 是的| 1 | PAD SPACE |
| utf8mb4_german2_ci | utf8mb4 | 244 | | 是的| 8 | PAD SPACE |
| utf8mb4_hr_0900_ai_ci | utf8mb4 | 275 | | 是的| 0 | 没有PAD |
| utf8mb4_hr_0900_as_cs | utf8mb4 | 298 | | 是的| 0 | 没有PAD |
| utf8mb4_hungarian_ci | utf8mb4 | 242 | | 是的| 8 | PAD SPACE |
| utf8mb4_hu_0900_ai_ci | utf8mb4 | 274 | | 是的| 0 | 没有PAD |
| utf8mb4_hu_0900_as_cs | utf8mb4 | 297 | | 是的| 0 | 没有PAD |
| utf8mb4_icelandic_ci | utf8mb4 | 225 | | 是的| 8 | PAD SPACE |
| utf8mb4_is_0900_ai_ci | utf8mb4 | 257 | | 是的| 0 | 没有PAD |
| utf8mb4_is_0900_as_cs | utf8mb4 | 280 | | 是的| 0 | 没有PAD |
| utf8mb4_ja_0900_as_cs | utf8mb4 | 303 | | 是的| 0 | 没有PAD |
| utf8mb4_ja_0900_as_cs_ks | utf8mb4 | 304 | | 是的| 24 | 没有PAD |
| utf8mb4_latvian_ci | utf8mb4 | 226 | | 是的| 8 | PAD SPACE |
| utf8mb4_la_0900_ai_ci | utf8mb4 | 271 | | 是的| 0 | 没有PAD |
| utf8mb4_la_0900_as_cs | utf8mb4 | 294 | | 是的| 0 | 没有PAD |
| utf8mb4_lithuanian_ci | utf8mb4 | 236 | | 是的| 8 | PAD SPACE |
| utf8mb4_lt_0900_ai_ci | utf8mb4 | 268 | | 是的| 0 | 没有PAD |
| utf8mb4_lt_0900_as_cs | utf8mb4 | 291 | | 是的| 0 | 没有PAD |
| utf8mb4_lv_0900_ai_ci | utf8mb4 | 258 | | 是的| 0 | 没有PAD |
| utf8mb4_lv_0900_as_cs | utf8mb4 | 281 | | 是的| 0 | 没有PAD |
| utf8mb4_persian_ci | utf8mb4 | 240 | | 是的| 8 | PAD SPACE |
| utf8mb4_pl_0900_ai_ci | utf8mb4 | 261 | | 是的| 0 | 没有PAD |
| utf8mb4_pl_0900_as_cs | utf8mb4 | 284 | | 是的| 0 | 没有PAD |
| utf8mb4_polish_ci | utf8mb4 | 229 | | 是的| 8 | PAD SPACE |
| utf8mb4_romanian_ci | utf8mb4 | 227 | | 是的| 8 | PAD SPACE |
| utf8mb4_roman_ci | utf8mb4 | 239 | | 是的| 8 | PAD SPACE |
| utf8mb4_ro_0900_ai_ci | utf8mb4 | 259 | | 是的| 0 | 没有PAD |
| utf8mb4_ro_0900_as_cs | utf8mb4 | 282 | | 是的| 0 | 没有PAD |
| utf8mb4_ru_0900_ai_ci | utf8mb4 | 306 | | 是的| 0 | 没有PAD |
| utf8mb4_ru_0900_as_cs | utf8mb4 | 307 | | 是的| 0 | 没有PAD |
| utf8mb4_sinhala_ci | utf8mb4 | 243 | | 是的| 8 | PAD SPACE |
| utf8mb4_sk_0900_ai_ci | utf8mb4 | 269 | | 是的| 0 | 没有PAD |
| utf8mb4_sk_0900_as_cs | utf8mb4 | 292 | | 是的| 0 | 没有PAD |
| utf8mb4_slovak_ci | utf8mb4 | 237 | | 是的| 8 | PAD SPACE |
| utf8mb4_slovenian_ci | utf8mb4 | 228 | | 是的| 8 | PAD SPACE |
| utf8mb4_sl_0900_ai_ci | utf8mb4 | 260 | | 是的| 0 | 没有PAD |
| utf8mb4_sl_0900_as_cs | utf8mb4 | 283 | | 是的| 0 | 没有PAD |
| utf8mb4_spanish2_ci | utf8mb4 | 238 | | 是的| 8 | PAD SPACE |
| utf8mb4_spanish_ci | utf8mb4 | 231 | | 是的| 8 | PAD SPACE |
| utf8mb4_sv_0900_ai_ci | utf8mb4 | 264 | | 是的| 0 | 没有PAD |
| utf8mb4_sv_0900_as_cs | utf8mb4 | 287 | | 是的| 0 | 没有PAD |
| utf8mb4_swedish_ci | utf8mb4 | 232 | | 是的| 8 | PAD SPACE |
| utf8mb4_tr_0900_ai_ci | utf8mb4 | 265 | | 是的| 0 | 没有PAD |
| utf8mb4_tr_0900_as_cs | utf8mb4 | 288 | | 是的| 0 | 没有PAD |
| utf8mb4_turkish_ci | utf8mb4 | 233 | | 是的| 8 | PAD SPACE |
| utf8mb4_unicode_520_ci | utf8mb4 | 246 | | 是的| 8 | PAD SPACE |
| utf8mb4_unicode_ci | utf8mb4 | 224 | | 是的| 8 | PAD SPACE |
| utf8mb4_vietnamese_ci | utf8mb4 | 247 | | 是的| 8 | PAD SPACE |
| utf8mb4_vi_0900_ai_ci | utf8mb4 | 277 | | 是的| 0 | 没有PAD |
| utf8mb4_vi_0900_as_cs | utf8mb4 | 300 | | 是的| 0 | 没有PAD |
| utf8mb4_zh_0900_as_cs | utf8mb4 | 308 | | 是的| 0 | 没有PAD |
+ ---------------------------- + --------- + ----- + ---- ----- + ---------- + --------- + --------------- +

有关这些归类的更多信息,请参见 第10.10.1节“Unicode字符集”

整理具有以下一般特征:

  • 两个不同的字符集不能具有相同的排序规则。

  • 每个字符集都有一个 默认排序规则 例如,对于默认排序规则 utf8mb4 latin1 utf8mb4_0900_ai_ci latin1_swedish_ci 分别。 INFORMATION_SCHEMA CHARACTER_SETS 表和 SHOW CHARACTER SET 声明表示每个字符集的默认排序规则。 INFORMATION_SCHEMA COLLATIONS 表和 SHOW COLLATION 语句中有一栏表示对每个比无论是它的字符集的默认( Yes 如果是的话,空如果不是)。

  • 排序规则名称以与其关联的字符集的名称开头,通常后跟一个或多个后缀,指示其他排序规则特征。 有关命名约定的其他信息,请参见 第10.3.1节“排序规则约定”

当字符集具有多个排序规则时,可能不清楚哪种排序规则最适合给定的应用程序。 为避免选择不适当的排序规则,请对代表性数据值进行一些比较,以确保给定的排序规则按预期方式对值进行排序。

10.2.1字符集保留节目

字符集 所有组成 部分是集合中的字符集合。

字符串表达式有一个repertoire属性,它可以有两个值:

  • ASCII :表达式可以包含以Unicode范围中的字符 U+0000 U+007F

  • UNICODE :表达式可以包含以Unicode字符范围 U+0000 U+10FFFF 这包括基本多语言平面(BMP)范围( U+0000 to U+FFFF )中的字符和BMP范围( U+10000 to U+10FFFF 之外的补充字符

ASCII 范围的一个子集 UNICODE 范围内,所以用一个字符串 ASCII 剧目可以安全地没有信息的字符集与任何串的损失被转换 UNICODE 库或为一个字符集是一个超集 ASCII ASCII 除了 swe7 瑞典重音字符 之外, 所有MySQL字符集都是超集 ,它重用了一些标点字符。)在许多情况下,使用repertoire可以在表达式中进行字符集转换,否则MySQL将返回 非法混合排序 错误。

以下讨论提供了表达式及其曲目的示例,并描述了曲目的使用如何更改字符串表达式评估:

  • 字符串常量的所有组成部分取决于字符串内容,并且可能与字符串字符集的所有组成部分不同。 请考虑以下陈述:

    SET NAMES utf8; SELECT'abc';
    SELECT _utf8'def';
    SELECT N'MySQL';
    

    虽然字符集是 utf8 在上述各情况下,琴弦实际上并不包含ASCII范围之外的任何字符,所以他们的剧目 ASCII ,而不是 UNICODE

  • 具有 ascii 字符集的 列由于其 字符集而具有 ASCII 所有组成部分。 在下表中, c1 ASCII 保留曲目:

    CREATE TABLE t1(c1 CHAR(1)CHARACTER SET ascii);
    

    以下示例说明了在没有保留曲目的情况下发生错误的情况下,repertoire如何确定结果:

    CREATE TABLE t1(
      c1 CHAR(1)CHARACTER SET latin1,
      c2 CHAR(1)字符集ascii
    );
    插入t1 VALUES('a','b');
    SELECT CONCAT(c1,c2)FROM t1;
    

    没有保留曲目,会发生以下错误:

    ERROR 1267(HY000):非法混合排序(latin1_swedish_ci,IMPLICIT)
    和(ascii_general_ci,IMPLICIT)用于操作'concat'
    

    使用保留节点, 可以发生 子集到超集( ascii latin1 )转换并返回结果:

    + --------------- +
    | CONCAT(c1,c2)|
    + --------------- +
    | ab |
    + --------------- +
    
  • 具有一个字符串参数的函数继承其参数的所有组成部分。 由于其论点具有 曲目 ,因此 具有 曲目 的结果 UPPER(_utf8'abc') ASCII ASCII

  • 对于返回一个字符串,但没有字符串参数和使用功能 character_set_connection 作为结果的字符集,结果曲目 ASCII ,如果 character_set_connection ascii ,和 UNICODE 以其他方式:

    格式(numeric_column,4);
    

    使用repertoire会改变MySQL如何评估以下示例:

    SET NAMES ascii;
    CREATE TABLE t1(INT,b VARCHAR(10)CHARACTER SET latin1);
    插入t1值(1,'b');
    SELECT CONCAT(FORMAT(a,4),b)FROM t1;
    

    没有保留曲目,会发生以下错误:

    ERROR 1267(HY000):非法混合排序(ascii_general_ci,COERCIBLE)
    和(latin1_swedish_ci,IMPLICIT)操作'concat'
    

    使用保留曲目,返回结果:

    + ------------------------- +
    | CONCAT(格式(a,4),b)|
    + ------------------------- +
    | 1.0000b |
    + ------------------------- +
    
  • 具有两个或多个字符串参数的 函数对结果库 使用 最宽 ”的 参数库( UNICODE 宽度大于 ASCII )。 请考虑以下 CONCAT() 呼叫:

    CONCAT(_ucs2 X'0041',_ uss2 X'0042')
    CONCAT(_ucs2 X'0041',_ uss2 X'00C2')
    

    对于第一次调用,该曲目是 ASCII 因为两个参数都在 ascii 字符集 的范围内 对于第二次调用,该曲目是 UNICODE 因为第二个参数在 ascii 字符集范围之外。

  • 函数返回值的所有组成部分仅基于影响结果字符集和排序规则的参数的所有组成部分来确定。

    IF(column1 <column2,'small','greater')
    

    结果曲目是 ASCII 因为两个字符串参数(第二个参数和第三个参数)都有 ASCII 曲目。 即使表达式使用字符串值,第一个参数对结果库也无关紧要。

10.2.2元数据的UTF-8

元数据 有关数据的数据。 任何 描述 数据库的 东西 - 而不是数据库的 内容 - 都是元数据。 因此,列名,数据库名,用户名,版本名称和大多数字符串结果 SHOW 都是元数据。 对于表的内容也是如此, INFORMATION_SCHEMA 因为这些表按定义包含有关数据库对象的信息。

元数据的表示必须满足以下要求:

  • 所有元数据必须位于同一字符集中。 否则, SHOW 语句和 SELECT 语句 不能 INFORMATION_SCHEMA 正常工作,因为这些操作的结果的同一列中的不同行将在不同的字符集中。

  • 元数据必须包含所有语言中的所有字符。 否则,用户将无法使用自己的语言命名列和表。

为了满足这两个要求,MySQL将元数据存储在Unicode字符集中,即UTF-8。 如果您从不使用重音或非拉丁字符,这不会造成任何中断。 但是如果你这样做,你应该知道元数据是UTF-8。

元数据的要求意味着的返回值 USER() CURRENT_USER() SESSION_USER() SYSTEM_USER() DATABASE() ,和 VERSION() 功能有UTF-8字符的默认设置。

服务器将 character_set_system 系统变量设置为元数据字符集的名称:

MySQL的> SHOW VARIABLES LIKE 'character_set_system';
+ ---------------------- + ------- +
| Variable_name | 价值|
+ ---------------------- + ------- +
| character_set_system | utf8 |
+ ---------------------- + ------- +

使用Unicode存储元数据 并不 意味着服务器 默认 返回列的标题和 字符集中 DESCRIBE 函数 结果 character_set_system 使用时 SELECT column1 FROM t ,名称 column1 本身从服务器返回到由 character_set_results 系统变量 值确定的字符集中的客户端,该 变量的默认值为 utf8mb4 如果希望服务器以不同的字符集传回元数据结果,请使用该 SET NAMES 语句强制服务器执行字符集转换。 SET NAMES 设置 character_set_results 和其他相关的系统变量。 (看到 第10.4节“连接字符集和排序” 。)或者,客户端程序可以在从服务器接收结果后执行转换。 客户端执行转换的效率更高,但并非所有客户端都可以使用此选项。

如果 character_set_results 设置为 NULL ,则不执行任何转换,并且服务器使用其原始字符集(指示的集合 character_set_system 返回元数据

从服务器返回到客户端的错误消息将自动转换为客户端字符集,与元数据一样。

如果您 USER() 在单个语句 中使用(例如) 函数进行比较或赋值,请不要担心。 MySQL为您执行一些自动转换。

SELECT * FROM t1 WHERE USER()= latin1_column;

这是有效的,因为 latin1_column 在比较之前 内容 会自动转换为UTF-8。

INSERT INTO t1(latin1_column)SELECT USER();

这是有效的,因为内容 在分配之前 USER() 自动转换为 latin1

虽然自动转换不在SQL标准中,但标准确实说每个字符集(就支持的字符而言)是 Unicode 子集 因为一个众所周知的原则是 适用于超集的内容可以应用于子集 ”, 我们认为Unicode的排序规则可以应用于与非Unicode字符串的比较。 有关字符串强制的更多信息,请参见 第10.8.4节“表达式中的校对强制性”

10.3指定字符集和排序规则

字符集和排序规则的默认设置分为四个级别:服务器,数据库,表和列。 以下部分中的描述可能看起来很复杂,但实践中发现多级默认会导致自然而明显的结果。

CHARACTER SET 用于指定字符集的子句。 CHARSET 可以用作的同义词 CHARACTER SET

字符集问题不仅影响数据存储,还影响客户端程序和MySQL服务器之间的通信。 如果您希望客户端程序使用与默认字符集不同的字符集与服务器通信,则需要指明哪一个。 例如,要使用 utf8mb4 Unicode字符集,请在连接到服务器后发出以下语句:

SET NAMES'utf8mb4';

有关客户端/服务器通信中与字符集相关的问题的更多信息,请参见 第10.4节“连接字符集和排序”

10.3.1归类命名约定

MySQL排序规则名称遵循以下约定:

  • 排序规则名称以与其关联的字符集的名称开头,通常后跟一个或多个后缀,指示其他排序规则特征。 例如, utf8mb4_general_ci 并且 latin1_swedish_ci 是用于排序规则 utf8mb4 latin1 分别字符集,。 binary 字符集有一个单一的整理,也叫 binary ,没有后缀。

  • 特定于语言的排序规则包括区域设置代码或语言名称。 例如, utf8mb4_tr_0900_ai_ci utf8mb4_hu_0900_ai_ci 排序为人物 utf8mb4 使用土耳其和匈牙利的规则,分别字符集。 utf8mb4_turkish_ci 并且 utf8mb4_hungarian_ci 类似,但基于较新版本的Unicode校对算法。

  • 排序后缀表示排序规则是大小写还是重音敏感或二进制。 下表显示了用于指示这些特征的后缀。

    表10.1校对案例/重音敏感度后缀

    后缀 含义
    _ai 口音不敏感
    _as 口音敏感
    _ci 不区分大小写
    _cs 区分大小写
    _ks 假名敏感
    _bin 二进制

    对于未指定重音敏感度的非二进制校对名称,它由大小写敏感性决定。 如果归类名不包含 _ai 或者 _as _ci 在其名称所暗示 _ai ,并 _cs 在其名称所暗示 _as 例如, latin1_general_ci 明确区分大小写且隐式重音不敏感, latin1_general_cs 明确区分大小写且隐式重音敏感,并且 utf8mb4_0900_ai_ci 明确区分大小写和重音不敏感。

    对于日语排序规则, _ks 后缀表示排序规则是假名敏感的; 也就是说,它将片假名字符与平假名字符区分开来。 没有 _ks 后缀的 日语校对 不是假名敏感的,并且将片假名和平假名字符等同于排序。

    对于 字符集 binary 整理 binary ,比较基于数字字节值。 对于 _bin 非二进制字符集 排序规则,比较基于数字字符代码值,这些值与多字节字符的字节值不同。 有关更多信息,请参见 第10.8.5节“二进制排序与_bin排序相比”

  • 对于Unicode字符集,排序规则名称可能包含版本号,以指示排序规则所基于的Unicode排序规则算法(UCA)的版本。 名称中没有版本号的基于UCA的排序规则使用版本-4.0.0 UCA权重键。 例如:

  • 对于Unicode字符集, xxx_general_mysql500_ci 排序规则保留了原始 xxx_general_ci 排序规则的5.1.24之前的排序,并允许在MySQL 5.1.24之前创建的表(Bug#27877)进行升级。

10.3.2服务器字符集和校对

MySQL Server具有服务器字符集和服务器排序规则。 这些可以在命令行或选项文件中的服务器启动时设置,并在运行时更改。

最初,服务器字符集和排序规则取决于启动 mysqld 时使用的选项 您可以使用 --character-set-server 字符集。 除此之外,您还可以添加 --collation-server 排序规则。 如果您没有指定字符集,那就与说法相同 --character-set-server=utf8mb4 如果仅指定字符集(例如 utf8mb4 )但不指定排序规则,则与说明相同, 因为 它是默认排序规则 因此,以下三个命令都具有相同的效果: --character-set-server=utf8mb4 --collation-server=utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci utf8mb4

mysqld的
mysqld --character-set-server = utf8mb4
mysqld --character-set-server = utf8mb4 \
  --collat​​ion服务器= utf8mb4_0900_ai_ci

更改设置的一种方法是重新编译。 要在从源构建时更改默认服务器字符集和排序规则,请使用 CMake DEFAULT_CHARSET DEFAULT_COLLATION 选项 例如:

cmake。-DDEFAULT_CHARSET = LATIN1

要么:

cmake。-DDEFAULT_CHARSET = latin1 \
  -DDEFAULT_COLLATION = latin1_german1_ci

双方 的mysqld CMake的 验证字符集/归类组合是有效的。 如果没有,每个程序都会显示一条错误消息并终止。

如果未在 CREATE DATABASE 语句中 指定数据库字符集和排序规则,则将服务器字符集和排序规则用作默认值 他们没有其他目的。

可以根据 系统变量 character_set_server collation_server 系统变量 的值来确定当前服务器字符集和排序规则 这些变量可以在运行时更改。

10.3.3数据库字符集和校对

每个数据库都有一个数据库字符集和一个数据库排序规则。 CREATE DATABASE ALTER DATABASE 语句有用于指定数据库字符集和校对可选条款:

创建数据库db_name
    [[默认]字符集charset_name]
    [[DEFAULT] COLLATE collation_name]

ALTER DATABASE db_name
    [[DEFAULT] CHARACTER SET charset_name]
    [[DEFAULT] COLLATE collation_name]

SCHEMA 可以使用 关键字 代替 DATABASE

CHARACTER SET COLLATE 条款使其能够创建具有不同的字符集和归类同一台MySQL服务器上的数据库。

数据库选项存储在数据字典中,可以通过检查 INFORMATION_SCHEMA.SCHEMATA 来检查

例:

创建数据库db_name字符集latin1 COLLATE latin1_swedish_ci;

MySQL以下列方式选择数据库字符集和数据库排序规则:

  • 如果同时 指定 则使用 字符集 和排序规则 CHARACTER SET charset_name COLLATE collation_name charset_name collation_name

  • 如果 未指定 则使用 字符集 及其默认排序规则。 要查看每个字符集的默认排序规则,请使用该 语句或查询该 表。 CHARACTER SET charset_name COLLATE charset_name SHOW CHARACTER SET INFORMATION_SCHEMA CHARACTER_SETS

  • 如果 未指定 ,则使用 与collat​​ion 关联的字符集 COLLATE collation_name CHARACTER SET collation_name collation_name

  • 否则(既未 指定 CHARACTER SET COLLATE 指定),使用服务器字符集和服务器排序规则。

可以根据 系统变量 character_set_database collation_database 系统变量 的值确定默认数据库的字符集和排序规则 每当默认数据库更改时,服务器都会设置这些变量 如果没有默认数据库,则变量与相应的服务器级系统变量具有相同的值, character_set_server 并且 collation_server

要查看给定数据库的缺省字符集和排序规则,请使用以下语句:

使用db_name;
SELECT @@ character_set_database,@@ collat​​ion_database;

或者,要在不更改默认数据库的情况下显示值:

SELECT DEFAULT_CHARACTER_SET_NAME,DEFAULT_COLLATION_NAME
FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME =' db_name';

数据库字符集和排序规则会影响服务器操作的这些方面:

  • 对于 CREATE TABLE 语句,如果未指定表字符集和排序规则,则数据库字符集和排序规则将用作表定义的缺省值。 要覆盖它,请提供显式 CHARACTER SET COLLATE 表选项。

  • 对于 LOAD DATA 不包含 CHARACTER SET 子句的语句,服务器使用 character_set_database 系统变量 指示的字符集 来解释文件中的信息。 要覆盖它,请提供显式 CHARACTER SET 子句。

  • 对于存储的例程(过程和函数),在例程创建时有效的数据库字符集和排序规则用作声明包含no CHARACTER SET COLLATE 属性 的字符数据参数的字符集和排序规则 要覆盖此,提供 CHARACTER SET COLLATE 明确。

10.3.4表字符集和校对

每个表都有一个表字符集和一个表格排序规则。 CREATE TABLE ALTER TABLE 语句对指定表字符集和校对可选条款:

CREATE TABLE tbl_namecolumn_list
    [[DEFAULT] CHARACTER SET charset_name]
    [收集collation_name]]

ALTER TABLE tbl_name
    [[DEFAULT] CHARACTER SET charset_name]
    [收集collation_name]

例:

CREATE TABLE t1(...)
字符集latin1 COLLATE latin1_danish_ci;

MySQL以下列方式选择表字符集和排序规则:

  • 如果同时 指定 则使用 字符集 和排序规则 CHARACTER SET charset_name COLLATE collation_name charset_name collation_name

  • 如果 未指定 则使用 字符集 及其默认排序规则。 要查看每个字符集的默认排序规则,请使用该 语句或查询该 表。 CHARACTER SET charset_name COLLATE charset_name SHOW CHARACTER SET INFORMATION_SCHEMA CHARACTER_SETS

  • 如果 未指定 ,则使用 与collat​​ion 关联的字符集 COLLATE collation_name CHARACTER SET collation_name collation_name

  • 否则(既未 指定 CHARACTER SET COLLATE 指定),使用数据库字符集和排序规则。

如果未在各个列定义中指定列字符集和排序规则,则表字符集和排序规则将用作列定义的默认值。 表字符集和排序规则是MySQL扩展; 标准SQL中没有这样的东西。

10.3.5列字符集和校对

每个 字符 列(即,类型列 CHAR VARCHAR 中, TEXT 类型,或其任何同义词)具有列字符集和列排序规则。 用于列定义的语法 CREATE TABLE ALTER TABLE 具有用于指定列的字符集和归类可选子句:

col_name{CHAR | VARCHAR | TEXT}(col_length
    [字符集charset_name]
    [收集collation_name]

这些子句也可以用于 ENUM SET 列:

col_name{ENUM | SET}(val_list
    [字符集charset_name]
    [收集collation_name]

例子:

CREATE TABLE t1
    col1 VARCHAR(5)
      字符集拉丁1
      收集latin1_german1_ci
);

更改表t1修改
    col1 VARCHAR(5)
      字符集拉丁1
      COLLATE latin1_swedish_ci;

MySQL以下列方式选择列字符集和排序规则:

  • 如果同时 指定 则使用 字符集 和排序规则 CHARACTER SET charset_name COLLATE collation_name charset_name collation_name

    CREATE TABLE t1
        col1 CHAR(10)CHARACTER SET utf8 COLLATE utf8_unicode_ci
    )CHARACTER SET latin1 COLLATE latin1_bin;
    

    为列指定了字符集和排序规则,因此使用它们。 该列具有字符集 utf8 和排序规则 utf8_unicode_ci

  • 如果 未指定 则使用 字符集 及其默认排序规则。 CHARACTER SET charset_name COLLATE charset_name

    CREATE TABLE t1
        col1 CHAR(10)字符集utf8
    )CHARACTER SET latin1 COLLATE latin1_bin;
    

    为列指定了字符集,但不是排序规则。 该列具有字符集 utf8 和默认排序规则 utf8 ,即 utf8_general_ci 要查看每个字符集的默认排序规则,请使用该 SHOW CHARACTER SET 语句或查询该 INFORMATION_SCHEMA CHARACTER_SETS 表。

  • 如果 未指定 ,则使用 与collat​​ion 关联的字符集 COLLATE collation_name CHARACTER SET collation_name collation_name

    CREATE TABLE t1
        col1 CHAR(10)COLLATE utf8_polish_ci
    )CHARACTER SET latin1 COLLATE latin1_bin;
    

    为列指定了排序规则,但字符集不是。 该列具有排序规则 utf8_polish_ci ,字符集是与排序规则关联的字符集,即 utf8

  • 否则(既未 指定 CHARACTER SET COLLATE 指定),使用表格字符集和排序规则。

    CREATE TABLE t1
        col1 CHAR(10)
    )CHARACTER SET latin1 COLLATE latin1_bin;
    

    没有为列指定字符集和排序规则,因此使用表默认值。 该列具有字符集 latin1 和排序规则 latin1_bin

CHARACTER SET COLLATE 子句是标准的SQL。

如果您使用 ALTER TABLE 将列从一个字符集转换为另一个字符集,MySQL会尝试映射数据值,但如果字符集不兼容,则可能会丢失数据。

10.3.6字符串文字字符集和校对

每个字符串文字都有字符集和排序规则。

对于简单的语句 ,该字符串有连接默认字符集和归类定义 系统变量。 SELECT 'string' character_set_connection collation_connection

字符串文字可以具有可选的字符集介绍人和 COLLATE 子句,以将其指定为使用特定字符集和排序规则的字符串:

[_ charset_name]' string'[收集collation_name]

表达正式称为 引导 它告诉解析器, 后面 的字符串使用字符集 介绍人不会将字符串更改为导入器字符集 它不会更改字符串值,但可能会出现填充。 介绍人只是一个信号。 请参见 第10.3.8节“字符集介绍” _charset_name charset_name CONVERT()

例子:

SELECT'abc';
SELECT _latin1'abc';
SELECT _binary'abc';
SELECT _utf8mb4'abc'COLLATE utf8mb4_danish_ci;

字符集引入器和 COLLATE 子句是根据标准SQL规范实现的。

MySQL以下列方式确定字符串文字的字符集和整理:

  • 如果同时 指定 _charset_name 则使用 字符集 和排序规则 必须是允许的整理 COLLATE collation_name charset_name collation_name collation_name charset_name

  • 如果 _charset_name 已指定但未 COLLATE 指定, charset_name 则使用 字符集 及其默认排序规则。 要查看每个字符集的默认排序规则,请使用该 SHOW CHARACTER SET 语句或查询该 INFORMATION_SCHEMA CHARACTER_SETS 表。

  • 如果 _charset_name 未指定但 指定, 则使用 系统变量和排序规则 给出的连接缺省字符集 必须是连接默认字符集的允许排序规则。 COLLATE collation_name character_set_connection collation_name collation_name

  • 否则(既未 指定 _charset_name 指定),使用由 系统变量 系统变量 给出的连接缺省字符集和排序规则 COLLATE collation_name character_set_connection collation_connection

例子:

  • 具有 latin1 字符集和 latin1_german1_ci 排序规则的 非二进制字符串

    SELECT_latin1'Müller'COLLATElatin1_german1_ci;
    
  • 带有 utf8mb4 字符集的 非二进制字符串 及其默认排序规则(即 utf8mb4_general_ci ):

    SELECT_utf8mb4'Müller';
    
  • binary 字符集的 二进制字符串 及其默认排序规则(即 binary ):

    SELECT_binary'Müller';
    
  • 具有连接缺省字符集和 utf8mb4_general_ci 排序规则 的非二进制字符串 (如果连接字符集不是,则失败 utf8mb4 ):

    SELECT'Müller'COLLATEutf8mb4_general_ci;
    
  • 具有连接默认字符集和排序规则的字符串:

    选择'Müller';
    

介绍人指示以下字符串的字符集,但不会更改解析器在字符串中执行转义处理的方式。 Escape总是由解析器根据给定的字符集解释 character_set_connection

以下示例显示 character_set_connection 即使在导入器存在的情况下 也会发生逃逸处理 这些示例使用 SET NAMES (更改 character_set_connection ,如 第10.4节“连接字符集和排序”中所述 ),并使用该 HEX() 函数 显示结果字符串, 以便可以看到确切的字符串内容。

例1:

mysql> SET NAMES latin1;
mysql>SELECT HEX('à\n'), HEX(_sjis'à\n');
+ ------------ + ----------------- +
| HEX('à\ n')| HEX(_sjis'à\ n')|
+ ------------ + ----------------- +
| E00A | E00A |
+ ------------ + ----------------- +

这里, à (十六进制值 E0 )后跟 \n 换行符的转义序列。 使用 character_set_connection latin1 解释转义序列 以生成文字换行符(十六进制值 0A )。 即使是第二个字符串也会发生这种情 也就是说, _sjis 介绍人不会影响解析器的转义处理。

例2:

mysql> SET NAMES sjis;
mysql>SELECT HEX('à\n'), HEX(_latin1'à\n');
+ ------------ + ------------------- +
| HEX('à\ n')| HEX(_latin1'à\ n')|
+ ------------ + ------------------- +
| E05C6E | E05C6E |
+ ------------ + ------------------- +

这里 character_set_connection sjis 一个字符集,其中 à 后面 的序列 \ (十六进制值 05 5C )是有效的多字节字符。 因此,字符串的前两个字节被解释为单个 sjis 字符,并且 \ 不会被解释为转义字符。 以下 n (十六进制值 6E )不会被解释为转义序列的一部分。 即使对于第二个字符串也是如此; _latin1 引导不影响转义处理。

10.3.7国家字符集

标准SQL定义 NCHAR NATIONAL CHAR 作为指示 CHAR 列应使用某些预定义字符集的方法。 MySQL使用 utf8 此预定义字符集。 例如,这些数据类型声明是等效的:

CHAR(10)CHARACTER SET utf8
国家人物(10)
NCHAR(10)

这些是:

VARCHAR(10)CHARACTER SET utf8
NATIONAL VARCHAR(10)
NVARCHAR(10)
NCHAR VARCHAR(10)
国家角色变化(10)
国家角色变化(10)

您可以使用 (或 )在国家字符集中创建字符串。 这些陈述是等价的: N'literal' n'literal'

SELECT N'some text';
SELECT n'some text';
SELECT _utf8的一些文字';

10.3.8字符集介绍人

字符串文字,十六进制文字或位值文字可以具有可选的字符集介绍人和 COLLATE 子句,以将其指定为使用特定字符集和排序规则的字符串:

[_ charset_name] literal[COLLATE collation_name]

表达正式称为 引导 它告诉解析器, 后面 的字符串使用字符集 介绍人不会将字符串更改为导入器字符集 它不会更改字符串值,但可能会出现填充。 介绍人只是一个信号。 _charset_name charset_name CONVERT()

对于字符串文字,允许介绍者和字符串之间的空格,但是可选。

例子:

SELECT'abc';
SELECT _latin1'abc';
SELECT _binary'abc';
SELECT _utf8mb4'abc'COLLATE utf8mb4_danish_ci;

SELECT _latin1 X'4D7953514C';
SELECT _utf8mb4 0x4D7953514C COLLATE utf8mb4_danish_ci;

SELECT _latin1 b'1000001';
SELECT _utf8mb4 0b1000001 COLLATE utf8mb4_danish_ci;

字符集引入器和 COLLATE 子句是根据标准SQL规范实现的。

可以使用 _binary 介绍人将 字符串文字指定为二进制字符串 默认情况下,十六进制文字和位值文字是二进制字符串,因此 _binary 是允许的,但通常是不必要的。 _binary 可能有用的是将十六进制或位文字保留为上下文中的二进制字符串,否则文字将被视为数字。 例如,位操作允许MySQL 8.0及更高版本中的数字或二进制字符串参数,但默认情况下将十六进制和位文字视为数字。 要为此类文字显式指定二进制字符串上下文 _binary ,请至少使用其中一个参数 介绍人:

mysql> SET @v1 = X'000D' | X'0BC0';
mysql> SET @v2 = _binary X'000D' | X'0BC0';
mysql>SELECT HEX(@v1), HEX(@v2);
+ ---------- + ---------- +
| 十六进制(@ v1)| HEX(@ v2)|
+ ---------- + ---------- +
| BCD | 0BCD |
+ ---------- + ---------- +

所显示的结果,这样对位操作类似,但没有结果 _binary 是一个 BIGINT 值,而将结果与 _binary 一个二进制字符串。 由于结果类型不同,显示的值不同:数字结果不显示高位0位数。

MySQL以下列方式确定字符串文字,十六进制文字或位值文字的字符集和排序规则:

  • 如果同时 指定 _charset_name 则使用 字符集 和排序规则 必须是允许的整理 COLLATE collation_name charset_name collation_name collation_name charset_name

  • 如果 _charset_name 已指定但未 COLLATE 指定, charset_name 则使用 字符集 及其默认排序规则。 要查看每个字符集的默认排序规则,请使用该 SHOW CHARACTER SET 语句或查询该 INFORMATION_SCHEMA CHARACTER_SETS 表。

  • 如果 _charset_name 未指定但 指定了: COLLATE collation_name

    • 对于字符串文字,使用 character_set_connection 系统变量和排序规则 给出的连接默认字符集 collation_name collation_name 必须是连接默认字符集的允许排序规则。

    • 对于十六进制文字或位值文字,唯一允许的排序规则是 binary 因为默认情况下这些类型的文字是二进制字符串。

  • 否则(既未 指定 _charset_name 指定): COLLATE collation_name

    • 对于字符串文字,使用由 系统变量 character_set_connection collation_connection 系统变量 给出的连接缺省字符集和排序规则

    • 对于十六进制文字或位值文字,字符集和整理是 binary

例子:

  • 具有 latin1 字符集和 latin1_german1_ci 排序 规则的非二进制字符串

    SELECT_latin1'Müller'COLLATElatin1_german1_ci;
    SELECT _latin1 X'0A0D'COLLATE latin1_german1_ci;
    SELECT _latin1 b'0110'COLLATE latin1_german1_ci;
    
  • 具有 utf8mb4 字符集的非 二进制字符串 及其默认排序规则(即 utf8mb4_0900_ai_ci ):

    SELECT_utf8mb4'Müller';
    SELECT _utf8mb4 X'0A0D';
    SELECT _utf8mb4 b'0110';
    
  • 具有 binary 字符集的 二进制字符串 及其默认排序规则(即 binary ):

    SELECT_binary'Müller';
    SELECT X'0A0D';
    SELECT b'0110';
    

    十六进制文字和位值文字不需要介绍人,因为默认情况下它们是二进制字符串。

  • 具有连接缺省字符集和 utf8mb4_general_ci 排序规则 的非二进制字符串 (如果连接字符集不是,则失败 utf8mb4 ):

    SELECT'Müller'COLLATEutf8mb4_general_ci;
    

    此结构( COLLATE 仅)不适用于十六进制文字或位文字,因为它们的字符集 binary 无论是连接字符集, binary 都与 utf8mb4_general_ci 排序规则 不兼容 COLLATE 没有介绍人 的唯一允许的 条款是 COLLATE binary

  • 具有连接默认字符集和排序规则的字符串:

    选择'Müller';
    

对于字符集文字,介绍人指示以下字符串的字符集,但不会更改解析器在字符串中执行转义处理的方式。 Escape总是由解析器根据给定的字符集解释 character_set_connection 有关其他讨论和示例,请参见 第10.3.6节“字符串文字字符集和排序规则”

10.3.9字符集和校对分配示例

以下示例显示MySQL如何确定默认字符集和排序规则值。

示例1:表和列定义

CREATE TABLE t1
    c1 CHAR(10)CHARACTER SET latin1 COLLATE latin1_german1_ci
)DEFAULT CHARACTER SET latin2 COLLATE latin2_bin;

这里我们有一个包含 latin1 字符集和 latin1_german1_ci 排序规则的列。 定义是明确的,因此很简单。 请注意, latin1 latin2 表中 存储 没有问题

示例2:表和列定义

CREATE TABLE t1
    c1 CHAR(10)CHARACTER SET latin1
)DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;

这次我们有一个包含 latin1 字符集和默认排序规则的列。 虽然看起来很自然,但默认排序规则不是从表级别获取的。 相反,因为默认排序规则 latin1 始终为 latin1_swedish_ci ,所以列 c1 具有 latin1_swedish_ci (非 latin1_danish_ci 排序规则

示例3:表和列定义

CREATE TABLE t1
    c1 CHAR(10)
)DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;

我们有一个包含默认字符集和默认排序规则的列。 在这种情况下,MySQL检查表级别以确定列字符集和排序规则。 因此,列的字符集 c1 latin1 其排序规则 latin1_danish_ci

示例4:数据库,表和列定义

创建数据库d1
    默认字符集latin2 COLLATE latin2_czech_ci;
使用d1;
CREATE TABLE t1
    c1 CHAR(10)
);

我们创建一个列而不指定其字符集和排序规则。 我们也没有在表级指定字符集和排序规则。 在这种情况下,MySQL会检查数据库级别以确定表设置,然后将其设置为列设置。)因此,列的字符集 c1 latin2 其排序规则 latin2_czech_ci

10.3.10与其他DBMS的兼容性

对于MaxDB兼容性,这两个语句是相同的:

CREATE TABLE t1(f1 CHAR(N)UNICODE);
CREATE TABLE t1(f1 CHAR(N)CHARACTER SET ucs2);

10.4连接字符集和排序规则

一个 连接 是当它连接到服务器,开始在其内与服务器交互会话的客户端程序发出什么。 客户端通过会话连接发送SQL语句,例如查询。 服务器通过连接将响应(例如结果集或错误消息)发送回客户端。

连接字符集和校对系统变量

多个字符集和整理系统变量与客户端与服务器的交互有关。 其中一些已在前面的部分中提到过:

在处理客户端和服务器之间的连接的流量时涉及附加的字符集和校对系统变量。 每个客户端都有特定于会话的连接相关字符集和整理系统变量。 这些会话系统变量值在连接时初始化,但可以在会话中更改。

有关客户端连接的字符集和排序规则处理的几个问题可以通过系统变量来回答:

要查看适用于当前会话的字符集和排序规则系统变量的值,请使用以下语句:

SELECT * FROM performance_schema.session_variables
VARIABLE_NAME IN(
'character_set_client','character_set_connection',
'character_set_results','collat​​ion_connection'
)ORDER BY VARIABLE_NAME;

以下更简单的语句也显示连接变量,但也包括其他相关变量。 它们可用于查看 所有 字符集和整理系统变量:

显示会话变量类似'character \ _set \ _%';
显示会话变量如'collat​​ion \ _%';

客户端可以微调这些变量的设置,或者取决于默认值(在这种情况下,您可以跳过本节的其余部分)。 如果不使用默认值,则必须更改 与服务器的每个连接 的字符设置

不允许的客户端字符集

character_set_client 系统变量不能设置为特定字符集:

UCS2
UTF16
utf16le应按
UTF32

尝试将任何这些字符集用作客户端字符集会产生错误:

MySQL的> SET character_set_client = 'ucs2';
错误1231(42000):变量'character_set_client'
不能设置为'ucs2'的值

如果在以下上下文中使用任何这些字符集,则会发生相同的错误,所有这些都导致尝试设置 character_set_client 为指定的字符集:

客户端程序连接字符集配置

当客户端连接到服务器时,它指示它要用于与服务器通信的字符集。 (实际上,在客户端指示该字符集,从该服务器可确定的字符集的默认排序。)服务器使用该信息来设置 character_set_client character_set_results character_set_connection 系统变量的字符集,并 collation_connection 以字符集默认排序规则。 实际上,服务器执行等效的 SET NAMES 操作。

如果服务器不支持请求的字符集或排序规则,则它将回退到使用服务器字符集和排序规则来配置连接。 有关此回退行为的其他详细信息,请参阅 连接字符集错误处理

MySQL的 中mysqladmin mysqlcheck的 mysqlimport的 ,而 mysqlshow 客户端程序确定默认字符集使用,如下所示:

  • 在没有其他信息的情况下,每个客户端通常使用已编译的默认字符集 utf8mb4

  • 每个客户端都可以根据操作系统设置自动检测要使用的字符集,例如 Unix系统上 LANG LC_ALL locale环境变量 的值 Windows系统上的代码页设置。 对于可从OS获得区域设置的系统,客户端使用它来设置默认字符集,而不是使用编译的默认值。 例如,设置 LANG ru_RU.KOI8-R 使用 koi8r 字符集。 因此,用户可以在其环境中配置语言环境以供MySQL客户端使用。

    如果没有完全匹配,则OS字符集将映射到最接近的MySQL字符集。 如果客户端不支持匹配的字符集,则它使用编译的默认值。 例如, utf8 utf-8 映射到 utf8mb4 ,并且 ucs2 不支持作为连接字符集,因此它映射到编译时的缺省。

    C应用程序可以 mysql_options() 在连接到服务器之前 通过 如下 调用 基于OS设置使用字符集自动检测

    的mysql_options(MySQL的,
                  MYSQL_SET_CHARSET_NAME,
                  MYSQL_AUTODETECT_CHARSET_NAME);
    
  • 每个客户端都支持一个 --default-character-set 选项,该选项允许用户显式指定字符集以覆盖客户端否则确定的任何默认值。

    注意

    某些字符集不能用作客户端字符集。 试图使用它们 --default-character-set 会产生错误。 请参见 不允许的客户端字符集

使用 mysql 客户端,要使用与默认值不同的字符集, SET NAMES 每次连接到服务器时 都可以显式执行 语句(请参阅 客户端程序连接字符集配置 )。 要更轻松地完成相同的结果,请在选项文件中指定字符集。 例如,以下选项文件设置更改 koi8r 每次调用 mysql 设置的三个与连接相关的字符集系统变量

[MySQL的]
默认字符集= koi8r

如果您正在使用 启用了自动重新连接 mysql 客户端(不建议这样做),则最好使用 charset 命令而不是 SET NAMES 例如:

MySQL的> charset koi8r
Charset改变了

charset 命令发出一个 SET NAMES 语句,并且还更改 mysql 在连接断开后重新连接时使用 的默认字符集

配置客户端程序时,还必须考虑它们执行的环境。 请参见 第10.5节“配置应用程序字符集和排序规则”

连接字符集配置的SQL语句

建立连接后,客户端可以更改当前会话的字符集和排序规则系统变量。 可以使用 SET 语句 单独更改这些变量 ,但是两个更方便的语句会将与连接相关的字符集系统变量作为一个组进行影响:

  • SET NAMES 'charset_name' [COLLATE 'collation_name']

    SET NAMES 指示客户端将用于将SQL语句发送到服务器的字符集。 因此, SET NAMES 'cp1251' 告诉服务器, 来自此客户端的未来传入消息是字符集 cp1251 它还指定了服务器用于将结果发送回客户端的字符集。 (例如,如果使用 SELECT 生成结果集 语句 ,它指示要用于列值的字符 集。)

    一个 语句相当于这三个语句: SET NAMES 'charset_name'

    SET character_set_client = charset_name;
    SET character_set_results = charset_name;
    SET character_set_connection = charset_name;
    

    设置 character_set_connection charset_name 也隐式地设置 collation_connection 为默认排序规则 charset_name 没有必要明确设置该排序规则。 要指定要用于的特定排序规则 collation_connection ,请添加 COLLATE 子句:

    设置名称' charset_name'COLLATE' collation_name'
    
  • SET CHARACTER SET 'charset_name

    SET CHARACTER SET 类似于 SET NAMES 但是设置 character_set_connection collation_connection to character_set_database collation_database (如前所述,它表示默认数据库的字符集和排序规则)。

    一个 语句相当于这三个语句: SET CHARACTER SET charset_name

    SET character_set_client = charset_name;
    SET character_set_results = charset_name;
    SET collat​​ion_connection = @@ collat​​ion_database;
    

    设置 collation_connection 也隐式设置 character_set_connection 为与排序规则关联的字符集(相当于执行 SET character_set_connection = @@character_set_database )。 没有必要 character_set_connection 明确 设置

注意

某些字符集不能用作客户端字符集。 试图使用它们 SET NAMES SET CHARACTER SET 产生错误。 请参见 不允许的客户端字符集

示例:假设 column1 定义为 CHAR(5) CHARACTER SET latin2 如果您没有说 SET NAMES SET CHARACTER SET ,那么 SELECT column1 FROM t 服务器会发回所有值,以便 column1 使用客户端连接时指定的字符集。 另一方面,如果您说 SET NAMES 'latin1' SET CHARACTER SET 'latin1' 在发出 SELECT 语句 之前 ,服务器将 latin2 转换 latin1 恰好在发送结果之前。 对于不在两个字符集中的字符,转换可能是有损的。

连接字符集错误处理

尝试使用不适当的连接字符集或排序规则可能会产生错误,或导致服务器回退到其给定连接的默认字符集和排序规则。 本节介绍配置连接字符集时可能出现的问题。 建立连接或更改已建立连接中的字符集时,可能会出现这些问题。

连接时错误处理

某些字符集不能用作客户端字符集; 请参阅 不允许的客户端字符集 如果指定有效但不允许作为客户端字符集的字符集,则服务器将返回错误:

外壳> mysql --default-character-set=ucs2
错误1231(42000):变量'character_set_client'不能设置为
'ucs2'的值

如果指定客户端无法识别的字符集,则会产生错误:

外壳> mysql --default-character-set=bogus
mysql:字符集'bogus'不是编译的字符集而是
未在'/usr/local/mysql/share/charsets/Index.xml'文件中指定
ERROR 2019(HY000):无法初始化字符集伪造
(路径:/ usr / local / mysql / share / charsets /)

如果指定客户端识别但服务器未识别的字符集,则服务器将回退到其默认字符集和排序规则。 假设服务器配置为使用 latin1 latin1_swedish_ci 作为其默认值,并且它不能识别 gb18030 为有效字符集。 指定的客户端 --default-character-set=gb18030 能够连接到服务器,但生成的字符集不是客户端想要的:

MySQL的> SHOW SESSION VARIABLES LIKE 'character\_set\_%';
+ -------------------------- + -------- +
| Variable_name | 价值|
+ -------------------------- + -------- +
| character_set_client | 拉丁1 |
| character_set_connection | 拉丁1 |
...
| character_set_results | 拉丁1 |
...
+ -------------------------- + -------- +
MySQL的> SHOW SESSION VARIABLES LIKE 'collation_connection';
+ ---------------------- + ------------------- +
| Variable_name | 价值|
+ ---------------------- + ------------------- +
| collat​​ion_connection | latin1_swedish_ci |
+ ---------------------- + ------------------- +

你可以看到,连接系统变量已经设置以反映字符集和校对 latin1 latin1_swedish_ci 发生这种情况是因为服务器无法满足客户端字符集请求并回退到其默认值。

在这种情况下,客户端无法使用它想要的字符集,因为服务器不支持它。 客户端必须愿意使用不同的字符集,或者连接到支持所需字符集的其他服务器。

同样的问题出现在更微妙的上下文中:当客户端告诉服务器使用服务器识别的字符集时,但在服务器端不知道客户端上该字符集的默认排序规则。 例如,当MySQL 8.0客户端想要使用 utf8mb4 客户端字符集 连接到MySQL 5.7服务器时,就会发生这种情况 指定的客户端 --default-character-set=utf8mb4 能够连接到服务器。 但是,与前面的示例一样,服务器回退到其默认字符集和排序规则,而不是客户端请求的位置:

MySQL的> SHOW SESSION VARIABLES LIKE 'character\_set\_%';
+ -------------------------- + -------- +
| Variable_name | 价值|
+ -------------------------- + -------- +
| character_set_client | 拉丁1 |
| character_set_connection | 拉丁1 |
...
| character_set_results | 拉丁1 |
...
+ -------------------------- + -------- +
MySQL的> SHOW SESSION VARIABLES LIKE 'collation_connection';
+ ---------------------- + ------------------- +
| Variable_name | 价值|
+ ---------------------- + ------------------- +
| collat​​ion_connection | latin1_swedish_ci |
+ ---------------------- + ------------------- +

为什么会这样? 毕竟, utf8mb4 8.0客户端和5.7服务器都知道,所以他们都认识到它。 要理解这种行为,有必要了解当客户端告诉服务器它想要使用哪个字符集时,它确实告诉服务器该字符集的默认排序规则。 因此,由于多种因素的组合,会出现上述行为:

  • 为缺省归类 utf8mb4 的MySQL 5.7和8.0之间不同( utf8mb4_general_ci 5.7, utf8mb4_0900_ai_ci 8.0)。

  • 当8.0客户端请求一个字符集时 utf8mb4 ,它发送给服务器的是默认的8.0 utf8mb4 排序规则; 也就是说 utf8mb4_0900_ai_ci

  • utf8mb4_0900_ai_ci 仅在MySQL 8.0中实现,因此5.7服务器无法识别它。

  • 由于5.7服务器无法识别 utf8mb4_0900_ai_ci ,因此无法满足客户端字符集请求,并回退到其默认字符集和排序规则( latin1 latin1_swedish_ci )。

在这种情况下,客户端仍可以 utf8mb4 通过 SET NAMES 'utf8mb4' 在连接后 发出 语句 来使用 得到的排序规则是5.7默认 utf8mb4 排序规则; 就是, utf8mb4_general_ci 如果客户端另外需要进行整理 utf8mb4_0900_ai_ci ,则无法实现该目标,因为服务器无法识别该整理。 客户端必须愿意使用不同的 utf8mb4 排序规则,或者从MySQL 8.0或更高版本连接到服务器。

运行时错误处理

在已建立的连接中,客户端可以请求更改连接字符集和与 SET NAMES 或进行 整理 SET CHARACTER SET

某些字符集不能用作客户端字符集; 请参阅 不允许的客户端字符集 如果指定有效但不允许作为客户端字符集的字符集,则服务器将返回错误:

MySQL的> SET NAMES 'ucs2';
错误1231(42000):变量'character_set_client'不能设置为
'ucs2'的值

如果服务器无法识别字符集(或排序规则),则会产生错误:

MySQL的> SET NAMES 'bogus';
ERROR 1115(42000):未知字符集:'bogus'

MySQL的> SET NAMES 'utf8mb4' COLLATE 'bogus';
ERROR 1273(HY000):未知整理:'伪造'
小费

想要验证服务器是否遵守其请求的字符集的客户端可以在连接并检查结果是否为预期字符集后执行以下语句:

SELECT @@ character_set_client;

10.5配置应用程序字符集和排序规则

对于使用默认MySQL字符集和排序规则( utf8mb4 utf8mb4_0900_ai_ci 存储数据的应用程序 ,不需要特殊配置。 如果应用程序需要使用不同的字符集或排序规则来存储数据,则可以通过以下几种方式配置字符集信息:

  • 指定每个数据库的字符设置 例如,使用一个数据库的应用程序可能使用默认值 utf8mb4 ,而使用另一个数据库的应用程序可能会使用 sjis

  • 在服务器启动时指定字符设置。 这会导致服务器对所有未进行其他安排的应用程序使用给定的设置。

  • 如果从源构建MySQL,请在配置时指定字符设置。 这会导致服务器将给定的设置用作所有应用程序的默认设置,而无需在服务器启动时指定它们。

当不同的应用程序需要不同的字符设置时,每数据库技术提供了很大的灵活性。 如果大多数或所有应用程序使用相同的字符集,则在服务器启动或配置时指定字符设置可能是最方便的。

对于每数据库或服务器启动技术,设置控制数据存储的字符集。 应用程序还必须告知服务器使用哪个字符集进行客户端/服务器通信,如以下说明中所述。

这里示出的示例假定使用的 latin1 字符集和 latin1_swedish_ci 归类在特定情况下作为替代的默认值 utf8mb4 utf8mb4_0900_ai_ci

  • 指定每个数据库的字符设置  要创建数据库,使其表使用给定的默认字符集和排序规则进行数据存储,请使用如下 CREATE DATABASE 语句:

    创建数据库mydb
      字符集拉丁1
      COLLATE latin1_swedish_ci;
    

    在数据库中创建的表将使用 latin1 latin1_swedish_ci 默认为任意字符列。

    使用数据库的应用程序还应在每次连接时配置与服务器的连接。 这可以通过 SET NAMES 'latin1' 在连接后 执行 语句 来完成 无论连接方法如何( mysql 客户端,PHP脚本等), 都可以使用该语句

    在某些情况下,可以将连接配置为以其他方式使用所需的字符集。 例如,要使用 mysql 进行连接 ,可以指定 --default-character-set=latin1 命令行选项以实现与之相同的效果 SET NAMES 'latin1'

    有关配置客户端连接的更多信息,请参见 第10.4节“连接字符集和排序”

    注意

    如果 ALTER DATABASE 用于更改数据库缺省字符集或排序规则,则必须删除并重新创建数据库中使用这些缺省值的现有存储例程,以便它们使用新的缺省值。 (在存储例程中,如果未明确指定字符集或排序规则,则具有字符数据类型的变量将使用数据库缺省值。请参见 第13.1.17节“创建过程和创建函数语法” 。)

  • 在服务器启动时指定字符设置。  要在服务器启动时选择字符集和排序规则,请使用 --character-set-server --collation-server 选项。 例如,要指定选项文件中的选项,请包括以下行:

    的[mysqld]
    字符集服务器= LATIN1
    核对服务器= latin1_swedish_ci
    

    这些设置适用于服务器范围,并应用为任何应用程序创建的数据库的默认设置,以及在这些数据库中创建的表。

    SET NAMES 如前所述 ,应用程序在连接 仍然需要使用 或等效的 配置连接 您可能会尝试使用 --init_connect="SET NAMES 'latin1'" 选项 启动服务器, 以便 SET NAMES 为每个连接的客户端自动执行。 但是,因为这可能会产生不一致的结果 init_connect 谁拥有用户不执行价值 CONNECTION_ADMIN SUPER 特权。

  • 在MySQL配置时指定字符设置。  要从源配置和构建MySQL,要选择字符集和排序规则,请使用 DEFAULT_CHARSET CMake 选项: DEFAULT_COLLATION

    cmake。-DDEFAULT_CHARSET = latin1 \
      -DDEFAULT_COLLATION = latin1_swedish_ci
    

    生成的服务器使用 latin1 latin1_swedish_ci 作为数据库和表以及客户端连接的缺省值。 在服务器启动时 不必使用 --character-set-server --collation-server 指定这些默认值。 应用程序 SET NAMES 在连接到服务器后 也不必使用 或等效连接。

无论您如何配置MySQL字符集以供应用程序使用,您还必须考虑这些应用程序执行的环境。 例如,如果您将使用从在编辑器中创建的文件中获取的UTF-8文本发送语句,则应编辑该文件,并将环境的语言环境设置为UTF-8,以便文件编码正确,以便操作系统正确处理它。 如果你使用 mysql 客户端从终端窗口中,窗口必须配置为使用UTF-8或字符可能无法正常显示。 对于在Web环境中执行的脚本,脚本必须正确处理与MySQL服务器交互的字符编码,并且必须生成正确指示编码的页面,以便浏览器知道如何显示页面内容。 例如,您可以 <meta> <head> 元素中 包含此 标记

<meta http-equiv =“Content-Type”content =“text / html; charset = utf-8”/>

10.6错误消息字符集

本节介绍MySQL服务器如何使用字符集构造错误消息。 有关错误消息语言(而不是字符集)的信息,请参见 第10.11节“设置错误消息语言” 有关配置错误日志记录的一般信息,请参见 第5.4.2节“错误日志”

错误消息构造的字符集

服务器构造错误消息,如下所示:

  • 消息模板使用UTF-8( utf8mb3 )。

  • 消息模板中的参数将替换为适用于特定错误发生的值:

    • 表或列名称等标识符在内部使用UTF-8,因此它们将按原样复制。

    • 字符(非二进制)字符串值从其字符集转换为UTF-8。

    • 二进制字符串值复制是用于字节范围 0x20 0x7E ,并使用 \x 十六进制编码该范围之外字节。 例如,如果发生重复键错误用于试图插入 0x41CF9F 到一个 VARBINARY 唯一的列,得到的错误消息使用UTF-8编码的与一些字节的十六进制:

      键1的重复条目“A \ xC3 \ x9F”
      

错误消息处置的字符集

一旦构造出错,消息就可以由服务器写入错误日志或发送给客户端:

  • 如果服务器将错误消息写入错误日志,则会将其按照构造的UTF-8写入,而不转换为其他字符集。

  • 如果服务器将错误消息发送到客户端程序,则服务器将其从UTF-8转换为 character_set_results 系统变量 指定的字符集 如果 character_set_results 值为 NULL binary ,则不会发生转换。 如果变量值是 utf8mb3 或者 utf8mb4 则不会发生转换 ,因为这些字符集具有包含消息构造中使用的所有UTF-8字符的所有字符集。

    如果无法表示字符 character_set_results ,则在转换期间可能会发生某些编码。 编码使用Unicode代码点值:

    • 基本多语言平面(BMP)范围( 0x0000 to 0xFFFF )中的 字符 使用 表示法 编写 \nnnn

    • BMP范围( 0x10000 to 0x10FFFF 之外的字符 使用 符号 书写 \+nnnnnn

    客户端可以设置 character_set_results 为控制接收错误消息的字符集。 变量可以直接设置,也可以通过诸如之类的方式间接设置 SET NAMES 有关更多信息 character_set_results ,请参见 第10.4节“连接字符集和排序”

10.7列字符集转换

要将二进制或非二进制字符串列转换为使用特定字符集,请使用 ALTER TABLE 要成功进行转换,必须满足以下条件之一:

  • 如果列有一个二进制数据类型( BINARY VARBINARY BLOB ),它包含必须使用单字节字符集编码的所有值(字符集你转换列)。 如果使用二进制列将信息存储在多个字符集中,MySQL无法知道哪些值使用哪个字符集并且无法正确转换数据。

  • 如果列具有一个非二进制数据类型( CHAR VARCHAR TEXT ),其内容应在列的字符集,而不是一些其他字符集编码。 如果内容以不同的字符集编码,则可以将列转换为首先使用二进制数据类型,然后转换为具有所需字符集的非二进制列。

假设一个表 t 有一个名为 col1 define 的二进制列 VARBINARY(50) 假设列中的信息使用单个字符集进行编码,您可以将其转换为具有该字符集的非二进制列。 例如,如果 col1 包含表示字符集中 greek 字符的 二进制数据 ,则 可以按如下方式进行转换:

ALTER TABLE t MODIFY col1 VARCHAR(50)CHARACTER SET greek;

如果原始列的类型为 BINARY(50) ,则可以将其转换为 CHAR(50) ,但结果值将 0x00 在末尾 填充 字节,这可能是不合需要的。 要删除这些字节,请使用以下 TRIM() 函数:

更新t SET col1 = TRIM(从col1到TRAILING 0x00);

假设该表 t 具有一个名为 col1 defined 的非二进制列 CHAR(50) CHARACTER SET latin1 但您希望将其转换为使用, utf8 以便您可以存储来自多种语言的值。 以下语句完成此操作:

ALTER TABLE t MODIFY col1 CHAR(50)CHARACTER SET utf8;

如果列包含不在两个字符集中的字符,则转换可能是有损的。

如果您在MySQL 4.1之前有旧表,则会发生一种特殊情况,其中非二进制列包含实际编码在与服务器的默认字符集不同的字符集中的值。 例如, sjis 即使MySQL的默认字符集不同 ,应用程序也可能 在列中 存储了 值。 可以将列转换为使用正确的字符集,但还需要一个额外的步骤。 假设服务器的默认字符集是 latin1 col1 定义为 CHAR(50) 但其内容是 sjis 值。 第一步是将列转换为二进制数据类型,该类型删除现有字符集信息而不执行任何字符转换:

ALTER TABLE t MODIFY col1 BLOB;

下一步是将列转换为具有正确字符集的非二进制数据类型:

ALTER TABLE t MODIFY col1 CHAR(50)CHARACTER SET sjis;

这个过程需要该表不是已经被用的语句,如修改 INSERT UPDATE 升级到MySQL 4.1或更高版本后。 在这种情况下,MySQL会使用列在列中存储新值 latin1 ,并且该列将包含 sjis latin1 的混合, 并且 无法正确转换。

如果在最初创建列时指定了属性,则还应在使用时更改表时指定它们 ALTER TABLE 例如,如果您指定 NOT NULL 了显式 DEFAULT 值,则还应在 ALTER TABLE 语句中 提供它们 否则,生成的列定义将不包括这些属性。

要转换表中的所有字符列,该 语句可能很有用。 请参见 第13.1.9节“ALTER TABLE语法” ALTER TABLE ... CONVERT TO CHARACTER SET charset

10.8整理问题

以下部分讨论字符集归类的各个方面。

10.8.1在SQL语句中使用COLLATE

使用该 COLLATE 子句,您可以覆盖默认排序规则以进行比较。 COLLATE 可以在SQL语句的各个部分中使用。 这里有些例子:

  • ORDER BY

    选择k
    从t1
    ORDER BY k COLLATE latin1_german2_ci;
    
  • AS

    SELECT k COLLATE latin1_german2_ci AS k1
    从t1
    ORDER BY k1;
    
  • GROUP BY

    选择k
    从t1
    GROUP BY k COLLATE latin1_german2_ci;
    
  • 使用聚合函数:

    SELECT MAX(k COLLATE latin1_german2_ci)
    从t1;
    
  • DISTINCT

    SELECT DISTINCT k COLLATE latin1_german2_ci
    从t1;
    
  • WHERE

         选择 *
         从t1
         在哪里_latin1'Müller'COLLATElatin1_german2_ci = k;
    
         选择 *
         从t1
         在哪里k LIKE_latin1'Müller'COLLATElatin1_german2_ci;
    
  • HAVING

    选择k
    从t1
    GROUP BY k
    拥有k =_latin1'Müller'COLLATElatin1_german2_ci;
    

10.8.2 COLLATE子句优先顺序

COLLATE 子句具有高优先级(高于 || ),因此以下两个表达式是等效的:

x || y COLLATE z
x || (y COLLATE z)

10.8.3字符集和校对兼容性

每个字符集都有一个或多个排序规则,但每个排序规则都与一个且只有一个字符集相关联。 因此,以下语句会导致错误消息,因为 latin2_bin 排序规则与 latin1 字符集 不合法

MySQL的> SELECT _latin1 'x' COLLATE latin2_bin;
ERROR 1253(42000):COLLATION'latin2_bin'无效
用于CHARACTER SET'latin1'

10.8.4表达式中的整理强制性

在绝大多数语句中,很明显MySQL用于解析比较操作的排序规则。 例如,在以下情况中,应该清楚的是,排序规则是列的排序规则 x

SELECT x FROM T ORDER BY x;
SELECT x FROM T WHERE x = x;
SELECT DISTINCT x FROM T;

但是,对于多个操作数,可能存在歧义。 例如:

SELECT x FROM T WHERE x ='Y';

比较应该使用列的整理 x ,还是字符串文字 的整理 'Y' 双方 x 'Y' 有排序规则,所以其整理的优先级?

排序的混合也可能出现在比较之外的上下文中。 例如,多参数连接操作(例如 CONCAT(x,'Y') 组合其参数以生成单个字符串)。 结果应该是什么样的整理?

为了解决这些问题,MySQL会检查是否可以将一个项目的排序规则强制转换为另一个项目的排序规则。 MySQL按如下方式分配强制性值:

  • 显式 COLLATE 条款的强制性为0(根本不可强制)。

  • 具有不同排序规则的两个字符串的串联具有1的强制性。

  • 列或存储的例程参数或局部变量的整理具有2的强制性。

  • 系统常数 (由功能,例如返回的字符串 USER() VERSION() )具有为3的可压缩性。

  • 文字的校对具有4的强制性。

  • 数值或时间值的整理具有5的强制性。

  • NULL 或者来自的表达 NULL 具有6的强制性。

MySQL使用具有以下规则的强制性值来解决歧义:

  • 使用具有最低强制性值的排序规则。

  • 如果双方具有相同的强制性,那么:

    • 如果双方都是Unicode,或双方都不是Unicode,那就是错误。

    • 如果其中一个侧面具有Unicode字符集,而另一侧具有非Unicode字符集,则具有Unicode字符集的一侧将获胜,并且自动字符集转换将应用于非Unicode侧。 例如,以下语句不会返回错误:

      SELECT CONCAT(utf8_column,latin1_column)FROM t1;
      

      它返回一个具有字符集 utf8 和相同排序规则的结果 utf8_column 在连接之前, latin1_column 会自动转换为 utf8

    • 为与来自相同的字符集的操作数但混合一个操作 _bin 整理和一个 _ci _cs 归类,则 _bin 使用归类。 这类似于混合非二进制和二进制字符串的操作如何将操作数评估为二进制字符串,除了它是用于排序而不是数据类型。

虽然自动转换不在SQL标准中,但标准确实说每个字符集(就支持的字符而言)是 Unicode 子集 因为一个众所周知的原则是 适用于超集的内容可以应用于子集 ”, 我们认为Unicode的排序规则可以应用于与非Unicode字符串的比较。

下表说明了前述规则的一些应用。

对照 使用整理
column1 = 'A' 使用整理 column1
column1 = 'A' COLLATE x 使用整理 'A' COLLATE x
column1 COLLATE x = 'A' COLLATE y 错误

要确定字符串表达式的强制性,请使用 COERCIBILITY() 函数(请参见 第12.15节“信息函数” ):

MySQL的> SELECT COERCIBILITY('A' COLLATE latin1_swedish_ci);
        - > 0
MySQL的> SELECT COERCIBILITY(VERSION());
        - > 3
MySQL的> SELECT COERCIBILITY('A');
        - > 4
MySQL的> SELECT COERCIBILITY(1000);
        - > 5

对于将数值或时间值隐式转换为字符串(例如,对于 1 表达式中 的参数) CONCAT(1, 'abc') ,结果是字符(非二进制)字符串,其具有由 系统变量 character_set_connection collation_connection 系统变量 确定的字符集和排序规则 请参见 第12.2节“表达式评估中的类型转换”

10.8.5二进制排序与_bin排序相比

本节介绍 binary 二进制字符串 排序规则 如何 比较 _bin

二进制字符串(如使用所存储的 BINARY VARBINARY BLOB 数据类型)有一个字符集和归类命名 binary 二进制字符串是字节序列,这些字节的数值确定比较和排序顺序。

非二进制字符串(如使用所存储的 CHAR VARCHAR TEXT 数据类型)具有一个字符集和比其他排序规则 binary 给定的非二进制字符集可以有多个排序规则,每个排序规则定义集合中字符的特定比较和排序顺序。 其中之一是字符集的二进制排序规则,由 _bin 排序规则名称中 后缀 表示 例如,对于二进制排序规则 utf8 latin1 命名 utf8_bin ,并 latin1_bin 分别。 utf8mb4 是一个具有两个二进制排序规则的例外;请参见 第10.10.1节“Unicode字符集” 。)

binary 整理与 _bin 几个方面 整理不同 ,将在以下各节中讨论:

比较和排序单位

二进制字符串是字节序列。 对于 binary 排序规则,比较和排序基于数字字节值。 非二进制字符串是字符序列,可以是多字节的。 非二进制字符串的排序定义字符值的排序以进行比较和排序。 对于 _bin 排序规则,此排序基于数字字符代码值,这类似于二进制字符串的排序,但字符代码值可能是多字节的。

字符集转换

非二进制字符串具有字符集,并且在许多情况下会自动转换为另一个字符集,即使字符串具有 _bin 排序规则:

  • 将列值分配给具有不同字符集的另一列时:

    UPDATE t1 SET utf8_bin_column = latin1_column;
    INSERT INTO t1(latin1_column)SELECT utf8_bin_column FROM t2;
    
  • INSERT 分配列值时 UPDATE 字符串文字 使用字符串文字时:

    SET NAMES latin1;
    INSERT INTO t1(utf8_bin_column)VALUES('string-in-latin1');
    
  • 将结果从服务器发送到客户端时:

    SET NAMES latin1;
    SELECT utf8_bin_column FROM t2;
    

对于二进制字符串列,不会发生转换。 对于与前面类似的情况,字符串值按字节方式复制。

信箱转换

非二进制字符集的归类提供有关字符的字母大小写的信息,因此非二进制字符串中的字符可以从一个字母大小写转换为另一个字母大小写,即使对于 _bin 忽略用于排序的字母大写的排序规则也是如此:

mysql> SET NAMES utf8mb4 COLLATE utf8mb4_bin;
mysql>SELECT LOWER('aA'), UPPER('zZ');
+ ------------- ------------- + +
| 更低('aA')| UPPER('zZ')|
+ ------------- ------------- + +
| aa | ZZ |
+ ------------- ------------- + +

lettercase的概念不适用于二进制字符串中的字节。 要执行lettercase转换,必须将字符串转换为非二进制字符串:

mysql> SET NAMES binary;
mysql>SELECT LOWER('aA'), LOWER(CONVERT('aA' USING utf8mb4));
+ ------------- + ----------------------------------- -  +
| 更低('aA')| 更低(转换('aA'使用utf8mb4))|
+ ------------- + ----------------------------------- -  +
| aA | aa |
+ ------------- + ----------------------------------- -  +

比较中的尾随空间处理

许多MySQL排序规则都有pad属性 PAD SPACE 基于UCA 9.0.0及更高版本的Unicode排序规则具有pad属性 NO PAD ; 请参见 第10.10.1节“Unicode字符集”

垫属性确定尾部空格是如何用于非二进制字符串(比较处理 CHAR VARCHAR TEXT 的值):

  • 对于 PAD SPACE 校对,尾随空格在比较中是微不足道的; 比较字符串而不考虑任何尾随空格。

  • NO PAD collat​​ions将字符串末尾的空格视为任何其他字符。

可以使用两个 utf8mb4 二进制排序 表示不同的行为 ,其中一个是 PAD SPACE ,另一个是 NO PAD 该示例还说明了如何使用该 INFORMATION_SCHEMA COLLATIONS 表来确定排序规则的pad属性。

MySQL的> SELECT COLLATION_NAME, PAD_ATTRIBUTE
       FROM INFORMATION_SCHEMA.COLLATIONS
       WHERE COLLATION_NAME LIKE 'utf8mb4%bin';
+ ------------------ + --------------- +
| COLLATION_NAME | PAD_ATTRIBUTE |
+ ------------------ + --------------- +
| utf8mb4_bin | PAD SPACE |
| utf8mb4_0900_bin | 没有PAD |
+ ------------------ + --------------- +
mysql> SET NAMES utf8mb4 COLLATE utf8mb4_bin;
mysql>SELECT 'a ' = 'a';
+ ------------ +
| 'a'='a'|
+ ------------ +
| 1 |
+ ------------ +
mysql> SET NAMES utf8mb4 COLLATE utf8mb4_0900_bin;
mysql>SELECT 'a ' = 'a';
+ ------------ +
| 'a'='a'|
+ ------------ +
| 0 |
+ ------------ +

对于二进制字符串,所有字符在比较中都很重要,包括尾随空格:

mysql> SET NAMES binary;
mysql>SELECT 'a ' = 'a';
+ ------------ +
| 'a'='a'|
+ ------------ +
| 0 |
+ ------------ +

插入和检索的尾随空间处理

CHAR(N) 列存储非二进制字符串。 对于插入,短于 N 字符的 用空格扩展。 对于检索,删除尾随空格。

BINARY(N) columns存储二进制字符串。 对于插入,使用 N 扩展 短于 字节的 0x00 字节 对于检索,没有删除任何内容; 始终返回声明长度的值。

mysql> 
mysql> 
mysql>CREATE TABLE t1 (
         a CHAR(10) CHARACTER SET utf8 COLLATE utf8_bin,
         b BINARY(10)
       );INSERT INTO t1 VALUES ('a','a');SELECT HEX(a), HEX(b) FROM t1;
+ -------- + ---------------------- +
| HEX(a)| HEX(b)|
+ -------- + ---------------------- +
| 61 | 61000000000000000000 |
+ -------- + ---------------------- +

10.8.6整理效果的例子

示例1:对德语变音符号进行排序

假设 X 中的列 T 有这些 latin1 值:

围巾
穆勒
MX系统
MySQL的

还假设使用以下语句检索列值:

通过X COLLATE选择X OR T ORDER collation_name;

如果我们使用 ORDER BY 不同的排序 规则,下表显示了值的结果顺序

latin1_swedish_ci latin1_german1_ci latin1_german2_ci
围巾 围巾 穆勒
MX系统 穆勒 围巾
穆勒 MX系统 MX系统
MySQL的 MySQL的 MySQL的

在这个例子中导致不同排序顺序的字符是U在它上面有两个点( ü ),德国人称之为 U-umlaut”。

  • 第一列显示了 SELECT 使用瑞典/芬兰整理规则 的结果,该 规则表明U-umlaut与Y进行排序。

  • 第二列显示了 SELECT 使用德国DIN-1规则 的结果,该 规则表明U-umlaut与U一起排序。

  • 第三列显示了 SELECT 使用德国DIN-2规则 的结果,该 规则表明U-umlaut与UE进行排序。

示例2:搜索德语变音符号

假设您有三个表只有使用的字符集和排序规则不同:

mysql> SET NAMES utf8;
mysql> 
mysql> 
mysql>CREATE TABLE german1 (
         c CHAR(10)
       ) CHARACTER SET latin1 COLLATE latin1_german1_ci;CREATE TABLE german2 (
         c CHAR(10)
       ) CHARACTER SET latin1 COLLATE latin1_german2_ci;CREATE TABLE germanutf8 (
         c CHAR(10)
       ) CHARACTER SET utf8 COLLATE utf8_unicode_ci;

每个表包含两个记录:

mysql> INSERT INTO german1 VALUES ('Bar'), ('Bär');
mysql> INSERT INTO german2 VALUES ('Bar'), ('Bär');
mysql>INSERT INTO germanutf8 VALUES ('Bar'), ('Bär');

上面的两个排序规则具有 A = Ä 相等性,一个没有这样的相等( latin1_german2_ci )。 因此,您将在比较中得到这些结果:

MySQL的> SELECT * FROM german1 WHERE c = 'Bär';
+ ------ +
| c |
+ ------ +
| 酒吧|
| Bär|
+ ------ +
MySQL的> SELECT * FROM german2 WHERE c = 'Bär';
+ ------ +
| c |
+ ------ +
| Bär|
+ ------ +
MySQL的> SELECT * FROM germanutf8 WHERE c = 'Bär';
+ ------ +
| c |
+ ------ +
| 酒吧|
| Bär|
+ ------ +

这是不是一个错误,而是的排序属性的结果 latin1_german1_ci utf8_unicode_ci (图示根据德国DIN 5007标准进行排序)。

10.8.7在INFORMATION_SCHEMA搜索中使用排序规则

表中的字符串列 INFORMATION_SCHEMA 具有排序规则 utf8_general_ci ,不区分大小写。 但是,对于与文件系统中表示的对象(例如数据库和表)相对应的值, INFORMATION_SCHEMA 字符串列中的 搜索 可以区分大小写或不区分,具体取决于基础文件系统的特征和 lower_case_table_names 系统变量设置。 例如,如果文件系统区分大小写,则搜索可能区分大小写。 本节介绍此行为以及如何在必要时进行修改。

假设查询在 SCHEMATA.SCHEMA_NAME 列中 搜索 test 数据库。 在Linux上,文件系统区分大小写,因此需要 SCHEMATA.SCHEMA_NAME 'test' 匹配进行比较,但是与之比较 'TEST' 不:

MySQL的> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
       WHERE SCHEMA_NAME = 'test';
+ ------------- +
| SCHEMA_NAME |
+ ------------- +
| 测试|
+ ------------- +

MySQL的> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
       WHERE SCHEMA_NAME = 'TEST';
空集(0.00秒)

lower_case_table_names 系统变量设置为0 时会出现这些结果 lower_case_table_names 设置为1或2会导致第二个查询返回与第一个查询相同(非空)的结果。

注意

禁止 lower_case_table_names 使用与初始化 服务器时使用的 设置不同的设置启动服务器。

在Windows或Mac系统,文件系统是不区分大小写,所以比较符合双方 'test' 'TEST'

MySQL的> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
       WHERE SCHEMA_NAME = 'test';
+ ------------- +
| SCHEMA_NAME |
+ ------------- +
| 测试|
+ ------------- +

MySQL的> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
       WHERE SCHEMA_NAME = 'TEST';
+ ------------- +
| SCHEMA_NAME |
+ ------------- +
| 测试|
+ ------------- +

lower_case_table_names 在这种情况下 ,价值 没有区别。

出现上述行为是因为 在搜索与文件系统中表示的对象相对应的值时 utf8_general_ci 排序规则不用于 INFORMATION_SCHEMA 查询。

如果 INFORMATION_SCHEMA 上的字符串操作的结果 与预期不同,则解决方法是使用显式 COLLATE 子句强制进行适当的排序规则(请参见 第10.8.1节“在SQL语句中使用COLLATE” )。 例如,为了执行不区分大小写的搜索中,使用 COLLATE INFORMATION_SCHEMA 列名:

MySQL的> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
       WHERE SCHEMA_NAME COLLATE utf8_general_ci = 'test';
+ ------------- +
| SCHEMA_NAME |
+ ------------- +
| 测试|
+ ------------- +

MySQL的> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
       WHERE SCHEMA_NAME COLLATE utf8_general_ci = 'TEST';
+ ------------- +
| SCHEMA_NAME |
+ ------------- +
| 测试|
+ ------------- +

您还可以使用 UPPER() LOWER() 功能:

在哪里UPPER(SCHEMA_NAME)='TEST'
在哪里(SCHEMA_NAME)='测试'

虽然即使在具有区分大小写的文件系统的平台上也可以执行不区分大小写的比较,如刚才所示,但它并不一定总是正确的。 在这样的平台上,可以有多个名称仅在字母大小不同的对象。 例如,名为 city ,, CITY 和的 City 可以同时存在。 考虑搜索是否应匹配所有此类名称或仅匹配一个并相应地编写查询。 以下第一个比较(with utf8_bin )区分大小写; 其他人不是:

WHERE TABLE_NAME COLLATE utf8_bin ='City'
WHERE TABLE_NAME COLLATE utf8_general_ci ='city'
在哪里UPPER(TABLE_NAME)='城市'
在哪里(TABLE_NAME)='城市'

INFORMATION_SCHEMA 字符串列中 搜索 引用 INFORMATION_SCHEMA 自身的 确实使用 utf8_general_ci 排序规则,因为它 INFORMATION_SCHEMA 未在文件系统中表示 虚拟 数据库。 例如,与 SCHEMATA.SCHEMA_NAME 匹配 'information_schema' 'INFORMATION_SCHEMA' 不论平台 进行比较

MySQL的> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
       WHERE SCHEMA_NAME = 'information_schema';
+ -------------------- +
| SCHEMA_NAME |
+ -------------------- +
| information_schema |
+ -------------------- +

MySQL的> SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
       WHERE SCHEMA_NAME = 'INFORMATION_SCHEMA';
+ -------------------- +
| SCHEMA_NAME |
+ -------------------- +
| information_schema |
+ -------------------- +

10.9 Unicode支持

Unicode标准包括基本多语言平面(BMP)中的字符和位于BMP之外的补充字符。 本节介绍MySQL中对Unicode的支持。 有关Unicode标准本身的信息,请访问 Unicode Consortium网站

BMP字符具有以下特征:

  • 它们的代码点值介于0到65535之间(或 U+0000 U+FFFF )。

  • 它们可以使用8,16或24位(1到3个字节)以可变长度编码进行编码。

  • 它们可以使用16位(2字节)以固定长度编码进行编码。

  • 它们足以满足主要语言中的几乎所有角色。

补充字符位于BMP之外:

  • 他们的代码点值介于 U+10000 之间 U+10FFFF

  • Unicode对增补字符的支持要求字符集的范围超出BMP字符,因此占用的空间比BMP字符多(每个字符最多4个字节)。

用于编码Unicode数据的UTF-8(具有8位单元的Unicode转换格式)方法是根据RFC 3629实现的,RFC 3629描述了从1到4个字节的编码序列。 UTF-8的想法是使用不同长度的字节序列编码各种Unicode字符:

  • 基本拉丁字母,数字和标点符号使用一个字节。

  • 大多数欧洲和中东脚本字母符合2字节序列:扩展拉丁字母(带波形符号,宏语,锐音,坟墓和其他重音符号),西里尔语,希腊语,亚美尼亚语,希伯来语,阿拉伯语,叙利亚语等。

  • 韩文,中文和日文表意文字使用3字节或4字节序列。

MySQL支持这些Unicode字符集:

  • utf8mb4 :Unicode字符集的UTF-8编码,每个字符使用一到四个字节。

  • utf8mb3 :Unicode字符集的UTF-8编码,每个字符使用一到三个字节。

  • utf8 :别名 utf8mb3

  • ucs2 :Unicode字符集的UCS-2编码,每个字符使用两个字节。

  • utf16 :Unicode字符集的UTF-16编码,每个字符使用两个或四个字节。 喜欢 ucs2 但有补充字符的扩展名。

  • utf16le :Unicode字符集的UTF-16LE编码。 就像 utf16 小端而不是大端。

  • utf32 :Unicode字符集的UTF-32编码,每个字符使用四个字节。

注意

utf8mb3 字符集已弃用,将在未来的MySQL版本中删除。 utf8mb4 改用。 虽然 utf8 目前是别名 utf8mb3 ,但在某些时候 utf8 会成为参考 utf8mb4 为避免含义模糊 utf8 ,请考虑 utf8mb4 明确 指定 字符集引用而不是 utf8

表10.2“Unicode字符集一般特性” 总结了MySQL支持的Unicode字符集的一般特性。

表10.2 Unicode字符集一般特征

字符集 支持的字符 每个字符所需的存储量
utf8mb3 utf8 仅限BMP 1,2或3个字节
ucs2 仅限BMP 2个字节
utf8mb4 BMP和补充 1,2,3或4个字节
utf16 BMP和补充 2或4个字节
utf16le BMP和补充 2或4个字节
utf32 BMP和补充 4字节

BMP外部的字符比较为REPLACEMENT CHARACTER,并 '?' 在转换为仅支持BMP字符( utf8mb3 ucs2 的Unicode字符集时转换为

如果使用支持增补字符的字符集,因此 比仅限BMP 字符集 更宽 ,则应用程序可能存在不兼容问题; 请参见 第10.9.8节“在3字节和4字节Unicode字符集之间进行转换” 该部分还描述了如何将表从(3字节) 转换为(4字节) ,以及在执行此操作时可能适用的约束。 utf8mb3 ucs2 utf8mb3 utf8mb4

大多数Unicode字符集都有一组类似的排序规则。 例如,每个具有丹麦核对,其名称是 utf8mb4_danish_ci utf8mb3_danish_ci utf8_danish_ci ucs2_danish_ci utf16_danish_ci ,和 utf32_danish_ci utf16le 唯一 的例外是 ,它只有两个排序规则。 有关Unicode归类及其区分属性(包括补充字符的归类属性)的信息,请参见 第10.10.1节“Unicode字符集”

UCS-2,UTF-16和UTF-32的MySQL实现以big-endian字节顺序存储字符,并且在值的开头不使用字节顺序标记(BOM)。 其他数据库系统可能使用little-endian字节顺序或BOM。 在这种情况下,在这些系统和MySQL之间传输数据时,需要执行值转换。 UTF-16LE的实现是小端的。

MySQL对UTF-8值不使用BOM。

使用Unicode与服务器通信的客户端应用程序应相应地设置客户端字符集(例如,通过发出 SET NAMES 'utf8mb4' 语句)。 某些字符集不能用作客户端字符集。 试图使用它们 SET NAMES SET CHARACTER SET 产生错误。 请参见 不允许的客户端字符集

以下部分提供了有关MySQL中Unicode字符集的更多详细信息。

10.9.1 utf8mb4字符集(4字节UTF-8 Unicode编码)

utfmb4 字符集有以下特点:

  • 支持BMP和补充字符。

  • 每个多字节字符最多需要四个字节。

utf8mb4 utf8mb3 字符集 形成对比 ,后者仅支持BMP字符,每个字符最多使用三个字节:

  • 对于BMP字符, utf8mb4 utf8mb3 具有相同的存储特性:相同的代码值,相同的编码,相同的长度。

  • 对于补充字符, utf8mb4 需要四个字节来存储它,而 utf8mb3 根本不能存储字符。 utf8mb3 转换 为时 utf8mb4 ,您无需担心转换补充字符,因为没有。

utf8mb4 是一个超集 utf8mb3 ,因此对于诸如以下串联的操作,结果具有字符集 utf8mb4 和整理 utf8mb4_col

SELECT CONCAT(utf8mb3_col,utf8mb4_col);

类似地,该 WHERE 子句中 的以下比较 根据以下排序 utf8mb4_col

SELECT * FROM utf8mb3_tbl,utf8mb4_tbl
在哪里utf8mb3_tbl.utf8mb3_col = utf8mb4_tbl.utf8mb4_col;

有关与多字节字符集相关的数据类型存储的信息,请参阅 字符串类型存储要求

10.9.2 utf8mb3字符集(3字节UTF-8 Unicode编码)

utf8mb3 字符集有以下特点:

  • 仅支持BMP字符(不支持增补字符)

  • 每个多字节字符最多需要三个字节。

使用UTF-8数据但需要补充字符支持的应用程序应使用 utf8mb4 而不是 utf8mb3 (参见 第10.9.1节“utf8mb4字符集(4字节UTF-8 Unicode编码)” )。

完全相同的字符集可用于 utf8mb3 ucs2 也就是说,他们有相同的 曲目

utf8 是别名 utf8mb3 ; 字符限制是隐式的,而不是名称中的显式。

注意

utf8mb3 字符集已弃用,将在未来的MySQL版本中删除。 utf8mb4 改用。 虽然 utf8 目前是别名 utf8mb3 ,但在某些时候 utf8 会成为参考 utf8mb4 为避免含义模糊 utf8 ,请考虑 utf8mb4 明确 指定 字符集引用而不是 utf8

utf8mb3 可以用在 CHARACTER SET 条款,并 条款,其中 ,等等。 例如: utf8mb3_collation_substring COLLATE collation_substring bin czech_ci danish_ci esperanto_ci estonian_ci

CREATE TABLE t(s1 CHAR(1)CHARACTER SET utf8mb3;
SELECT * FROM t WHERE s1 COLLATE utf8mb3_general_ci ='x';
DECLARE x VARCHAR(5)CHARACTER SET utf8mb3 COLLATE utf8mb3_danish_ci;
SELECT CAST('a'AS CHAR CHARACTER SET utf8)COLLATE utf8_czech_ci;

MySQL立即将 utf8mb3 in语句的 实例转换 utf8 ,因此在诸如 SHOW CREATE TABLE SELECT CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.COLUMNS 等语句中 SELECT COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS ,用户将看到名称 utf8 utf8_collation_substring

utf8mb3 在除了以外的语境中也有效 CHARACTER SET 条款 例如:

mysqld --character-set-server = utf8mb3
SET NAMES'utf8mb3'; / *和其他具有类似效果的SET语句* /
SELECT _utf8mb3'a';

有关与多字节字符集相关的数据类型存储的信息,请参阅 字符串类型存储要求

10.9.3 utf8字符集(utf8mb3的别名)

utf8 utf8mb3 字符集 的别名 有关更多信息,请参见 第10.9.2节“utf8mb3字符集(3字节UTF-8 Unicode编码)”

注意

utf8mb3 字符集已弃用,将在未来的MySQL版本中删除。 utf8mb4 改用。 虽然 utf8 目前是别名 utf8mb3 ,但在某些时候 utf8 会成为参考 utf8mb4 为避免含义模糊 utf8 ,请考虑 utf8mb4 明确 指定 字符集引用而不是 utf8

10.9.4 ucs2字符集(UCS-2 Unicode编码)

在UCS-2中,每个字符由一个2字节的Unicode代码表示,其中最重要的字节优先。 例如: LATIN CAPITAL LETTER A 有代码 0x0041 ,它存储为2字节序列: 0x00 0x41 CYRILLIC SMALL LETTER YERU (Unicode 0x044B )存储为2字节序列: 0x04 0x4B 有关Unicode字符及其代码,请参阅 Unicode Consortium网站

ucs2 字符集有以下特点:

  • 仅支持BMP字符(不支持增补字符)

  • 使用固定长度的16位编码,每个字符需要两个字节。

10.9.5 utf16字符集(UTF-16 Unicode编码)

utf16 字符集是 ucs2 ,使补充的字符编码字符带有延伸设置:

  • 对于BMP字符, utf16 ucs2 具有相同的存储特性:相同的代码值,相同的编码,相同的长度。

  • 对于补充字符, utf16 具有使用32位表示字符的特殊序列。 这称为 代理 机制:对于大于 0xffff 10 的数字 ,取10位并将它们加到 0xd800 第一个16位字中,再取10位,然后将它们加到 0xdc00 下一个16位中。字。 因此,所有补充字符都需要32位,其中前16位是 0xd800 之间的数字 0xdbff ,最后16位是 0xdc00 之间的数字 0xdfff 例子在章节中 15.5 Unicode 4.0文档的 代理区域

因为 utf16 支持代理 ucs2 而不 代理 ,所以有效检查仅适用于 utf16 :您不能插入没有底部代理的顶级代理,反之亦然。 例如:

INSERT INTO t(ucs2_column)VALUES(0xd800); / * legal * /
INSERT INTO t(utf16_column)VALUES(0xd800); / *非法* /

有是在技术上有效的,但不是真正的Unicode(这是Unicode的认为是,人物角色无有效性检查 未分配的代码点 私用 ,甚至出现 非法移民 一样 0xffff )。 例如,既然 U+F8FF 是Apple徽标,这是合法的:

INSERT INTO t(utf16_column)VALUES(0xf8ff); / * legal * /

不能指望这样的人物对每个人都意味着同样的事情。

因为MySQL必须允许最坏的情况(一个字符需要四个字节),所以 utf16 列或索引的最大长度只是列或索引的最大长度的一半 ucs2 例如, MEMORY 表索引键 的最大长度 为3072字节,因此这些语句创建具有最长允许索引 ucs2 utf16 列的表:

CREATE TABLE tf(s1 VARCHAR(1536)CHARACTER SET ucs2)ENGINE = MEMORY;
创建指数i on tf(s1);
CREATE TABLE tg(s1 VARCHAR(768)CHARACTER SET utf16)ENGINE = MEMORY;
CREATE INDEX i ON tg(s1);

10.9.6 utf16le字符集(UTF-16LE Unicode编码)

这是相同的, utf16 但是是小端而不是大端。

10.9.7 utf32字符集(UTF-32 Unicode编码)

utf32 字符集是固定长度(例如 ucs2 ,不像 utf16 )。 utf32 每个字符使用32位,不像 ucs2 每个字符 使用16位),而不像 utf16 (对于某些字符使用16位而对其他字符使用32位)。

utf32 占用的空间 ucs2 和空间 都是两倍 utf16 ,但是 utf32 具有与 ucs2 可预测的存储 相同的优势 :所需的字节数 utf32 等于字符数乘以4.另外,不同的 utf16 是,编码没有技巧 utf32 ,所以存储的值等于代码值。

为了演示后一个优势如何有用,下面是一个示例,说明如何在 utf8mb4 给定 utf32 代码值的情况下 确定 值:

/ *假设代码值= 100cc LINEAR B WHEELED CHARIOT * /
CREATE TABLE tmp(utf32_col CHAR(1)CHARACTER SET utf32,
                  utf8mb4_col CHAR(1)CHARACTER SET utf8mb4);
插入tmp VALUES(0x000100cc,NULL);
UPDATE tmp SET utf8mb4_col = utf32_col;
SELECT HEX(utf32_col),HEX(utf8mb4_col)FROM tmp;

MySQL对添加未分配的Unicode字符或私有区域字符非常宽容。 实际上只有一个有效性检查 utf32 :没有代码值可能大于 0x10ffff 例如,这是非法的:

INSERT INTO t(utf32_column)VALUES(0x110000); / *非法* /

10.9.8在3字节和4字节Unicode字符集之间进行转换

本节介绍在 字符集 utf8mb3 utf8mb4 字符集 之间转换字符数据时可能遇到的问题

注意

本讨论主要侧重于 utf8mb3 之间的转换 utf8mb4 ,但类似的原则适用于在 ucs2 字符集和字符集 之间进行转换, 例如 utf16 utf32

utf8mb3 utf8mb4 字符集的区别如下:

  • utf8mb3 仅支持基本多语言平面(BMP)中的字符。 utf8mb4 另外还支持BMP之外的补充字符。

  • utf8mb3 每个字符最多使用三个字节。 utf8mb4 每个字符最多使用四个字节。

注意

这个讨论是指 utf8mb3 utf8mb4 字符集的名字更明确一些参考3字节和4个字节的UTF-8字符集的数据。 例外情况是在表定义 utf8 中使用,因为MySQL将 utf8mb3 此类定义 指定的 实例转换 utf8 ,这是其别名 utf8mb3

从转换的一个优点 utf8mb3 utf8mb4 是,这使应用程序能够使用增补字符。 一个权衡是,这可能会增加数据存储空间要求。

就表格内容而言,从转换 utf8mb3 utf8mb4 没有问题:

  • 对于BMP字符, utf8mb4 utf8mb3 具有相同的存储特性:相同的代码值,相同的编码,相同的长度。

  • 对于补充字符, utf8mb4 需要四个字节来存储它,而 utf8mb3 根本不能存储字符。 utf8mb3 转换 为时 utf8mb4 ,您无需担心转换补充字符,因为没有。

就表结构而言,这些是主要的潜在不兼容性:

  • 对于可变长度字符数据类型( VARCHAR TEXT 类型), utf8mb4 中字符的最大允许长度小于 utf8mb3 列。

  • 对于所有字符数据类型( CHAR VARCHAR TEXT 类型), utf8mb4 可以索引的最大字符数对于 列而言比 utf8mb3 列少。

因此,要将表转换 utf8mb3 utf8mb4 ,可能需要更改某些列或索引定义。

表可以从被转换 utf8mb3 utf8mb4 通过使用 ALTER TABLE 假设一个表有这个定义:

CREATE TABLE t1(
  col1 CHAR(10)CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  col2 CHAR(10)CHARACTER SET utf8 COLLATE utf8_bin NOT NULL
)CHARACTER SET utf8;

以下语句转换 t1 为使用 utf8mb4

改编表t1
  默认字符集utf8mb4,
  修改col1 CHAR(10)
    CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  修改col2 CHAR(10)
    CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL;

从转换时捕捉 utf8mb3 utf8mb4 的是一列或索引关键字的最大长度是在以下方面不变 字节 因此,它在 字符 方面较小, 因为 字符 的最大长度是四个字节而不是三个字节。 对于 CHAR VARCHAR TEXT 数据类型,将你的MySQL表时观看了这些问题:

  • 检查 utf8mb3 列的 所有定义, 并确保它们不会超过存储引擎的最大长度。

  • 检查 utf8mb3 上的所有索引, 并确保它们不会超过存储引擎的最大长度。 有时,由于存储引擎的增强,最大值可能会发生变化。

如果前述条件适用,则必须减少列或索引的已定义长度,或者继续使用 utf8mb3 而不是 使用 utf8mb4

以下是可能需要进行结构更改的一些示例:

  • TINYTEXT 列最多可容纳255个字节,因此最多可容纳85个3字节或63个4字节字符。 假设您有一个 TINYTEXT 使用 utf8mb3 但必须能够包含超过63个字符的列。 utf8mb4 除非您还将数据类型更改为更长的类型 否则 无法将其转换 TEXT

    同样,一个很长的 VARCHAR 列可能需要改变,以较长的一个 TEXT 类型,如果你想从转换 utf8mb3 utf8mb4

  • InnoDB 对于使用 COMPACT REDUNDANT 行格式的 表,最大索引长度为767字节 ,因此对于 utf8mb3 utf8mb4 列,最多可以索引255或191个字符。 如果您当前具有 utf8mb3 索引长度超过191个字符的列,则必须索引较少数量的字符。

    InnoDB 使用 COMPACT REDUNDANT 行格式 表中 ,这些列和索引定义是合法的:

    col1 VARCHAR(500)CHARACTER SET utf8,INDEX(col1(255))
    

    要使用 utf8mb4 ,索引必须更小:

    col1 VARCHAR(500)CHARACTER SET utf8mb4,INDEX(col1(191))
    
    注意

    对于 InnoDB 使用 COMPRESSED DYNAMIC 行格式的 表,允许使用 长度超过767字节(最多3072字节)的 索引键前缀 使用这些行格式创建的表使您可以 分别 utf8mb3 utf8mb4 索引最多1024或768个字符 有关相关信息,请参见 第15.6.1.6节“InnoDB表的限制” DYNAMIC行格式

仅当您具有很长的列或索引时,才可能需要前面的更改类型。 否则,您应该能够将表转换 utf8mb3 utf8mb4 没有问题, ALTER TABLE 如前所述。

以下各项总结了其他潜在的不兼容性:

  • SET NAMES 'utf8mb4' 导致使用4字节字符集连接字符集。 只要服务器没有发送4字节字符,就不会有问题。 否则,期望每个字符最多接收三个字节的应用程序可能会出现问题。 相反,期望发送4字节字符的应用程序必须确保服务器能够理解它们。

  • 对于复制,如果要在主服务器上使用支持增补字符的字符集,则所有从服务器也必须理解它们。

    另外,请记住一般原则,如果表在主服务器和从服务器上有不同的定义,这可能会导致意外的结果。 例如,最大索引密钥长度的差异使得 utf8mb3 在主服务器和 utf8mb4 从服务器上 使用 时存在 风险

如果你已经转换为 utf8mb4 utf16 utf16le ,或 utf32 ,然后再决定转换回 utf8mb3 ucs2 (例如,降级到旧版本的MySQL),这些事项:

  • utf8mb3 ucs2 数据应该没有问题。

  • 服务器必须足够新,以识别引用您要转换的字符集的定义。

  • 对于参照对象定义 utf8mb4 的字符集,你可以把它们扔掉 的mysqldump 之前降级,编辑备份文件来修改的实例 utf8mb4 utf8 ,然后重新在旧服务器上的文件,只要有中没有4字节字符数据。 较旧的服务器将 utf8 在转储文件中 看到 对象定义并创建使用(3字节) utf8 字符集的 新对象

10.10支持的字符集和排序规则

本节说明MySQL支持哪些字符集。 每组相关字符集都有一个子部分。 对于每个字符集,列出允许的排序规则。

要列出可用的字符集及其默认排序规则,请使用该 SHOW CHARACTER SET 语句或查询该 INFORMATION_SCHEMA CHARACTER_SETS 表。 例如:

MySQL的> SHOW CHARACTER SET;
+ ---------- + --------------------------------- + ---- ----------------- + -------- +
| Charset | 说明| 默认排序规则| Maxlen |
+ ---------- + --------------------------------- + ---- ----------------- + -------- +
| armscii8 | ARMSCII-8亚美尼亚语| armscii8_general_ci | 1 |
| ascii | 美国ASCII | ascii_general_ci | 1 |
| big5 | Big5繁体中文| big5_chinese_ci | 2 |
| 二进制| 二进制伪字符集| 二进制| 1 |
| cp1250 | Windows Central European | cp1250_general_ci | 1 |
| cp1251 | Windows西里尔文| cp1251_general_ci | 1 |
| cp1256 | Windows阿拉伯语| cp1256_general_ci | 1 |
| cp1257 | Windows波罗的海| cp1257_general_ci | 1 |
| cp850 | DOS西欧| cp850_general_ci | 1 |
| cp852 | DOS中欧| cp852_general_ci | 1 |
| cp866 | DOS俄罗斯| cp866_general_ci | 1 |
| cp932 | SJIS for Windows日语| cp932_japanese_ci | 2 |
| dec8 | DEC西欧| dec8_swedish_ci | 1 |
| eucjpms | UJIS for Windows日语| eucjpms_japanese_ci | 3 |
| euckr | EUC-KR韩语| euckr_korean_ci | 2 |
| gb18030 | 中国国家标准GB18030 | gb18030_chinese_ci | 4 |
| gb2312 | GB2312简体中文| gb2312_chinese_ci | 2 |
| gbk | GBK简体中文| gbk_chinese_ci | 2 |
| geostd8 | GEOSTD8格鲁吉亚语| geostd8_general_ci | 1 |
| 希腊| ISO 8859-7希腊语| greek_general_ci | 1 |
| 希伯来语| ISO 8859-8希伯来语| hebrew_general_ci | 1 |
| hp8 | 惠普西欧| hp8_english_ci | 1 |
| keybcs2 | DOS Kamenicky捷克斯洛伐克语| keybcs2_general_ci | 1 |
| koi8r | KOI8-R Relcom俄语| koi8r_general_ci | 1 |
| koi8u | KOI8-U乌克兰语| koi8u_general_ci | 1 |
| 拉丁1 | cp1252西欧| latin1_swedish_ci | 1 |
| 拉丁文2 | ISO 8859-2中欧| latin2_general_ci | 1 |
| 拉丁语5 | ISO 8859-9土耳其语| latin5_turkish_ci | 1 |
| 拉丁语7 | ISO 8859-13 Baltic | latin7_general_ci | 1 |
| macce | Mac中欧| macce_general_ci | 1 |
| macroman | Mac西欧| macroman_general_ci | 1 |
| sjis | Shift-JIS日语| sjis_japanese_ci | 2 |
| swe7 | 7bit瑞典语| swe7_swedish_ci | 1 |
| tis620 | TIS620泰国| tis620_thai_ci | 1 |
| ucs2 | UCS-2 Unicode | ucs2_general_ci | 2 |
| ujis | EUC-JP日语| ujis_japanese_ci | 3 |
| utf16 | UTF-16 Unicode | utf16_general_ci | 4 |
| utf16le | UTF-16LE Unicode | utf16le_general_ci | 4 |
| utf32 | UTF-32 Unicode | utf32_general_ci | 4 |
| utf8 | UTF-8 Unicode | utf8_general_ci | 3 |
| utf8mb4 | UTF-8 Unicode | utf8mb4_0900_ai_ci | 4 |
+ ---------- + --------------------------------- + ---- ----------------- + -------- +

在字符集具有多个排序规则的情况下,可能不清楚哪种排序规则最适合给定的应用程序。 为避免选择错误的排序规则,与代表性数据值进行一些比较可能会有所帮助,以确保给定的排序规则按预期方式对值进行排序。

10.10.1 Unicode字符集

本节介绍可用于Unicode字符集的排序规则及其区分属性。 有关Unicode的一般信息,请参见 第10.9节“Unicode支持”

MySQL支持多个Unicode字符集:

  • utf8mb4 :Unicode字符集的UTF-8编码,每个字符使用一到四个字节。

  • utf8mb3 :Unicode字符集的UTF-8编码,每个字符使用一到三个字节。

  • utf8 :别名 utf8mb3

  • ucs2 :Unicode字符集的UCS-2编码,每个字符使用两个字节。

  • utf16 :Unicode字符集的UTF-16编码,每个字符使用两个或四个字节。 喜欢 ucs2 但有补充字符的扩展名。

  • utf16le :Unicode字符集的UTF-16LE编码。 就像 utf16 小端而不是大端。

  • utf32 :Unicode字符集的UTF-32编码,每个字符使用四个字节。

注意

utf8mb3 字符集已弃用,将在未来的MySQL版本中删除。 utf8mb4 改用。 虽然 utf8 目前是别名 utf8mb3 ,但在某些时候 utf8 会成为参考 utf8mb4 为避免含义模糊 utf8 ,请考虑 utf8mb4 明确 指定 字符集引用而不是 utf8

utf8mb4 utf16 utf16le ,和 utf32 支持躺在BMP外基本多语种平面(BMP)字符和增补字符。 utf8 并且 ucs2 仅支持BMP字符。

大多数Unicode字符集都有一般的排序规则(由 _general 名称或缺少语言说明符表示),二进制排序规则( _bin 在名称中 表示 )和几种特定于语言的排序规则(由语言说明符表示)。 例如,for utf8mb4 utf8mb4_general_ci and utf8mb4_bin ,它是一般和二进制排序规则,并且 utf8mb4_danish_ci 是其特定于语言的排序规则之一。

大多数字符集都有一个二进制排序规则。 utf8mb4 是一个例外,它有两个: utf8mb4_bin 和(从MySQL 8.0.17开始) utf8mb4_0900_bin 这两个二进制排序规则具有相同的排序顺序,但通过其pad属性和排序权重特征进行区分。 请参阅 排序垫属性 字符 排序 权重

整理支持 utf16le 有限。 唯一可用的排序规则是 utf16le_general_ci utf16le_bin 这些类似于 utf16_general_ci utf16_bin

Unicode归类算法(UCA)版本

MySQL xxx_unicode_ci 根据 http://www.unicode.org/reports/tr10/中 描述的Unicode排序算法(UCA) 实现 排序规则 排序规则使用版本4.0.0 UCA权重键: http //www.unicode.org/Public/UCA/4.0.0/allkeys-4.0.0.txt xxx_unicode_ci 排序规则仅部分支持Unicode排序规则算法。 不支持某些字符,并且不完全支持组合标记。 这主要影响越南语,约鲁巴语和一些较小的语言,如纳瓦霍语。 组合字符被认为与字符串比较中使用单个unicode字符编写的相同字符不同,并且这两个字符被认为具有不同的长度(例如,由 CHAR_LENGTH() 函数或结果集元数据返回)。

基于UCA版本高于4.0.0的Unicode排序规则包括排序规则名称中的版本。 例子:

LOWER() UPPER() 功能的情况下执行根据它们参数的排序规则折叠。 只有在参数排序规则使用足够高的UCA版本时,才会通过这些函数转换仅在Unicode版本高于4.0.0时具有大写和小写版本的字符。

校对板属性

基于UCA 9.0.0及更高版本的排序比基于9.0.0之前的UCA版本的排序更快。 NO PAD PAD SPACE 基于9.0.0之前的UCA版本的排序中使用的 相比, 它们还具有pad属性 为了比较非二进制字符串, NO PAD collat​​ions将字符串末尾的空格视为任何其他字符(请参阅 比较中的尾随空间处理 )。

要确定排序规则的pad属性,请使用 INFORMATION_SCHEMA COLLATIONS 包含 PAD_ATTRIBUTE 例如:

MySQL的> SELECT COLLATION_NAME, PAD_ATTRIBUTE
       FROM INFORMATION_SCHEMA.COLLATIONS
       WHERE CHARACTER_SET_NAME = 'utf8mb4';
+ ---------------------------- + -------- +
| COLLATION_NAME | PAD_ATTRIBUTE |
+ ---------------------------- + -------- +
| utf8mb4_general_ci | PAD SPACE |
| utf8mb4_bin | PAD SPACE |
| utf8mb4_unicode_ci | PAD SPACE |
| utf8mb4_icelandic_ci | PAD SPACE |
...
| utf8mb4_0900_ai_ci | 没有PAD |
| utf8mb4_de_pb_0900_ai_ci | 没有PAD |
| utf8mb4_is_0900_ai_ci | 没有PAD |
...
| utf8mb4_ja_0900_as_cs | 没有PAD |
| utf8mb4_ja_0900_as_cs_ks | 没有PAD |
| utf8mb4_0900_as_ci | 没有PAD |
| utf8mb4_ru_0900_ai_ci | 没有PAD |
| utf8mb4_ru_0900_as_cs | 没有PAD |
| utf8mb4_zh_0900_as_cs | 没有PAD |
| utf8mb4_0900_bin | 没有PAD |
+ ---------------------------- + -------- +

具有 排序规则 的非二进制字符串值( CHAR VARCHAR TEXT )的 比较 NO PAD 与关于尾随空格的其他排序规则不同。 例如, 'a' 'a ' 比较不同的字符串,而不是相同的字符串。 这可以使用二进制排序规则来查看 utf8mb4 pad的属性 utf8mb4_bin PAD SPACE ,而 utf8mb4_0900_bin 它是 NO PAD 因此,涉及 utf8mb4_0900_bin 不添加尾随空格的 操作 以及涉及具有尾随空格的字符串的比较可能因两个排序规则而不同:

MySQL的> CREATE TABLE t1 (c CHAR(10) COLLATE utf8mb4_bin);
查询正常,0行受影响(0.03秒)

MySQL的> INSERT INTO t1 VALUES('a');
查询OK,1行受影响(0.01秒)

MySQL的> SELECT * FROM t1 WHERE c = 'a ';
+ ------ +
| c |
+ ------ +
| a |
+ ------ +
1排(0.00秒)

MySQL的> ALTER TABLE t1 MODIFY c CHAR(10) COLLATE utf8mb4_0900_bin;
查询OK,0行受影响(0.02秒)
记录:0重复:0警告:0

MySQL的> SELECT * FROM t1 WHERE c = 'a ';
空集(0.00秒)

语言特定的排序规则

如果仅基于Unicode归类算法(UCA)的排序对语言不起作用,则MySQL实现特定于语言的Unicode排序规则。 特定于语言的排序规则是基于UCA的,具有其他语言定制规则。 此类规则的示例将在本节后面部分中介绍。 有关特定语言排序的问题, unicode.org http://www.unicode.org/cldr/charts/30/collat​​ion/index.html上 提供了Common Locale Data Repository(CLDR)排序规则图表

例如,非 utf8mb4_0900_ai_ci 语言 特定 特定于 语言的 Unicode排序规则各自具有以下特征: utf8mb4_LOCALE_0900_ai_ci

  • 排序规则基于UCA 9.0.0和CLDR v30,重音不敏感,不区分大小写。 这些特征由 _0900 _ai _ci 在排序规则名称中表示。 例外: utf8mb4_la_0900_ai_ci 不基于CLDR,因为在CLDR中未定义Classical Latin。

  • 排序规则适用于[U + 0,U + 10FFFF]范围内的所有字符。

  • 如果排序规则不是特定于语言的,则会按默认顺序对所有字符(包括增补字符)进行排序(如下所述)。 如果排序规则是特定于语言的,则它会根据特定于语言的规则对语言的字符进行排序,并按默认顺序对语言中的字符进行排序。

  • 默认情况下,排序规则根据表中指定的权重值对具有DUCET表(默认Unicode排序规则元素表)中列出的代码点的字符进行排序。 排序规则使用隐式权重值对没有DUCET表中列出的代码点的字符进行排序,该隐式权重值是根据UCA构造的。

  • 对于非语言特定的排序规则,收缩序列中的字符被视为单独的字符。 对于特定于语言的排序规则,收缩可能会更改字符排序顺序。

包含下表中显示的区域设置代码或语言名称的排序规则名称是特定于语言的排序规则。 Unicode字符集可以包括一种或多种这些语言的排序规则。

表10.3 Unicode排序规则语言说明符

语言 语言说明
中文 zh
古典拉丁文 la 要么 roman
克罗地亚 hr 要么 croatian
捷克 cs 要么 czech
丹麦 da 要么 danish
世界语 eo 要么 esperanto
爱沙尼亚语 et 要么 estonian
德国电话簿订单 de_pb 要么 german2
匈牙利 hu 要么 hungarian
冰岛的 is 要么 icelandic
日本 ja
拉脱维亚 lv 要么 latvian
立陶宛 lt 要么 lithuanian
波斯语 persian
抛光 pl 要么 polish
罗马尼亚 ro 要么 romanian
俄语 ru
僧伽罗语 sinhala
斯洛伐克 sk 要么 slovak
斯洛文尼亚 sl 要么 slovenian
现代西班牙语 es 要么 spanish
传统西班牙语 es_trad 要么 spanish2
瑞典 sv 要么 swedish
土耳其 tr 要么 turkish
越南 vi 要么 vietnamese

克罗地亚归类是专为这些克罗地亚字母: Č Ć Đ Lj Nj Š Ž

丹麦的整理也可以用于挪威语。

对于日语, utf8mb4 字符集包括 utf8mb4_ja_0900_as_cs utf8mb4_ja_0900_as_cs_ks 排序。 这两种排序都是重音敏感且区分大小写的。 utf8mb4_ja_0900_as_cs_ks 也是假名敏感,并且将片假名字符与平假名字符区分开来,而 utf8mb4_ja_0900_as_cs 将片假名和平假名字符视为排序等同。 需要日语整理而非假名敏感度的应用程序可 utf8mb4_ja_0900_as_cs 用于更好的排序性能。 utf8mb4_ja_0900_as_cs 使用三个重量级别进行分类; utf8mb4_ja_0900_as_cs_ks 使用四个。

对于重音不敏感的经典拉丁校对, I 并且 J 比较相等, U 并且 V 比较相等。 I J ,和 U V 比较的基础信水平相等。 换句话说, J 被视为重音 I ,并被 U 视为重音 V

西班牙语整理可用于现代和传统的西班牙语。 对于两者, ñ (n-tilde)是 n 之间的单独字母 o 另外,对于传统的西班牙语, ch c 之间的单独字母 d ,并且 ll l 之间的单独字母 m

传统的西班牙语排序也可用于阿斯图里亚斯语和加利西亚语。

瑞典的整理包括瑞典的规则。 例如,在瑞典语中,以下关系成立,这不是德语或法语发言者所期望的:

Ü= Y <Ö

_general_ci Versus _unicode_ci Collat​​ions

对于任何Unicode字符集,使用 xxx_general_ci 排序规则 执行的操作 比排序规则更快 xxx_unicode_ci 例如,比较的比较 utf8_general_ci 速度更快,但比正确性稍差 utf8_unicode_ci 原因是 utf8_unicode_ci 支持扩展等映射; 也就是说,当一个字符与其他字符的组合相等时。 例如, ß 等于 ss 德语和其他一些语言。 utf8_unicode_ci 还支持收缩和可忽略的角色。 utf8_general_ci 是一种遗留的排序规则,不支持扩展,收缩或可忽略的字符。 它只能在字符之间进行一对一的比较。

为了进一步举例说明,下面的等式成立两者 utf8_general_ci utf8_unicode_ci (对于此在比较或搜索的效果,见 第10.8.6,“影响的排序规则的例子” ):

Ä= A.
Ö= O.
Ü= U.

排序规则之间的区别在于 utf8_general_ci

ß= s

虽然这是真的 utf8_unicode_ci ,它支持德国DIN-1排序(也称为字典顺序):

ß= ss

utf8 如果排序 utf8_unicode_ci 不适用于某种语言, MySQL会实现 特定于语言的排序规则 例如, utf8_unicode_ci 适用于德语字典顺序和法语,因此无需创建特殊 utf8 排序规则。

utf8_general_ci 德语和法语也令人满意,除了 ß 等于 s ,而不是 等于 ss 如果您的应用程序可以接受,那么您应该使用 utf8_general_ci 因为它更快。 如果这是不可接受的(例如,如果您需要德语字典顺序),请使用, utf8_unicode_ci 因为它更准确。

如果您需要德国DIN-2(电话簿)订购,请使用 utf8_german2_ci 排序规则,该排序规则将以下几组字符进行比较:

Ä=Æ= AE
Ö=Œ= OE
Ü= UE
ß= ss

utf8_german2_ci 类似于 latin1_german2_ci ,但后者不 Æ 等于等于 AE Œ 等于 OE 没有 utf8_german_ci 相应 latin1_german_ci 的德国字典顺序,因为 utf8_general_ci 足够。

字符整理权重

角色的整理重量确定如下:

  • 对于除 _bin (二进制) 排序规则之外的所有Unicode排序规则 ,MySQL执行表查找以查找字符的排序权重。

  • 对于 _bin 排序规则除外 utf8mb4_0900_bin ,权重基于代码点,可能添加前导零字节。

  • 因为 utf8mb4_0900_bin ,权重是 utf8mb4 编码字节。 排序顺序与之相同 utf8mb4_bin ,但速度要快得多。

可以使用该 WEIGHT_STRING() 功能 显示整理权重 (请参见 第12.5节“字符串函数” 。)如果排序规则使用权重查找表,但表中不存在字符(例如,因为它是 字符),则排序权重确定变得更加复杂:

  • 对于一般collat​​ions( xxx_general_ci )中的 BMP字符 ,权重是代码点。

  • 对于UCA归类中的BMP字符(例如, xxx_unicode_ci 以及特定 语言的归类),以下算法适用:

    if(code> = 0x3400 && code <= 0x4DB5)
      base = 0xFB80; / * CJK表意文字扩展* /
    否则if(code> = 0x4E00 && code <= 0x9FA5)
      base = 0xFB40; / * CJK表意文字* /
    其他
      base = 0xFBC0; / *所有其他字符* /
    aaaa = base +(代码>> 15);
    bbbb =(代码和0x7FFF)| 为0x8000;
    

    结果是两个整理元素的序列, aaaa 然后是 bbbb 例如:

    MySQL的> SELECT HEX(WEIGHT_STRING(_ucs2 0x04CF COLLATE ucs2_unicode_ci));
    + ------------------------------------------------- --------- +
    | HEX(WEIGHT_STRING(_ucs2 0x04CF COLLATE ucs2_unicode_ci))|
    + ------------------------------------------------- --------- +
    | FBC084CF |
    + ------------------------------------------------- --------- +
    

    因此, U+04cf CYRILLIC SMALL LETTER PALOCHKA 在所有UCA 4.0.0校对中,大于 U+04c0 CYRILLIC LETTER PALOCHKA 使用UCA 5.2.0排序规则,所有palochkas排在一起。

  • 对于一般校对中的补充字符,权重是权重 0xfffd REPLACEMENT CHARACTER 对于UCA 4.0.0排序规则中的补充字符,它们的整理权重是 0xfffd 也就是说,对于MySQL,所有的补充字符彼此相等,并且大于几乎所有BMP字符。

    Deseret字符的示例和 COUNT(DISTINCT)

    CREATE TABLE t(s1 VARCHAR(5)CHARACTER SET utf32 COLLATE utf32_unicode_ci);
    插入值(0xfffd); / *替换字符* /
    插入到值(0x010412); / * DESERET CAPITAL LETTER BEE * /
    插入到值(0x010413); / * DESERET CAPITAL LETTER TEE * /
    SELECT COUNT(DISTINCT s1)FROM t;
    

    结果是2,因为在MySQL xxx_unicode_ci 排序规则中,替换字符的权重为 0x0dc6 ,而Deseret Bee和Deseret Tee的权重均为 0xfffd (如果使用 utf32_general_ci 排序规则,结果为1,因为所有三个字符都具有 0xfffd 该排序规则 的权重 。)

    楔形文字符号的示例 WEIGHT_STRING()

    / *
    INSERT字符串中的四个字符是
    00000041 #LATIN CAPITAL LETTER A
    0001218F #CUNEIFORM SIGN KAB
    000121A7 #CUNEIFORM SIGN KISH
    00000042 #LATIN CAPITAL LETTER B
    * /
    CREATE TABLE t(s1 CHAR(4)CHARACTER SET utf32 COLLATE utf32_unicode_ci);
    插入到VALUES(0x000000410001218f000121a700000042);
    SELECT HEX(WEIGHT_STRING(s1))FROM t;
    

    结果是:

    0E33 FFFD FFFD 0E4A
    

    0E33 并且 0E4A UCA 4.0.0 中的主要权重 FFFD 是KAB和KISH的重量。

    所有补充字符彼此相等的规则不是最优的,但预计不会引起麻烦。 这些字符非常罕见,因此多字符字符串完全由补充字符组成是非常罕见的。 在日本,由于补充字符是不明显的汉字表意文字,因此典型的用户并不关心他们的订单。 如果您真的想要按MySQL规则排序的行,其次是按代码点值排序,那么很容易:

    ORDER BY s1 COLLATE utf32_unicode_ci,s1 COLLATE utf32_bin
    
  • 对于基于UCA版本高于4.0.0的 xxx_unicode_520_ci 补充字符 (例如 ),补充字符不一定都具有相同的整理权重。 有些人从UCA allkeys.txt 文件中 有明确的权重 其他人根据此算法计算权重:

    aaaa = base +(代码>> 15);
    bbbb =(代码和0x7FFF)| 为0x8000;
    

有之间的差异 的字符的代码值排序 按字符的二进制表示 订购 只出现一个与别不同 utf16_bin ,因为代理人的。

假设 utf16_bin (二进制排序规则 utf16 )是 逐字节 的二进制比较 而不是 逐个字符”。 如果是这样的话,字符的顺序 utf16_bin 将与顺序不同 utf8_bin 例如,下图显示了两个罕见的字符。 第一个字符在范围内 E000 - FFFF 因此它大于代理但小于补充。 第二个字符是补充。

代码点字符utf8 utf16
---------- --------- ---- -----
0FF9D HALFWIDTH KATAKANA LETTER N EF BE 9D FF 9D
10384 UGARITIC LETTER DELTA F0 90 8E 84 D8 00 DF 84

图表中的两个字符按代码点值排序,因为 0xff9d < 0x10384 它们按 utf8 价值 排序, 因为 0xef < 0xf0 但是 utf16 如果我们使用逐字节比较, 它们不按 排序 ,因为 0xff > 0xd8

所以MySQL的 utf16_bin 整理不是 逐字节”。 它是 代码点。 当MySQL看到补充字符编码时 utf16 ,它会转换为字符的代码点值,然后进行比较。 因此, utf8_bin utf16_bin 订单相同。 这与UCS_BASIC排序规则的SQL:2008标准要求一致: UCS_BASIC是一种排序规则,其排序完全由要排序的字符串中的字符的Unicode标量值确定。 它适用于UCS角色曲目。 由于每个字符集都是UCS指令集的子集,因此UCS_BASIC校对可能适用于每个字符集。 注11:字符的Unicode标量值是其代码点,视为无符号整数。

如果是字符集 ucs2 ,则比较是逐字节的,但 ucs2 字符串不应包含代理项。

杂项信息

xxx_general_mysql500_ci 归类保留原始的预5.1.24排序 xxx_general_ci 排序规则,并允许为MySQL 5.1.24(错误#27877)之前创建的表升级。

10.10.2西欧字符集

西欧的字符集涵盖了大多数西欧语言,如法语,西班牙语,加泰罗尼亚语,巴斯克语,葡萄牙语,意大利语,阿尔巴尼亚语,荷兰语,德语,丹麦语,瑞典语,挪威语,芬兰语,法罗语,冰岛语,爱尔兰语,苏格兰语和英语。

  • ascii (US ASCII)排序规则:

    • ascii_bin

    • ascii_general_ci (默认)

  • cp850 (DOS西欧)排序规则:

    • cp850_bin

    • cp850_general_ci (默认)

  • dec8 (DEC西欧)整理:

    • dec8_bin

    • dec8_swedish_ci (默认)

  • hp8 (HP西欧)排序规则:

    • hp8_bin

    • hp8_english_ci (默认)

  • latin1 (cp1252西欧)整理:

    • latin1_bin

    • latin1_danish_ci

    • latin1_general_ci

    • latin1_general_cs

    • latin1_german1_ci

    • latin1_german2_ci

    • latin1_spanish_ci

    • latin1_swedish_ci (默认)

    MySQL latin1 与Windows cp1252 字符集 相同 这意味着它是一样的官方 ISO 8859-1 或IANA(互联网编号分配机构) latin1 ,不同的是IANA latin1 治疗之间的代码点 0x80 ,并 0x9f 不确定的, 然而 cp1252 ,因此MySQL的 latin1 ,分配这些职位的字符。 例如, 0x80 是欧元符号。 对于 未定义 条目 cp1252 ,MySQL转换 0x81 为Unicode 0x0081 0x8d to 0x008d 0x8f to 0x008f 0x90 to 0x0090 0x9d to 0x009d

    latin1_swedish_ci 整理是很可能被用来深受广大客户的MySQL的默认。 虽然经常说它是基于瑞典/芬兰的整理规则,但瑞典人和芬兰人不同意这一说法。

    这些 latin1_german1_ci latin1_german2_ci 整理基于DIN-1和DIN-2标准,其中DIN代表 DeutschesInstitutfürNormung (德国相当于ANSI)。 DIN-1被称为 字典整理 ,DIN-2被称为 电话簿整理”。 有关比较或搜索时效果的示例,请参见 第10.8.6节”整理效果示例“

    • latin1_german1_ci (字典)规则:

      Ä= A.
      Ö= O.
      Ü= U.
      ß= s
      
    • latin1_german2_ci (电话簿)规则:

      Ä= AE
      Ö= OE
      Ü= UE
      ß= ss
      

    latin1_spanish_ci 整理中, ñ (n-tilde)是 n 之间的单独字母 o

  • macroman (Mac West European)排序规则:

    • macroman_bin

    • macroman_general_ci (默认)

  • swe7 (7位瑞典语)整理:

    • swe7_bin

    • swe7_swedish_ci (默认)

10.10.3中欧字符集

MySQL为捷克共和国,斯洛伐克,匈牙利,罗马尼亚,斯洛文尼亚,克罗地亚,波兰和塞尔维亚(拉丁美洲)使用的字符集提供了一些支持。

  • cp1250 (Windows中欧)排序规则:

    • cp1250_bin

    • cp1250_croatian_ci

    • cp1250_czech_cs

    • cp1250_general_ci (默认)

    • cp1250_polish_ci

  • cp852 (DOS中欧)排序规则:

    • cp852_bin

    • cp852_general_ci (默认)

  • keybcs2 (DOS Kamenicky Czech-Slovak)整理:

    • keybcs2_bin

    • keybcs2_general_ci (默认)

  • latin2 (ISO 8859-2中欧)整理:

    • latin2_bin

    • latin2_croatian_ci

    • latin2_czech_cs

    • latin2_general_ci (默认)

    • latin2_hungarian_ci

  • macce (Mac Central European)排序规则:

    • macce_bin

    • macce_general_ci (默认)

10.10.4南欧和中东字符集

MySQL支持的南欧和中东字符集包括亚美尼亚语,阿拉伯语,格鲁吉亚语,希腊语,希伯来语和土耳其语。

  • armscii8 (ARMSCII-8亚美尼亚语)整理:

    • armscii8_bin

    • armscii8_general_ci (默认)

  • cp1256 (Windows阿拉伯语)排序规则:

    • cp1256_bin

    • cp1256_general_ci (默认)

  • geostd8 (GEOSTD8格鲁吉亚语)整理:

    • geostd8_bin

    • geostd8_general_ci (默认)

  • greek (ISO 8859-7希腊语)整理:

    • greek_bin

    • greek_general_ci (默认)

  • hebrew (ISO 8859-8希伯来语)整理:

    • hebrew_bin

    • hebrew_general_ci (默认)

  • latin5 (ISO 8859-9土耳其语)整理:

    • latin5_bin

    • latin5_turkish_ci (默认)

10.10.5波罗的海字符集

波罗的海字符集涵盖爱沙尼亚语,拉脱维亚语和立陶宛语。

  • cp1257 (Windows Baltic)排序规则:

    • cp1257_bin

    • cp1257_general_ci (默认)

    • cp1257_lithuanian_ci

  • latin7 (ISO 8859-13波罗的海)整理:

    • latin7_bin

    • latin7_estonian_cs

    • latin7_general_ci (默认)

    • latin7_general_cs

10.10.6西里尔字符集

西里尔字符集和校对用于白俄罗斯语,保加利亚语,俄语,乌克兰语和塞尔维亚语(西里尔语)。

  • cp1251 (Windows Cyrillic)排序规则:

    • cp1251_bin

    • cp1251_bulgarian_ci

    • cp1251_general_ci (默认)

    • cp1251_general_cs

    • cp1251_ukrainian_ci

  • cp866 (DOS俄罗斯)整理:

    • cp866_bin

    • cp866_general_ci (默认)

  • koi8r (KOI8-R Relcom Russian)整理:

    • koi8r_bin

    • koi8r_general_ci (默认)

  • koi8u (KOI8-U乌克兰语)整理:

    • koi8u_bin

    • koi8u_general_ci (默认)

10.10.7亚洲字符集

我们支持的亚洲字符集包括中文,日文,韩文和泰文。 这些可能很复杂。 例如,中文集必须允许数千个不同的字符。 有关 和的 更多信息 请参见 第10.10.7.1节“cp932字符集” cp932 sjis 字符集的 有关 中国国家标准GB 18030的字符集支持的其他信息 请参见 第10.10.7.2节“gb18030字符集”

有关MySQL中亚洲字符集支持的一些常见问题和问题的答案,请参见 第A.11节“MySQL 8.0常见问题解答:MySQL中文,日文和韩文字符集”

  • big5 (Big5繁体中文)整理:

    • big5_bin

    • big5_chinese_ci (默认)

  • cp932 (SJIS for Windows Japanese)排序规则:

    • cp932_bin

    • cp932_japanese_ci (默认)

  • eucjpms (UJIS for Windows Japanese)排序规则:

    • eucjpms_bin

    • eucjpms_japanese_ci (默认)

  • euckr (EUC-KR韩国)整理:

    • euckr_bin

    • euckr_korean_ci (默认)

  • gb2312 (GB2312简体中文)整理:

    • gb2312_bin

    • gb2312_chinese_ci (默认)

  • gbk (GBK简体中文)整理:

    • gbk_bin

    • gbk_chinese_ci (默认)

  • gb18030 (中国国家标准GB18030)整理:

    • gb18030_bin

    • gb18030_chinese_ci (默认)

    • gb18030_unicode_520_ci

  • sjis (Shift-JIS Japanese)整理:

    • sjis_bin

    • sjis_japanese_ci (默认)

  • tis620 (TIS620 Thai)整理:

    • tis620_bin

    • tis620_thai_ci (默认)

  • ujis (EUC-JP日文)整理:

    • ujis_bin

    • ujis_japanese_ci (默认)

big5_chinese_ci 整理排序笔划数。

10.10.7.1 cp932字符集

为什么是 cp932 需要?

在MySQL中, sjis 字符集对应于 Shift_JIS IANA定义 字符集,它支持JIS X0201和JIS X0208字符。 (看到 http://www.iana.org/assignments/character-sets 。)

但是, SHIFT JIS 的含义 作为描述性术语 变得非常模糊,并且通常包括 Shift_JIS 由各种供应商定义 的扩展

例如, 日语Windows环境中使用的 SHIFT JIS 是Microsoft扩展名, Shift_JIS 其确切名称为 Microsoft Windows Codepage : 932 cp932 除了支持的字符外 Shift_JIS ,还 cp932 支持扩展字符,如NEC特殊字符,NEC选择的IBM扩展字符和IBM选定的字符。

许多日本用户在使用这些扩展字符时遇到了问题。 这些问题源于以下因素:

  • MySQL自动转换字符集。

  • 字符集使用Unicode转换( ucs2

  • sjis 字符集不支持这些扩展字符转换。

  • 从所谓的 SHIFT JIS 到Unicode 有几种转换规则,根据转换规则 ,某些字符会根据不同的方式转换为Unicode。 MySQL仅支持其中一条规则(稍后介绍)。

MySQL cp932 字符集旨在解决这些问题。

因为MySQL支持字符集转换,所以将IANA Shift_JIS IANA分开是很重要的 cp932 为两个不同的字符集,因为它们提供不同的转换规则。

怎么 cp932 有所不同 sjis

cp932 字符集不同于 sjis 在以下方面:

对于某些字符,转换和转换 ucs2 是不同的 sjis cp932 下表说明了这些差异。

转换为 ucs2

sjis / cp932 价值 sjis - > ucs2 转换 cp932 - > ucs2 转换
5C 005C 005C
7E 007E 007E
815C 2015年 2015年
815F 005C FF3C
8160 301C FF5E
8161 2016 2225
817C 2212 FF0D
8191 00A2 FFE0
8192 00A3 FFE1
81CA 00AC FFE2

转换自 ucs2

ucs2 ucs2 - > sjis 转换 ucs2 - > cp932 转换
005C 815F 5C
007E 7E 7E
00A2 8191 3F
00A3 8192 3F
00AC 81CA 3F
2015年 815C 815C
2016 8161 3F
2212 817C 3F
2225 3F 8161
301C 8160 3F
FF0D 3F 817C
FF3C 3F 815F
FF5E 3F 8160
FFE0 3F 8191
FFE1 3F 8192
FFE2 3F 81CA

任何日语字符集的用户都应该意识到使用 --character-set-client-handshake (或 --skip-character-set-client-handshake )具有重要作用。 请参见 第5.1.7节“服务器命令选项”

10.10.7.2 gb18030字符集

在MySQL中, gb18030 字符集对应于 中国国家标准GB 18030-2005:信息技术 - 中文编码字符集 ,这是中华人民共和国(PRC)的官方字符集。

MySQL gb18030字符集的特征
  • 支持GB 18030-2005标准定义的所有代码点。 范围(GB + 8431A439,GB + 90308130)和(GB + E3329A36,GB + EF39EF39)中未分配的代码点被视为' ? '(0x3F)。 未分配代码点的转换返回' ? '。

  • 支持所有GB18030代码点的UPPER和LOWER转换。 还支持由Unicode定义的大小写折叠(基于 CaseFolding-6.3.0.txt )。

  • 支持与其他字符集之间的数据转换。

  • 支持SQL语句,如 SET NAMES

  • 支持 gb18030 字符串之间的 比较 ,以及 gb18030 字符串和其他字符集的字符串 之间的 比较 如果字符串具有不同的字符集,则存在转换。 还支持包含或忽略尾随空格的比较。

  • Unicode中的专用区域(U + E000,U + F8FF)映射到 gb18030

  • (U + D800,U + DFFF)和GB18030之间没有映射。 尝试转换此范围内的代码点将返回' ? '。

  • 如果传入的序列是非法的,则返回错误或警告。 如果使用非法序列 CONVERT() ,则返回错误。 否则,将返回警告。

  • 为了与 utf8 一致, utf8mb4 连字不支持UPPER。

  • 使用 gb18030_unicode_520_ci 排序规则 时,搜索连字也匹配大写连字

  • 如果一个字符有多个大写字符,则所选的大写字符是小写字符本身的字符。

  • 最小多字节长度为1,最大值为4.字符集使用前1或2个字节确定序列的长度。

支持的排序规则
  • gb18030_bin :二进制排序规则。

  • gb18030_chinese_ci :默认排序规则,支持拼音。 非中文字符的排序基于原始排序键的顺序。 原始排序键 GB(UPPER(ch)) 是否 UPPER(ch) 存在。 否则,原始排序键是 GB(ch) 中文字符根据Unicode公共区域设置数据存储库(CLDR 24)中定义的拼音排序规则进行排序。 非中文字符在中文字符之前排序 GB+FE39FE39 ,但代码点最大值 除外

  • gb18030_unicode_520_ci :Unicode排序规则。 如果需要确保正确排序连字,请使用此排序规则。

10.10.8二进制字符集

binary 字符集是chararcter设置二进制串,其是字节序列。 binary 字符集有一个整理,也叫 binary 比较和排序基于数字字节值。 结果是字母组和重音差异在比较中很重要。 也就是说, binary 整理是区分大小写并且区分重音。

mysql> SET NAMES 'binary';
mysql>SELECT CHARSET('abc'), COLLATION('abc');
+ ---------------- + ------------------ +
| CHARSET('abc')| COLLATION('abc')|
+ ---------------- + ------------------ +
| 二进制| 二进制|
+ ---------------- + ------------------ +
MySQL的> SELECT 'abc' = 'ABC', 'a' = 'ä';
+ --------------- + ------------ +
| 'abc'='ABC'| 'a'='ä'|
+ --------------- + ------------ +
| 0 | 0 |
+ --------------- + ------------ +

有关之间的差异信息 binary 的核对 binary 集字符和 _bin 的非二进制字符集的排序规则,请参见 第10.8.5节,“BINARY排序相比_bin归类”

要将字符串表达式转换为二进制字符串,这些构造中的任何一个都是等效的:

二元expr
铸造(expr作为二进制)
CONVERT(expr使用二进制)

如果 expr 是字符串文字,则 _binary 可以使用介绍人将其指定为二进制字符串。 例如:

_binary'a'

所述 _binary 导引器是允许用于十六进制文字和比特值文字为好,但不必要的; 默认情况下,此类文字是二进制字符串。

有关介绍人的更多信息,请参见 第10.3.8节“字符集介绍人”

10.11设置错误消息语言

默认情况下, mysqld 会生成英文错误消息,但它们可以用其他几种语言显示:捷克语,丹麦语,荷兰语,爱沙尼亚语,法语,德语,希腊语,匈牙利语,意大利语,日语,韩语,挪威语,挪威语,波兰语,葡萄牙语,罗马尼亚语,俄语,斯洛伐克语,西班牙语或瑞典语。 这适用于服务器写入错误日志并发送给客户端的消息。

要选择服务器写入错误消息的语言,请按照本节中的说明进行操作。 有关更改错误消息(而不是语言)的字符集的信息,请参见 第10.6节“错误消息字符集” 有关配置错误日志记录的一般信息,请参见 第5.4.2节“错误日志”

服务器使用以下规则搜索错误消息文件:

  • 它在由两个系统变量值构造的目录中查找文件, lc_messages_dir 并将 lc_messages 后者转换为语言名称。 假设您使用以下命令启动服务器:

    mysqld --lc_messages_dir = / usr / share / mysql --lc_messages = fr_FR
    

    在这种情况下, mysqld 将语言环境映射 fr_FR 到语言 french 并在 /usr/share/mysql/french 目录中 查找错误文件

    默认情况下,语言文件位于 MySQL基目录下的目录中。 share/mysql/LANGUAGE

  • 如果在刚刚描述的构造目录中找不到消息文件,则服务器会忽略该 lc_messages 值并仅使用该 lc_messages_dir 值作为查看的位置。

  • 如果服务器找不到配置的消息文件,它会将消息写入错误日志以指示问题,并默认为内置英语消息。

lc_messages_dir 系统变量只能在服务器启动时设置并且只有在运行一个全球性的只读值。 lc_messages 可以在服务器启动时设置,并具有可在运行时修改的全局和会话值。 因此,可以在服务器运行时更​​改错误消息语言,并且每个客户端可以通过将其会话 lc_messages 值设置为所需的区域设置名称 来拥有自己的错误消息语言 例如,如果服务器使用 fr_FR 区域设置来显示错误消息,则客户端可以执行此语句以接收英语错误消息:

SET lc_messages ='en_US';

10.12添加字符集

本节讨论向MySQL添加字符集的过程。 正确的过程取决于字符集是简单还是复杂:

  • 如果字符集不需要特殊的字符串整理例程来进行排序,并且不需要多字节字符支持,那么它很简单。

  • 如果字符集需要这些功能中的任何一个,那么它很复杂。

例如, greek swe7 简单的字符集,而 big5 czech 是复杂的字符集。

要使用以下说明,您必须具有MySQL源代码分发。 在说明中, MYSET 表示要添加的字符集的名称。

  1. 添加 <charset> 元素 MYSET sql/share/charsets/Index.xml 文件。 使用文件中的现有内容作为添加新内容的指南。 latin1 <charset> 元素的 部分列表 如下:

    <charset name =“latin1”>
      <家庭>西</家庭>
      <description> cp1252西欧</ description>
      ...
      <collat​​ion name =“latin1_swedish_ci”id =“8”order =“Finnish,Swedish”>
        <标志>主</标志>
        <标志>编译</标志>
      </核对>
      <collat​​ion name =“latin1_danish_ci”id =“15”order =“Danish”/>
      ...
      <collat​​ion name =“latin1_bin”id =“47”order =“Binary”>
        <标志>二进制</标志>
        <标志>编译</标志>
      </核对>
      ...
    </字符集>
    

    <charset> 元素必须列出的字符集所有的排序规则。 这些必须至少包括二进制排序规则和默认(主要)排序规则。 默认排序规则通常使用后缀 general_ci (通用,不区分大小写) 命名 二进制排序规则可能是默认排序规则,但通常它们是不同的。 默认排序规则应该有一个 primary 标志。 二进制排序规则应该有一个 binary 标志。

    您必须为每个排序规则分配唯一的ID号。 1024到2047之间的ID范围保留给用户定义的排序规则。 要查找当前使用的归类ID的最大值,请使用以下查询:

    SELECT MAX(ID)FROM INFORMATION_SCHEMA.COLLATIONS;
    
  2. 此步骤取决于您是要添加简单字符集还是复杂字符集。 简单字符集仅需要配置文件,而复杂字符集则需要定义归类函数,多字节函数或两者的C源文件。

    对于简单字符集,请创建 MYSET.xml 描述字符集属性 的配置文件 sql/share/charsets 目录中 创建此文件 您可以使用副本 latin1.xml 作为此文件的基础。 该文件的语法非常简单:

    • 注释被写为普通的XML注释( )。 <!-- text -->

    • <map> 数组元素中的 单词 由任意数量的空格分隔。

    • <map> 数组元素中的 每个单词 必须是十六进制格式的数字。

    • <map> 元素 数组元素 <ctype> 有257个单词。 之后的其他 <map> 数组元素有256个字。 请参见 第10.12.1节“字符定义数组”

    • 对于 <charset> 字符集元素中 列出的每个排序规则 Index.xml MYSET.xml 必须包含 <collation> 定义字符排序 元素。

    对于复杂字符集,请创建描述字符集属性的C源文件,并定义正确执行字符集操作所需的支持例程:

  3. 修改配置信息。 使用现有配置信息作为添加信息的指南 MYSYS 此处的示例假定字符集具有默认和二进制排序规则,但如果 MYSET 具有其他排序规则, 则需要更多行

    1. 编辑 mysys/charset-def.c 注册 新字符集的排序规则。

      将这些行添加到 声明 部分:

      #ifdef HAVE_CHARSET_ MYSET
      extern CHARSET_INFO my_charset_MYSET _general_ci;
      extern CHARSET_INFO my_charset_MYSET _bin;
      #万一
      

      将这些行添加到 注册 部分:

      #ifdef HAVE_CHARSET_ MYSET
        add_compiled_collat​​ion(&my_charset_MYSET _general_ci);
        add_compiled_collat​​ion(my_charset_MYSET _bin);
      #万一
      
    2. 如果字符集使用 ,编辑 并添加 变量 的定义 ctype-MYSET.c strings/CMakeLists.txt ctype-MYSET.c STRINGS_SOURCES

    3. 编辑 cmake/character_sets.cmake

      1. 按字母顺序 添加 MYSET 到的值 CHARSETS_AVAILABLE

      2. 按字母顺序 添加 MYSET CHARSETS_COMPLEX 即使对于简单的字符集也需要这样,否则 CMake 将无法识别 -DDEFAULT_CHARSET=MYSET

  4. 重新配置,重新编译和测试。

10.12.1字符定义数组

每个简单字符集都有一个位于 sql/share/charsets 目录中 的配置文件 对于名为的字符集 MYSYS ,该文件已命名 MYSET.xml 它使用 <map> 数组元素列出字符集属性。 <map> 元素出现在这些元素中:

  • <ctype> 定义每个字符的属性。

  • <lower> <upper> 列出小写和大写字符。

  • <unicode> 将8位字符值映射到Unicode值。

  • <collation> 元素表示用于比较和排序的字符排序,每个排序规则一个元素。 二进制排序规则不需要 <map> 元素,因为字符代码本身提供排序。

对于 目录 中的 文件中 实现的复杂字符集 ,有相应的数组: 等等。 并非每个复杂的字符集都包含所有数组。 有关 示例, 另请参阅现有 文件。 有关 其他信息, 请参阅 目录中 文件 ctype-MYSET.c strings ctype_MYSET[] to_lower_MYSET[] ctype-*.c CHARSET_INFO.txt strings

大多数数组都按字符值索引,并且有256个元素。 <ctype> 数组由字符值+ 1索引,并具有257个元素。 这是处理的传统惯例 EOF

<ctype> 数组元素是位值。 每个元素描述字符集中单个字符的属性。 每个属性都与位掩码相关联,如下所述 include/m_ctype.h

#define _MY_U 01 / *大写* /
#define _MY_L 02 / *小写* /
#define _MY_NMR 04 / *数字(数字)* /
#define _MY_SPC 010 / *间距字符* /
#define _MY_PNT 020 / *标点* /
#define _MY_CTR 040 / *控制字符* /
#define _MY_B 0100 / *空白* /
#define _MY_X 0200 / * heXadecimal digit * /

<ctype> 给定字符 值应该是描述字符的适用位掩码值的并集。 例如, 'A' 是一个大写字符( _MY_U )以及十六进制数字( _MY_X ),因此它的 ctype 值应该像这样定义:

ctype ['A'+ 1] = _MY_U | _MY_X = 01 | 0200 = 0201

位掩码值 m_ctype.h 是八进制值,但是 <ctype> 数组 的元素 MYSET.xml 应该写为十六进制值。

<lower> <upper> 阵列保持对应于该字符集的每个成员的大写和小写字符。 例如:

lower ['A']应该包含'a'
upper ['a']应该包含'A'

每个 <collation> 数组都指示如何排序字符以进行比较和排序。 MySQL根据此信息的值对字符进行排序。 在某些情况下,这与 <upper> 数组 相同 ,这意味着排序不区分大小写。 有关更复杂的排序规则(对于复杂字符集),请参见 第10.12.2节“对复杂字符集的字符串整理支持”中 的字符串整理的讨论

10.12.2复杂字符集的字符串整理支持

对于名为的简单字符集 MYSET MYSET.xml 使用 <map> 元素内的数组元素在 配置文件 中指定排序规则 <collation> 如果您的语言的排序规则太复杂而无法使用简单数组处理,则必须 目录 中的 源文件中 定义字符串整理函数 ctype-MYSET.c strings

现有字符集提供了最佳文档和示例,以说明如何实现这些功能。 再看 ctype-*.c 中的文件 strings 目录,如文件为 big5 czech gbk sjis ,和 tis160 字符集。 看看 MY_COLLATION_HANDLER 结构,看看它们是如何使用的。 有关 其他信息, 另请参阅 目录中 CHARSET_INFO.txt 文件 strings

10.12.3复杂字符集的多字节字符支持

如果要添加对 MYSET 包含多字节字符 的新字符集的支持 ,则必须 目录 中的 源文件中 使用多字节字符函数 ctype-MYSET.c strings

现有字符集提供了最佳文档和示例,以说明如何实现这些功能。 再看 ctype-*.c 中的文件 strings 目录,如文件为 euc_kr gb2312 gbk sjis ,和 ujis 字符集。 看看 MY_CHARSET_HANDLER 结构,看看它们是如何使用的。 有关 其他信息, 另请参阅 目录中 CHARSET_INFO.txt 文件 strings

10.13为字符集添加排序规则

排序规则是一组规则,用于定义如何比较和排序字符串。 MySQL中的每个排序规则都属于一个字符集。 每个字符集至少有一个排序规则,大多数都有两个或多个排序规则。

整理根据权重对字符进行排序。 字符集中的每个字符都映射到一个权重。 具有相等权重的字符比较相等,并且具有不等权重的字符根据其权重的相对大小进行比较。

WEIGHT_STRING() 函数可用于查看字符串中字符的权重。 它返回的值表示权重是二进制字符串,因此可以方便地 以可打印的形式显示权重。 以下示例显示, 如果 字母为非 二进制不区分大小写的字符串, 则字母的字母大小的权重不同 ,但如果它是二进制字符串则不同: HEX(WEIGHT_STRING(str)) 'AaBb'

MySQL的> SELECT HEX(WEIGHT_STRING('AaBb' COLLATE latin1_swedish_ci));
+ ------------------------------------------------- ----- +
| HEX(WEIGHT_STRING('AaBb'COLLATE latin1_swedish_ci))|
+ ------------------------------------------------- ----- +
| 41414242 |
+ ------------------------------------------------- ----- +
MySQL的> SELECT HEX(WEIGHT_STRING(BINARY 'AaBb'));
+ ----------------------------------- +
| HEX(WEIGHT_STRING(BINARY'AaBb'))|
+ ----------------------------------- +
| 41614262 |
+ ----------------------------------- +

MySQL支持几种排序规则实现,如 第10.13.1节“排序规则实现类型”中所述 其中一些可以添加到MySQL而无需重新编译:

  • 8位字符集的简单归类。

  • 基于UCA的Unicode字符集排序规则。

  • 二进制( xxx_bin )排序规则。

以下部分描述如何将前两种类型的排序规则添加到现有字符集。 所有现有字符集都已经具有二进制排序规则,因此这里不需要描述如何添加一个。

添加新排序规则的过程摘要:

  1. 选择排序规则ID。

  2. 添加命名归类的配置信息并描述字符排序规则。

  3. 重启服务器。

  4. 验证是否存在排序规则。

这里的说明仅涵盖可以在不重新编译MySQL的情况下添加的排序规则。 要添加需要重新编译的排序规则(通过C源文件中的函数实现),请使用 第10.12节“添加字符集”中的说明 但是,只需修改现有字符集的相应文件,而不是添加完整字符集所需的所有信息。 也就是说,根据字符集当前排序规则已经存在的内容,为新排序规则添加数据结构,函数和配置信息。

注意

如果修改现有排序规则,则可能会影响使用排序规则的列上索引的行排序。 在这种情况下,重建任何此类索引以避免诸如不正确的查询结果之类的问题。 请参见 第2.11.13节“重建或修复表或索引”

其他资源

10.13.1归类实施类型

MySQL实现了几种类型的排序规则:

8位字符集的简单归类

这种排序是使用256个权重的数组实现的,这些权重定义了从字符代码到权重的一对一映射。 latin1_swedish_ci 就是一个例子。 它是一个不区分大小写的排序规则,因此字符的大写和小写版本具有相同的权重,并且它们相等。

MySQL的> SET NAMES 'latin1' COLLATE 'latin1_swedish_ci';
查询OK,0行受影响(0.01秒)

MySQL的> SELECT HEX(WEIGHT_STRING('a')), HEX(WEIGHT_STRING('A'));
+ ------------------------- + ----------------------- -  +
| HEX(WEIGHT_STRING('a'))| HEX(WEIGHT_STRING('A'))|
+ ------------------------- + ----------------------- -  +
| 41 | 41 |
+ ------------------------- + ----------------------- -  +
1排(0.01秒)

MySQL的> SELECT 'a' = 'A';
+ ----------- +
| 'a'='A'|
+ ----------- +
| 1 |
+ ----------- +
1排(0.12秒)

有关实现说明,请参见 第10.13.3节“将简单排序添加到8位字符集”

8位字符集的复杂排序规则

这种排序规则是使用C源文件中的函数实现的,这些函数定义如何排序字符,如 第10.12节“添加字符集”中所述

非Unicode多字节字符集的排序规则

对于这种类型的排序规则,8位(单字节)和多字节字符的处理方式不同。 对于8位字符,字符代码以不区分大小写的方式映射到权重。 (例如,单字节字符 'a' 'A' 两者都具有的重量 0x41 。)对于多字节字符,有两种类型的字符代码和重量之间关系的:

  • 权重等于字符代码。 sjis_japanese_ci 是这种整理的一个例子。 多字节字符 'ぢ' 的字符代码为 0x82C0 ,而权重也是 0x82C0

    MySQL的> CREATE TABLE t1
           (c1 VARCHAR(2) CHARACTER SET sjis COLLATE sjis_japanese_ci);
    查询OK,0行受影响(0.01秒)
    
    MySQL的> INSERT INTO t1 VALUES ('a'),('A'),(0x82C0);
    查询OK,3行受影响(0.00秒)
    记录:3个重复:0个警告:0
    
    MySQL的> SELECT c1, HEX(c1), HEX(WEIGHT_STRING(c1)) FROM t1;
    + ------ + --------- + ------------------------ +
    | c1 | HEX(c1)| HEX(WEIGHT_STRING(c1))|
    + ------ + --------- + ------------------------ +
    | a | 61 | 41 |
    | A | 41 | 41 |
    | ぢ| 82C0 | 82C0 |
    + ------ + --------- + ------------------------ +
    3组(0.00秒)
    
  • 字符代码一对一地映射到权重,但代码不一定等于权重。 gbk_chinese_ci 是这种整理的一个例子。 多字节字符 '膰' 的字符代码 0x81B0 但权重为 0xC286

    MySQL的> CREATE TABLE t1
           (c1 VARCHAR(2) CHARACTER SET gbk COLLATE gbk_chinese_ci);
    查询OK,0行受影响(0.33秒)
    
    MySQL的> INSERT INTO t1 VALUES ('a'),('A'),(0x81B0);
    查询OK,3行受影响(0.00秒)
    记录:3个重复:0个警告:0
    
    MySQL的> SELECT c1, HEX(c1), HEX(WEIGHT_STRING(c1)) FROM t1;
    + ------ + --------- + ------------------------ +
    | c1 | HEX(c1)| HEX(WEIGHT_STRING(c1))|
    + ------ + --------- + ------------------------ +
    | a | 61 | 41 |
    | A | 41 | 41 |
    | 膰| 81B0 | C286 |
    + ------ + --------- + ------------------------ +
    3组(0.00秒)
    

有关实现说明,请参见 第10.12节“添加字符集”

Unicode多字节字符集的排序规则

其中一些归类基于Unicode归类算法(UCA),而其他归类算法则不是。

非UCA排序规则具有从字符代码到权重的一对一映射。 在MySQL中,这种排序规则不区分大小写并且不区分重音。 utf8_general_ci 是一个例子: 'a' 'A' 'À' ,和 'á' 每个都具有不同的字符代码,但是都具有的重量 0x0041 和比较结果为相等。

MySQL的> SET NAMES 'utf8' COLLATE 'utf8_general_ci';
查询正常,0行受影响(0.00秒)

MySQL的> CREATE TABLE t1
       (c1 CHAR(1) CHARACTER SET UTF8 COLLATE utf8_general_ci);
查询OK,0行受影响(0.01秒)

MySQL的> INSERT INTO t1 VALUES ('a'),('A'),('À'),('á');
查询OK,4行受影响(0.00秒)
记录:4个重复:0警告:0

MySQL的> SELECT c1, HEX(c1), HEX(WEIGHT_STRING(c1)) FROM t1;
+ ------ + --------- + ------------------------ +
| c1 | HEX(c1)| HEX(WEIGHT_STRING(c1))|
+ ------ + --------- + ------------------------ +
| a | 61 | 0041 |
| A | 41 | 0041 |
| À| C380 | 0041 |
| á| C3A1 | 0041 |
+ ------ + --------- + ------------------------ +
4行(0.00秒)

MySQL中基于UCA的排序规则具有以下属性:

  • 如果字符具有权重,则每个权重使用2个字节(16位)。

  • 角色可以具有零权重(或空权重)。 在这种情况下,角色是可以忽略的。 示例:“U + 0000 NULL”没有权重且可忽略。

  • 角色可能有一个重量。 示例: 'a' 重量为 0x0E33

    MySQL的> SET NAMES 'utf8' COLLATE 'utf8_unicode_ci';
    查询OK,0行受影响(0.05秒)
    
    MySQL的> SELECT HEX('a'), HEX(WEIGHT_STRING('a'));
    + ---------- + ------------------------- +
    | 十六进制('a')| HEX(WEIGHT_STRING('a'))|
    + ---------- + ------------------------- +
    | 61 | 0E33 |
    + ---------- + ------------------------- +
    1排(0.02秒)
    
  • 角色可能有很多权重。 这是一个扩展。 示例:德语字母 'ß' (SZ连字或SHARP S)的权重为 0x0FEA0FEA

    MySQL的> SET NAMES 'utf8' COLLATE 'utf8_unicode_ci';
    查询OK,0行受影响(0.11秒)
    
    MySQL的> SELECT HEX('ß'), HEX(WEIGHT_STRING('ß'));
    + ----------- + -------------------------- +
    | HEX('ß')| HEX(WEIGHT_STRING('ß'))|
    + ----------- + -------------------------- +
    | C39F | 0FEA0FEA |
    + ----------- + -------------------------- +
    1排(0.00秒)
    
  • 许多角色可能有一个重量。 这是一种收缩。 示例: 'ch' 捷克语为单个字母,重量为 0x0EE2

    MySQL的> SET NAMES 'utf8' COLLATE 'utf8_czech_ci';
    查询正常,0行受影响(0.09秒)
    
    MySQL的> SELECT HEX('ch'), HEX(WEIGHT_STRING('ch'));
    + ----------- + -------------------------- +
    | 十六进制('ch')| HEX(WEIGHT_STRING('ch'))|
    + ----------- + -------------------------- +
    | 6368 | 0EE2 |
    + ----------- + -------------------------- +
    1排(0.00秒)
    

许多字符到多重权重的映射也是可能的(这是与扩展的收缩),但MySQL不支持。

有关非UCA归类的实现说明,请参见 第10.12节“添加字符集” 有关UCA归类,请参见 第10.13.4节“将UCA归类添加到Unicode字符集”

杂项整理

还有一些不属于以前任何类别的排序规则。

10.13.2选择归类ID

每个排序规则必须具有唯一ID。 要添加排序规则,您必须选择当前未使用的ID值。 MySQL支持双字节整理ID。 1024到2047之间的ID范围保留给用户定义的排序规则。 您选择的排序规则ID将显示在以下上下文中:

要确定当前使用的最大ID,请发出以下语句:

MySQL的> SELECT MAX(ID) FROM INFORMATION_SCHEMA.COLLATIONS;
+ --------- +
| MAX(ID)|
+ --------- +
| 210 |
+ --------- +

要显示所有当前使用的ID的列表,请发出以下语句:

MySQL的> SELECT ID FROM INFORMATION_SCHEMA.COLLATIONS ORDER BY ID;
+ ----- +
| ID |
+ ----- +
| 1 |
| 2 |
| ...... |
| 52 |
| 53 |
| 57 |
| 58 |
| ...... |
| 98 |
| 99 |
| 128 |
| 129 |
| ...... |
| 210 |
+ ----- +
警告

在升级之前,您应该保存更改的配置文件。 如果您就地升级,该过程将替换您修改的文件。

10.13.3将简单排序规则添加到8位字符集

本节介绍如何通过 在MySQL 文件中 编写 <collation> <charset> 字符集描述 相关联 元素 ,为8位字符集添加简单排序规则 Index.xml 此处描述的过程不需要重新编译MySQL。 这个例子添加一个名为归类 latin1_test_ci latin1 字符集。

  1. 选择排序规则ID,如 第10.13.2节“选择排序规则ID”中所示 以下步骤使用ID为1024。

  2. 修改 Index.xml latin1.xml 配置文件。 这些文件位于 character_sets_dir 系统变量 指定的目录中 尽管您的系统上的路径名可能不同,但您可以按如下方式检查变量值:

    MySQL的> SHOW VARIABLES LIKE 'character_sets_dir';
    + -------------------- + ---------------------------- ------------- +
    | Variable_name | 价值|
    + -------------------- + ---------------------------- ------------- +
    | character_sets_dir | / user / local / mysql / share / mysql / charsets / |
    + -------------------- + ---------------------------- ------------- +
    
  3. 选择排序规则的名称并将其列在 Index.xml 文件中。 查找 <charset> 要添加排序规则的字符集的 <collation> 元素 ,并添加 指示排序规则名称和ID 元素,以将名称与ID相关联。 例如:

    <charset name =“latin1”>
      ...
      <collat​​ion name =“latin1_test_ci”id =“1024”/>
      ...
    </字符集>
    
  4. latin1.xml 配置文件中,添加一个 <collation> 命名归类的 <map> 元素, 元素 包含一个 元素, 元素定义字符代码0到255的字符代码 - 权重映射表。 <map> 元素中的 每个值 必须是十六进制格式的数字。

    <collat​​ion name =“latin1_test_ci”>
    <地图>
     00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
     10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
     20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
     30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
     40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
     50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
     60 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
     50 51 52 53 54 55 56 57 58 59 5A 7B 7C 7D 7E 7F
     80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
     90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
     A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
     B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
     41 41 41 41 5B 5D 5B 43 45 45 45 45 49 49 49 49
     44 4E 4F 4F 4F 4F 5C D7 5C 55 55 55 59 59 DE DF
     41 41 41 41 5B 5D 5B 43 45 45 45 45 49 49 49 49
     44 4E 4F 4F 4F 4F 5C F7 5C 55 55 55 59 59 DE FF
    </地图>
    </核对>
    
  5. 重新启动服务器并使用此语句验证是否存在排序规则:

    MySQL的> SHOW COLLATION WHERE Collation = 'latin1_test_ci';
    + ---------------- + --------- + ------ + --------- + ----- ----- + --------- +
    | 整理| Charset | Id | 默认| 编译| Sortlen |
    + ---------------- + --------- + ------ + --------- + ----- ----- + --------- +
    | latin1_test_ci | 拉丁1 | 1024 | | | 1 |
    + ---------------- + --------- + ------ + --------- + ----- ----- + --------- +
    

10.13.4将UCA归类添加到Unicode字符集

本节介绍如何通过 在MySQL 文件中 <collation> <charset> 字符集描述中 写入 元素 来为Unicode字符集添加UCA归类 Index.xml 此处描述的过程不需要重新编译MySQL。 它使用了区域设置数据标记语言(LDML)规范的子集,该规范可从 http://www.unicode.org/reports/tr35/获得 使用此方法,您无需定义整个排序规则。 相反,你从现有的 基础 ”开始 整理并根据它与基本整理的不同来描述新的整理。 下表列出了可以为其定义UCA归类的Unicode字符集的基本归类。 无法为其创建用户定义的UCA排序规则 utf16le ; 没有 utf16le_unicode_ci 整理可以作为这种整理的基础。

表10.4可用于用户定义的UCA排序规则的MySQL字符集

字符集 基础整理
utf8 utf8_unicode_ci
ucs2 ucs2_unicode_ci
utf16 utf16_unicode_ci
utf32 utf32_unicode_ci

以下部分显示如何添加使用LDML语法定义的排序规则,并提供MySQL中支持的LDML规则的摘要。

10.13.4.1使用LDML语法定义UCA归类

要在不重新编译MySQL的情况下为Unicode字符集添加UCA归类,请使用以下过程。 如果您不熟悉用于描述排序规则排序特征的LDML规则,请参见 第10.13.4.2节“MySQL中支持的LDML语法”

这个例子添加一个名为归类 utf8_phone_ci utf8 字符集。 排序规则是针对涉及用户发布其姓名和电话号码的Web应用程序的方案而设计的。 电话号码可以采用不同的格式:

+ 7-12345-67
+ 7-12-345-67
+7 12 345 67
+7(12)345 67
71234567

处理这些值所引起的问题是,不同的允许格式使得搜索特定电话号码变得非常困难。 解决方案是定义一个新的排序规则,重新排序标点字符,使它们可以忽略。

  1. 选择排序规则ID,如 第10.13.2节“选择排序规则ID”中所示 以下步骤使用ID 1029。

  2. 修改 Index.xml 配置文件。 此文件位于 character_sets_dir 系统变量 指定的目录中 尽管您的系统上的路径名可能不同,但您可以按如下方式检查变量值:

    MySQL的> SHOW VARIABLES LIKE 'character_sets_dir';
    + -------------------- + ---------------------------- ------------- +
    | Variable_name | 价值|
    + -------------------- + ---------------------------- ------------- +
    | character_sets_dir | / user / local / mysql / share / mysql / charsets / |
    + -------------------- + ---------------------------- ------------- +
    
  3. 选择排序规则的名称并将其列在 Index.xml 文件中。 此外,您还需要提供整理排序规则。 查找 <charset> 要添加排序规则的字符集的 <collation> 元素 ,并添加 指示排序规则名称和ID 元素,以将名称与ID相关联。 <collation> 元素内,提供 <rules> 包含排序规则 元素:

    <charset name =“utf8”>
      ...
      <collat​​ion name =“utf8_phone_ci”id =“1029”>
        <规则>
          <复位> \ u0000的</复位>
          <i> \ u0020 </ i> <! - 空间 - >
          <i> \ u0028 </ i> <! - 左括号 - >
          <i> \ u0029 </ i> <! - 右括号 - >
          <i> \ u002B </ i> <! -  plus  - >
          <i> \ u002D </ i> <! - 连字符 - >
        </规则>
      </核对>
      ...
    </字符集>
    
  4. 如果要为其他Unicode字符集进行类似的排序规则,请添加其他 <collation> 元素。 例如,要定义 ucs2_phone_ci ,请向 <collation> 元素 添加 <charset name="ucs2"> 元素。 请记住,每个排序规则都必须具有自己的唯一ID。

  5. 重新启动服务器并使用此语句验证是否存在排序规则:

    MySQL的> SHOW COLLATION WHERE Collation = 'utf8_phone_ci';
    + --------------- + --------- + ------ + --------- + ------ ---- + --------- +
    | 整理| Charset | Id | 默认| 编译| Sortlen |
    + --------------- + --------- + ------ + --------- + ------ ---- + --------- +
    | utf8_phone_ci | utf8 | 1029 | | | 8 |
    + --------------- + --------- + ------ + --------- + ------ ---- + --------- +
    

现在测试排序规则以确保它具有所需的属性。

使用新的排序规则创建包含一些示例电话号码的表格:

MySQL的> CREATE TABLE phonebook (
         name VARCHAR(64),
         phone VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_phone_ci
       );
查询正常,0行受影响(0.09秒)

MySQL的> INSERT INTO phonebook VALUES ('Svoj','+7 912 800 80 02');
查询正常,1行受影响(0.00秒)

MySQL的> INSERT INTO phonebook VALUES ('Hf','+7 (912) 800 80 04');
查询正常,1行受影响(0.00秒)

MySQL的> INSERT INTO phonebook VALUES ('Bar','+7-912-800-80-01');
查询正常,1行受影响(0.00秒)

MySQL的> INSERT INTO phonebook VALUES ('Ramil','(7912) 800 80 03');
查询正常,1行受影响(0.00秒)

MySQL的> INSERT INTO phonebook VALUES ('Sanja','+380 (912) 8008005');
查询正常,1行受影响(0.00秒)

运行一些查询以查看忽略的标点字符实际上是否被忽略以进行比较和排序:

MySQL的> SELECT * FROM phonebook ORDER BY phone;
+ ------- + -------------------- +
| 名字| 电话|
+ ------- + -------------------- +
| Sanja | +380(912)8008005 |
| 酒吧| + 7-912-800-80-01 |
| Svoj | +7 912 800 80 02 |
| 拉米尔| (7912)800 80 03 |
| Hf | +7(912)800 80 04 |
+ ------- + -------------------- +
5行(0.00秒)

MySQL的> SELECT * FROM phonebook WHERE phone='+7(912)800-80-01';
+ ------ + ------------------ +
| 名字| 电话|
+ ------ + ------------------ +
| 酒吧| + 7-912-800-80-01 |
+ ------ + ------------------ +
1排(0.00秒)

MySQL的> SELECT * FROM phonebook WHERE phone='79128008001';
+ ------ + ------------------ +
| 名字| 电话|
+ ------ + ------------------ +
| 酒吧| + 7-912-800-80-01 |
+ ------ + ------------------ +
1排(0.00秒)

MySQL的> SELECT * FROM phonebook WHERE phone='7 9 1 2 8 0 0 8 0 0 1';
+ ------ + ------------------ +
| 名字| 电话|
+ ------ + ------------------ +
| 酒吧| + 7-912-800-80-01 |
+ ------ + ------------------ +
1排(0.00秒)

10.13.4.2 MySQL支持的LDML语法

本节介绍MySQL识别的LDML语法。 这是 http://www.unicode.org/reports/tr35/上 提供的LDML规范中描述的语法的子集, 有关详细信息,请参阅。 MySQL的认识到,在许多情况下,有可能从Unicode的通用语言环境数据存储库下载一个归类定义并粘贴相关的部分(即,之间的部分的语法足够大的子集 <rules> </rules> 标签)到MySQL的 Index.xml 文件。 此处描述的规则都受支持,但字符排序仅在主要级别进行。 在次级或更高级别级别指定差异的规则被识别(因此可以包括在归类定义中),但在主级别被视为相等。

MySQL服务器在解析 Index.xml 文件 时发现问题时会生成诊断信息 请参见 第10.13.4.3节“Index.xml解析期间的诊断”

字符表示

LDML规则中命名的字符可以按字面或 格式 编写 ,其中 是十六进制Unicode代码点值。 例如, 并且 可以从字面上或者作为书面 在十六进制值内,数字 通过 不区分大小写; 并且 是等价的。 为UCA 4.0.0归类,十六进制表示法可用于仅在基本多语种平面字符,而不是为的BMP范围之外的字符 对于UCA 5.2.0归类,十六进制表示法可用于任何字符。 \unnnn nnnn A á \u0041 \u00E1 A F \u00E1 \u00e1 0000 FFFF

Index.xml 文件本身应使用UTF-8编码写入。

语法规则

LDML具有重置规则和移位规则以指定字符排序。 排序是作为一组规则给出的,这些规则以建立锚点的重置规则开始,后面是表示字符如何相对于锚点排序的转换规则。

  • 一个 <reset> 规则并不在其本身指定任何次序。 相反,它 重置 后续移位规则的顺序,以使它们与给定字符相关。 以下任一规则都会重置与该字母相关的后续轮班规则 'A'

    <复位> A </复位>
    
    <复位> \ u0041 </复位>
    
  • <p> <s> <t> 换档规则定义从另一个字符的字符的伯,仲和叔胺的差异:

    • 使用主要差异来区分单独的字母。

    • 使用次要差异来区分重音变化。

    • 使用三次差异来区分字母变体。

    这些规则中的任何一个都指定了 'G' 角色 的主要移位规则

    <P“G </ P>
    
    <P> \ u0047 </ P>
    
  • <i> 换档规则表示一个字符相同的排序到另一个。 以下规则导致 'b' 排序相同 'a'

    <复位>一</复位>
    的<i> B'/ I>
    
  • 缩略移位语法使用一对标签指定多个移位规则。 下表显示了缩写语法规则与等效非缩写规则之间的对应关系。

    表10.5缩写Shift语法

    缩写语法 非缩写语法
    <pc>xyz</pc> <p>x</p><p>y</p><p>z</p>
    <sc>xyz</sc> <s>x</s><s>y</s><s>z</s>
    <tc>xyz</tc> <t>x</t><t>y</t><t>z</t>
    <ic>xyz</ic> <i>x</i><i>y</i><i>z</i>

  • 扩展是重置规则,它为多字符序列建立锚点。 MySQL支持2到6个字符长的扩展。 以下规则 'z' 在主要级别上比在三个字符的序列中更大 'abc'

    <复位> ABC </复位>
    <P>ž</ P>
    
  • 收缩是一种对多字符序列进行排序的转换规则。 MySQL支持2到6个字符长的收缩。 以下规则将 'xyz' 主要级别 的三个字符序列设置为 大于 'a'

    <复位>一</复位>
    <P> XYZ </ P>
    
  • 长时间的扩展和长时间的收缩可以一起使用。 这些规则将 'xyz' 主要级别 的三个字符序列放在比三个字符的序列 更大的位置 'abc'

    <复位> ABC </复位>
    <P> XYZ </ P>
    
  • 正常扩展语法使用 <x> 加号 <extend> 元素来指​​定扩展。 以下规则使字符 'k' 在次级上比序列更大 'ch' 也就是说, 'k' 表现就好像它 'c' 后面跟着 一个字符扩展为 'h'

    <复位> C </复位>
    <X> <S>ķ</秒> <延伸>ħ</延伸> </ X>
    

    该语法允许长序列。 这些规则对 'ccs' 第三级的序列进行 排序比序列 更高 'cscs'

    <复位> CS </复位>
    <X> <T> CCS </吨> <延伸> CS </延伸> </ X>
    

    LDML规范将正常的扩展语法描述为 棘手的”。 详情请参阅该规范。

  • 先前的上下文语法使用 <x> 加号 <context> 元素来指​​定字符前的上下文影响其排序方式。 以下规则 '-' 在次级别上比在 以下规则中 更大 'a' ,但仅在 以下规则 '-' 发生时 'b'

    <复位>一</复位>
    <X> <上下文> B'/上下文> <S>  -  </ S> </ X>
    
  • 先前的上下文语法可以包括该 <extend> 元素。 这些规则把 'def' 在初级水平大于 'aghi' ,但只有当 'def' 后说到 'abc'

    <复位>一</复位>
    <X> <上下文> ABC </上下文> <P> DEF </ p> <延伸> GHI </延伸> </ X>
    
  • 重置规则允许 before 属性。 通常,重置规则后的移位规则表示在重置字符后排序的字符。 在具有该 before 属性 的重置规则之后的移位规则 指示在重置字符之前排序的字符。 以下规则将字符 置于主要级别 'b' 之前 'a'

    <reset before =“primary”> a </ reset>
    <P> B'/ P>
    

    允许的 before 属性值按名称或等效数值指定排序级别:

    <reset before =“primary”>
    <reset before =“1”>
    
    <reset before =“secondary”>
    <reset before =“2”>
    
    <reset before =“tertiary”>
    <reset before =“3”>
    
  • 重置规则可以命名逻辑重置位置而​​不是文字字符:

    <first_tertiary_ignorable />
    <last_tertiary_ignorable />
    <first_secondary_ignorable />
    <last_secondary_ignorable />
    <first_primary_ignorable />
    <last_primary_ignorable />
    <first_variable />
    <last_variable />
    <first_non_ignorable />
    <last_non_ignorable />
    <first_trailing />
    <last_trailing />
    

    这些规则 'z' 在主要级别上比具有默认Unicode归类元素表(DUCET)条目且不是CJK的不可签名字符更大:

    <复位> <last_non_ignorable /> </复位>
    <P>ž</ P>
    

    逻辑位置具有下表中显示的代码点。

    表10.6逻辑复位位置代码点

    逻辑位置 Unicode 4.0.0代码点 Unicode 5.2.0代码点
    <first_non_ignorable/> U + 02D0 U + 02D0
    <last_non_ignorable/> U + A48C U + 1342E
    <first_primary_ignorable/> U + 0332 U + 0332
    <last_primary_ignorable/> U + 20EA U + 101FD
    <first_secondary_ignorable/> U + 0000 U + 0000
    <last_secondary_ignorable/> U + FE73 U + FE73
    <first_tertiary_ignorable/> U + 0000 U + 0000
    <last_tertiary_ignorable/> U + FE73 U + FE73
    <first_trailing/> U + 0000