我有一张这样的 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 SET
和COLLATION
的要点。 CHARACTER SET
是不同字符的集合。 COLLATION
表示是否将字符视为相等的 -- 想想 A
和 a
-- 不同的字符,但被视为 ORDER BY
和 WHERE =
等相同。
mysql> SELECT 'K'='K' COLLATE utf8_unicode_ci;
+-----------------------------------+
| 'K'='K' COLLATE utf8_unicode_ci |
+-----------------------------------+
| 1 |
+-----------------------------------+
因此在 utf8_unicode_ci(或 utf8mb4_unicode_ci)中,这两个字符被认为是“相等的”。
“等于”是对 UNIQUE
键的测试。
将列的 COLLATION
设置为对您有意义的值。
- utf8mb4_unicode_ci 用于很好的“现实生活”比较,显然包括这个。 K=k=Ķ=ķ
- utf8mb4_unicode_ci 用于更简单的比较。特别是没有 2 个字符的组合匹配 1 个字符的编码。确实发生了大小写折叠和重音剥离。 K=k=Ķ=ķ
- utf8mb4_bin 盲目检查位。无大小写折叠等。K k Ķ ķ 均不等。
utf8mb4_latvian_ci 有点不同:K=k 但不等于 Ķ=ķ 。其他语言(主要是西欧语言)还有其他专门的排序规则。
你的K
叫做“FULLWIDTH LATIN CAPITAL LETTER K”,所以它相当于拉丁文K
是很合理的。
关于mysql utf8mb4_unicode_ci 导致唯一键冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31867895/