mysql utf8mb4_unicode_ci 导致唯一键冲突

hbp*_*oss 5 mysql utf-8 utf8mb4

我有一张这样的桌子

CREATE TABLE `mb1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `u_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Run Code Online (Sandbox Code Playgroud)

我插入两行

insert into mb1(name) values('K'),('?');
Run Code Online (Sandbox Code Playgroud)

注意,第二个 K 是 unicode 字符

+------+-----------+
| name | hex(name) |
+------+-----------+
| K    | 4B        |
| ?   | EFBCAB    |
+------+-----------+
Run Code Online (Sandbox Code Playgroud)

为什么它们会导致唯一的密钥冲突?它们在 utf8mb4 中不是不同的字符吗?

删除 COLLATE utf8mb4_unicode_ci 后,问题消失。

Ric*_*mes 4

\n

为什么它们会导致唯一键冲突?它们在 utf8mb4 中不是不同的字符吗?

\n
\n\n

CHARACTER SET你错过了关于和 的要点COLLATION。ACHARACTER SET是不同字符的集合。ACOLLATION表示是否将字符视为相等 - 认为Aa- 不同的字符,但将ORDER BYWHERE =等视为相同。

\n\n
mysql> SELECT \'K\'=\'\xef\xbc\xab\' COLLATE utf8_unicode_ci;\n+-----------------------------------+\n| \'K\'=\'\xef\xbc\xab\' COLLATE utf8_unicode_ci  |\n+-----------------------------------+\n|                                 1 |\n+-----------------------------------+\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,在 utf8_unicode_ci (或 utf8mb4_unicode_ci)中,这两个字符被认为是“相等”。

\n\n

“平等”是检验UNIQUE

\n\n

设置COLLATION为对您有意义的任何值。

\n\n
    \n
  • utf8mb4_unicode_ci用于良好的“现实生活”比较,显然包括这个。K=k=\xc4\xb6=\xc4\xb7
  • \n
  • utf8mb4_unicode_ci进行更简单的比较。特别是,没有 2 个字符的组合与 1 个字符的编码相匹配。确实会发生大小写折叠和重音剥离。K=k=\xc4\xb6=\xc4\xb7
  • \n
  • utf8mb4_bin盲目检查位。无大小写折叠等。 K k \xc4\xb6 \xc4\xb7 均不相等。
  • \n
\n\n

utf8mb4_latvian_ci 有点不同: K=k 但不等于 \xc4\xb6=\xc4\xb7 。还有其他针对其他语言(主要是西欧语言)的专门排序规则。

\n\n

您的\xef\xbc\xab名称为“FULLWIDTH LATIN CAPITAL LETTER K”,因此它与拉丁语相比是相当合理的K

\n