暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL 中的字符集和排序规则

原创 你猜我猜不猜 2023-05-31
606

了解 MySQL 中字符集和排序规则之间的差异。
utf8mb4_0900_ai_ci中各个字段意思

0900:UCA 9.0.0 weight keys
ci:case-insensitive collation
ai:accent-insensitive collation
复制

在处理 MySQL 中的字符串列时,字符集和排序规则是需要理解的基本重要概念。对其中任何一个的轻微误解都可能导致性能不佳或插入数据时出现意外错误。

字符集定义允许进入列的字符。排序规则是一组用于比较这些字符的规则。每个字符集可以有多个排序规则,但一个排序规则只能属于一个字符集。

1、MySQL 中的字符集
MySQL支持的字符集范围很广,可以从information_schema数据库中选择查看。这将列出所有字符集及其默认排序规则。每个字符集都有一个默认排序规则。

+--------------------+----------------------+---------------------------------+--------+
| CHARACTER_SET_NAME | DEFAULT_COLLATE_NAME | DESCRIPTION                     | MAXLEN |
+--------------------+----------------------+---------------------------------+--------+
| armscii8           | armscii8_general_ci  | ARMSCII-8 Armenian              |      1 |
| ascii              | ascii_general_ci     | US ASCII                        |      1 |
| big5               | big5_chinese_ci      | Big5 Traditional Chinese        |      2 |
| binary             | binary               | Binary pseudo charset           |      1 |
| cp1250             | cp1250_general_ci    | Windows Central European        |      1 |
| cp1251             | cp1251_general_ci    | Windows Cyrillic                |      1 |
| cp1256             | cp1256_general_ci    | Windows Arabic                  |      1 |
| cp1257             | cp1257_general_ci    | Windows Baltic                  |      1 |
| cp850              | cp850_general_ci     | DOS West European               |      1 |
| cp852              | cp852_general_ci     | DOS Central European            |      1 |
| cp866              | cp866_general_ci     | DOS Russian                     |      1 |
| cp932              | cp932_japanese_ci    | SJIS for Windows Japanese       |      2 |
| dec8               | dec8_swedish_ci      | DEC West European               |      1 |
| eucjpms            | eucjpms_japanese_ci  | UJIS for Windows Japanese       |      3 |
| euckr              | euckr_korean_ci      | EUC-KR Korean                   |      2 |
| gb18030            | gb18030_chinese_ci   | China National Standard GB18030 |      4 |
| gb2312             | gb2312_chinese_ci    | GB2312 Simplified Chinese       |      2 |
| gbk                | gbk_chinese_ci       | GBK Simplified Chinese          |      2 |
| geostd8            | geostd8_general_ci   | GEOSTD8 Georgian                |      1 |
| greek              | greek_general_ci     | ISO 8859-7 Greek                |      1 |
| hebrew             | hebrew_general_ci    | ISO 8859-8 Hebrew               |      1 |
| hp8                | hp8_english_ci       | HP West European                |      1 |
| keybcs2            | keybcs2_general_ci   | DOS Kamenicky Czech-Slovak      |      1 |
| koi8r              | koi8r_general_ci     | KOI8-R Relcom Russian           |      1 |
| koi8u              | koi8u_general_ci     | KOI8-U Ukrainian                |      1 |
| latin1             | latin1_swedish_ci    | cp1252 West European            |      1 |
| latin2             | latin2_general_ci    | ISO 8859-2 Central European     |      1 |
| latin5             | latin5_turkish_ci    | ISO 8859-9 Turkish              |      1 |
| latin7             | latin7_general_ci    | ISO 8859-13 Baltic              |      1 |
| macce              | macce_general_ci     | Mac Central European            |      1 |
| macroman           | macroman_general_ci  | Mac West European               |      1 |
| sjis               | sjis_japanese_ci     | Shift-JIS Japanese              |      2 |
| swe7               | swe7_swedish_ci      | 7bit Swedish                    |      1 |
| tis620             | tis620_thai_ci       | TIS620 Thai                     |      1 |
| ucs2               | ucs2_general_ci      | UCS-2 Unicode                   |      2 |
| ujis               | ujis_japanese_ci     | EUC-JP Japanese                 |      3 |
| utf16              | utf16_general_ci     | UTF-16 Unicode                  |      4 |
| utf16le            | utf16le_general_ci   | UTF-16LE Unicode                |      4 |
| utf32              | utf32_general_ci     | UTF-32 Unicode                  |      4 |
| utf8               | utf8_general_ci      | UTF-8 Unicode                   |      3 |
| utf8mb4            | utf8mb4_general_ci   | UTF-8 Unicode                   |      4 |
+--------------------+----------------------+---------------------------------+--------+
41 rows in set (0.00 sec)

复制

