表情符号作为 MariaDB 主键中的问号

Posted

技术标签:

【中文标题】表情符号作为 MariaDB 主键中的问号【英文标题】:Emojis as question marks in MariaDB primary key 【发布时间】:2018-12-28 15:18:05 【问题描述】:

如下表,使用mariadb-server-10.1 10.1.32+maria-1~trusty:

CREATE TABLE `tags` (
  `tag_name` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
  `thing_id` int(11) NOT NULL,
  PRIMARY KEY (`thing_id`,`tag_name`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

清单为(在 SQLAlchemy 应用程序中):

IntegrityError: (IntegrityError) 
(1062, "Duplicate entry '1532-?' for key 'PRIMARY'")

在第二次尝试插入表情符号时。

第一个在数据库中似乎没问题(相信我,它在我的控制台和浏览器中显示为“外星人”表情符号):

> select tag_name, HEX(tag_name) from tags;
+----------+----------------+
| tag_name | HEX(tag_name)  |
+----------+----------------+
| GOODGUY  | 474F4F44475559 |
| ????        | F09F91BD       |
+----------+----------------+
2 rows in set (0.00 sec)

我知道 Emoji's in mysql turns to question marks ,但 my.cnf 有:

default-character-set = utf8mb4
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
default-character-set = utf8mb4

并且 utf8mb4 正在客户端中使用(作为?charset=utf8mb4 添加到连接字符串的字符集)。而且我相信在服务器端检查了主键。

还有什么我遗漏的(可以检查)或者是一些 MariaDB 错误还是需要一些额外的配置?

不确定是否相关,但通过mysql shell 插入时同样的问题。也试过这个看看发生了什么(在mysql utf8mb4_unicode_ci cause unique key collision找到这个):

> SELECT '????'='????' COLLATE utf8mb4_unicode_ci;
+------------------------------------+
| '?'='?' COLLATE utf8mb4_unicode_ci |
+------------------------------------+
|                                  1 |
+------------------------------------+

但不确定这是否相关。

我不明白:数据库有时会正常显示(通过客户端 - shell 和 SQLAlchemy 应用程序),但随后无法在标题中显示?从我得到的证据来看,我不明白这种糟糕的转变发生在哪里。数据库中的数据似乎没问题(见上面的十六进制),但是两个表情符号等效于主键?

还有一个对比:

> SELECT '????'='????' COLLATE utf8mb4_bin;
+-----------------------------+
| '?'='?' COLLATE utf8mb4_bin |
+-----------------------------+
|                           0 |
+-----------------------------+

这种点手指主键不使用二进制?所有表情符号在用于索引之前都转换为其他内容?很奇怪。

【问题讨论】:

查看***.com/questions/38363566/…中的问号 Trouble with UTF-8 characters; what I see is not what I stored的可能重复 @RickJames 请不要这么快下结论。你提到的问题并没有解决我的问题。我已经在使用那里描述的技术了。 难道#1532 已经被那个表情符号标记了?而你又是INSERTing 同一个标签?而“问号”实际上来自 SQLAlchemy,而不是 MySQL?如果是这样,请考虑INSERT IGNORE ... 通过 mysql shell 也是一样的。我找到了另一个与排序相关的答案,但不确定该怎么做。将在一分钟内更新答案 【参考方案1】:
mysql> SELECT '?'='?' COLLATE utf8mb4_unicode_520_ci;
+----------------------------------------+
| '?'='?' COLLATE utf8mb4_unicode_520_ci |
+----------------------------------------+
|                                      0 |
+----------------------------------------+

需要注意的两点:

520 排序规则将它们视为不同。 问号是显示问题。

为了进一步隔离...

mysql> SELECT HEX('?');
+----------+
| HEX('?') |
+----------+
| F09F9886 |
+----------+

我的意思是问号可能是 显示 问题,并且(正如您用十六进制指出的那样)它不是编码问题:

(1062, "Duplicate entry '1532-?' for key 'PRIMARY'")

而且,如果您想用两个 Emoji 标记 1532,则该列需要为 utf8mb4_unicode_520_ci(或 utf8mb4_bin)。

【讨论】:

是的,我的结果和上面一样。但那是什么 utf8mb4_unicode_520_ci ?为什么我应该选择它而不是我当前的选择?我看到很多帖子如何摆脱“520”。 好的。找到描述***.com/questions/18904883/… @RomanSusi - 520 将 Emoji 视为独特的。该链接正在谈论土耳其语。 520 不能很好地处理特定语言的要求。 ***.com/questions/42385099/… ,加上谷歌搜索的更多内容 - 我没有进一步阅读。当然,也有类似的错误建议将 utf8mb4 替换为 utf8 @RomanSusi - 第二个链接涉及有人从 5.6(有 520)降级到 5.5。同样,这是避免 520 的正当理由,但不是适用于您的理由。

以上是关于表情符号作为 MariaDB 主键中的问号的主要内容,如果未能解决你的问题,请参考以下文章

替换给定 unicode 字符串中的所有表情符号

在Visual Studio或GCC中使用表情符号作为c ++中的标识符名称

在android中添加自定义图像作为表情符号

如何在 C# if 语句中使用 Discord 表情符号

在推文中查找表情符号作为整个集群而不是单个字符

单词列表python不和谐中的表情符号