mysql utf8mb4_unicode_ci 导致唯一键冲突

标签 mysql utf-8 utf8mb4

我有一张这样的 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 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 但不等于 Ķ=ķ 。其他语言(主要是西欧语言)还有其他专门的排序规则。

你的叫做“FULLWIDTH LATIN CAPITAL LETTER K”,所以它相当于拉丁文K是很合理的。

关于mysql utf8mb4_unicode_ci 导致唯一键冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31867895/

相关文章:

php - 正确插入 PhP & MySQL 用户数据

python - 从 Python 传递 shellcode 作为命令行参数

java - 当我在 java 中使用 connection.setAutoCommit(false) 时,对 MySQL 设置了什么样的锁定?

php - 如何将来自两个不同表的数据合并到一个变量中

php - 如何确保英镑符号 (£) 正确显示?

mysql - 从 MySQL 使用 java 获取 utf8mb4 数据(表情符号)

mysql - LOAD DATA LOCAL INFILE - 无效的 utf8mb4 字符串

mysql - 数据库 utf8mb4_unicode_ci 未保存完整表情符号

mysql - 如何在 Azure Web 应用安装存储中指定带点的安装路径

git - 将源代码文件的 Git 存储库从 ISO-8859-1 编码切换为 UTF-8 编码