在此表的底部,您会注意到两个字符集,描述为UTF-8 Unicode. 字符utf8集的MAXLEN为 3,而 autf8mb4的MAXLEN为 4。此处描述的是每个字符的最大允许长度(以字节为单位)。

根据 UTF-8 规范,每个字符允许四个字节,这意味着 MySQL 的字符集实际上utf8从来不是 UTF-8,因为它只支持每个字符三个字节。在 MySQL 8 中,utf8mb4是默认字符集,也是您最常使用的字符集。保留是为了向后兼容,不应再使用utf8。

2、如何定义一个字符集
有几种方法可以定义列的字符集。utf8mb4如果您没有在表或列级别指定字符集,将应用服务器默认值(除非您明确声明了不同的服务器或数据库默认值)。
我们可以通过创建一个没有字符集信息的表然后读回它来证明这一点:

CREATE TABLE no_charset (my_column VARCHAR(255));
复制
SHOW CREATE TABLE no_charset;
复制

结果CREATE TABLE语句显示已应用默认字符集和排序规则。

CREATE TABLE `no_charset` ( `my_column` varchar(255) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
复制

在表级别定义#
您可以使用表示法在表级别显式设置字符集,而不是允许应用数据库或服务器默认值CHARSET=[charset]。在这里,我们将创建一个表,其中所有字符列都具有latin1字符集:

CREATE TABLE `no_charset` ( `my_column` VARCHAR(255) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1;
复制

在列级别定义#
最后,您可以在列级别设置字符集。这是最具体的,会覆盖任何表级设置。

CREATE TABLE `mixed_collations` (`explicitly_set` VARCHAR(255) CHARACTER SET latin1, `implicitly_set` VARCHAR(255));
复制

使用语句回读此表SHOW CREATE TABLE可以清楚地看出该表是utf8mb4,但该explicitly_set列是latin1:

CREATE TABLE `mixed_collations` ( `explicitly_set` VARCHAR(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL,`implicitly_set` VARCHAR(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
复制

这是声明字符集的最具体的方法。

列级规范将覆盖表级规范,表级规范将覆盖数据库默认值,数据库级字符集将覆盖服务器默认值。

3、MySQL 中的排序规则
虽然字符集定义了可以存储在列中的合法字符,但排序规则是确定如何进行字符串比较的规则。如果您正在排序或比较字符串,MySQL 使用排序规则来决定顺序以及字符串是否相同。

您可以通过再次查询表来显示所有排序规则information_schema。有很多排序规则,因此我们将结果限制为仅适用于utf8mb4字符集的排序规则。

mysql> SELECT * FROM information_schema.collations WHERE character_set_name='utf8mb4' ORDER BY collation_name;
+------------------------+--------------------+-----+------------+-------------+---------+
| COLLATION_NAME         | CHARACTER_SET_NAME | ID  | IS_DEFAULT | IS_COMPILED | SORTLEN |
+------------------------+--------------------+-----+------------+-------------+---------+
| utf8mb4_bin            | utf8mb4            |  46 |            | Yes         |       1 |
| utf8mb4_croatian_ci    | utf8mb4            | 245 |            | Yes         |       8 |
| utf8mb4_czech_ci       | utf8mb4            | 234 |            | Yes         |       8 |
| utf8mb4_danish_ci      | utf8mb4            | 235 |            | Yes         |       8 |
| utf8mb4_esperanto_ci   | utf8mb4            | 241 |            | Yes         |       8 |
| utf8mb4_estonian_ci    | utf8mb4            | 230 |            | Yes         |       8 |
| utf8mb4_general_ci     | utf8mb4            |  45 | Yes        | Yes         |       1 |
| utf8mb4_german2_ci     | utf8mb4            | 244 |            | Yes         |       8 |
| utf8mb4_hungarian_ci   | utf8mb4            | 242 |            | Yes         |       8 |
| utf8mb4_icelandic_ci   | utf8mb4            | 225 |            | Yes         |       8 |
| utf8mb4_latvian_ci     | utf8mb4            | 226 |            | Yes         |       8 |
| utf8mb4_lithuanian_ci  | utf8mb4            | 236 |            | Yes         |       8 |
| utf8mb4_persian_ci     | utf8mb4            | 240 |            | Yes         |       8 |
| utf8mb4_polish_ci      | utf8mb4            | 229 |            | Yes         |       8 |
| utf8mb4_romanian_ci    | utf8mb4            | 227 |            | Yes         |       8 |
| utf8mb4_roman_ci       | utf8mb4            | 239 |            | Yes         |       8 |
| utf8mb4_sinhala_ci     | utf8mb4            | 243 |            | Yes         |       8 |
| utf8mb4_slovak_ci      | utf8mb4            | 237 |            | Yes         |       8 |
| utf8mb4_slovenian_ci   | utf8mb4            | 228 |            | Yes         |       8 |
| utf8mb4_spanish2_ci    | utf8mb4            | 238 |            | Yes         |       8 |
| utf8mb4_spanish_ci     | utf8mb4            | 231 |            | Yes         |       8 |
| utf8mb4_swedish_ci     | utf8mb4            | 232 |            | Yes         |       8 |
| utf8mb4_turkish_ci     | utf8mb4            | 233 |            | Yes         |       8 |
| utf8mb4_unicode_520_ci | utf8mb4            | 246 |            | Yes         |       8 |
| utf8mb4_unicode_ci     | utf8mb4            | 224 |            | Yes         |       8 |
| utf8mb4_vietnamese_ci  | utf8mb4            | 247 |            | Yes         |       8 |
+------------------------+--------------------+-----+------------+-------------+---------+
26 rows in set (0.00 sec)
复制

该查询将显示所有排序规则、相关字符集名称、它们是否为默认值以及其他一些信息。请注意,对于每个字符集,都有一个默认排序规则。例如,utf8mb4_0900_ai_ci是字符集的默认排序规则utf8mb4。

排序规则遵循一种命名方案,其中字符集形成前缀,后缀组合排序规则的属性。

以下是您可能会看到的一些后缀的细分:

| Suffix | Meaning            |
|--------|--------------------|
| _ai    | Accent-insensitive |
| _as    | Accent-sensitive   |
| _ci    | Case-insensitive   |
| _cs    | Case-sensitive     |
| _ks    | Kana-sensitive     |
| _bin   | Binary             |

复制

让我们采用默认utf8mb4排序规则utf8mb4_0900_ai_ci并稍微扩展一下。
该utf8mb4部分声明它属于utf8mb4字符集。引用0900UCA 9.0.0 权重键。_ai表示排序规则不区分重音,同时_ci声明它不区分大小写。
这使我们能够自信地回答“字符串比较区分大小写吗?”这个问题。答案当然是:视情况而定!这取决于整理。
让我们通过使用COLLATE关键字显式转换字符串来证明这一点。

SELECT "MySQL" COLLATE utf8mb4_0900_ai_ci = "mysql" COLLATE utf8mb4_0900_ai_ci;
复制

运行这个语句给我们一个值1,这意味着 MySQL 将两个字符串视为相等的。如果我们使用区分大小写的排序规则重新运行它,我们会期望(并获得!)不同的结果:

SELECT "MySQL" COLLATE utf8mb4_0900_as_cs = "mysql" COLLATE utf8mb4_0900_as_cs;
复制

此查询返回值0,这意味着 MySQL 认为这些字符串是唯一的,因为它们的大小写不同。

同样的逻辑也适用于重音敏感度。使用不区分重音的排序规则,résumé并且resume将被视为相同,因为重音将被忽略。

4、如何定义排序规则
与字符集一样,可以在表和列级别设置排序规则。如果未明确定义排序规则,则 MySQL 使用字符集的默认排序规则。

要在表级别定义排序规则,可以COLLATE在CREATE TABLE语句中使用子句。例如,您可以创建一个表,其中所有字符列都使用utf8mb4_bin排序规则:

CREATE TABLE table_with_collation (
    my_column VARCHAR(255)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
复制

如果要在列级别定义排序规则,可以在列定义中进行。以下示例创建一个包含两列的表:explicitly_set使用utf8mb4_general_ci排序规则,并implicitly_set使用字符集中的默认排序规则utf8mb4,即utf8mb4_0900_ai_ci.

CREATE TABLE table_with_collation (
    `explicitly_set` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,
    `implicitly_set` varchar(255)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
复制

您还可以使用以下语句更改现有表中列的排序规则ALTER TABLE:

ALTER TABLE table_with_collation 
    CHANGE `explicitly_set` `explicitly_set` varchar(255) 
        CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
复制

5、摘要
在 MySQL 中处理字符串数据时,了解字符集和排序规则是基础。字符集定义可以存储在列中的合法字符,而排序规则确定如何进行字符串比较。

字符集可以在列级、表级定义,也可以从数据库或服务器默认继承。使用最具体的级别(列 > 表 > 数据库 > 服务器)。
排序规则可以在列级别、表级别定义,也可以从字符集默认值继承。同样,使用最具体的级别。
列的字符集和排序规则会影响数据的存储方式以及数据的比较和排序方式。在设计数据库时,请注意这些设置以确保正确的行为和最佳性能。
如果您不确定要使用哪个字符集或排序规则,MySQL 默认utf8mb4字符集及其默认utf8mb4_0900_ai_ci排序规则通常是不错的选择。它们支持所有 Unicode 字符并提供不区分大小写和不区分重音的比较。

扫码_搜索联合传播样式标准色版.png

最后修改时间:2023-07-27 21:01:40
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论