mysql utf8mb4_unicode_ci 导致唯一键冲突

mysql utf8mb4_unicode_ci cause unique key collision

我有一个table这样的

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;

然后我插入两行

insert into mb1(name) values('K'),('K');

注意,第二个K是unicode字符

+------+-----------+
| name | hex(name) |
+------+-----------+
| K    | 4B        |
| K   | EFBCAB    |
+------+-----------+

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

删除 COLLATE utf8mb4_unicode_ci 后,问题消失了。

Why do they cause unique key collision? Aren't they different character in utf8mb4?

您忽略了关于 CHARACTER SETCOLLATION 的要点。 CHARACTER SET 是不同字符的集合。 COLLATION 表示是否将字符视为相等——想想 Aa —— 不同的字符,但将 ORDER BYWHERE = 等视为一样。

mysql> SELECT 'K'='K' COLLATE utf8_unicode_ci;
+-----------------------------------+
| 'K'='K' COLLATE utf8_unicode_ci  |
+-----------------------------------+
|                                 1 |
+-----------------------------------+

所以在utf8_unicode_ci(或utf8mb4_unicode_ci)中,这两个字符被认为是"equal"。

"Equal" 是 UNIQUE 键的测试。

将列的 COLLATION 设置为对您有意义的值。

  • utf8mb4_unicode_ci 很好的 'real life' 比较,显然包括这个。 K=k=Ķ=ķ
  • utf8mb4_unicode_ci比较简单。特别是没有 2 个字符的组合匹配 1 个字符的编码。确实发生了大小写折叠和重音剥离。 K=k=Ķ=ķ
  • utf8mb4_bin 盲查位。没有大小写折叠等。K k Ķ ķ 都是不等的。

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

你的被称为"FULLWIDTH LATIN CAPITAL LETTER K",所以它与拉丁文K.

比较是相当合理的