【问题标题】:MySQL parsing characters above \u0080MySQL解析\u0080以上的字符
【发布时间】:2019-06-25 12:20:58
【问题描述】:

我不明白这种行为,希望有人能启发我......

mysql> CREATE TABLE test (id INT AUTO_INCREMENT, data JSON, PRIMARY KEY(id));
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO test(data) VALUES ('["\\u0000\"]'), ('["\\u0001"]'), ('["\\u0081"]'), ('["\\u0091"]');
Query OK, 4 rows affected (0.09 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select *,char_length(data),hex(data) from test;
+----+------------+-------------------+----------------------+
| id | data       | char_length(data) | hex(data)            |
+----+------------+-------------------+----------------------+
|  1 | ["\u0000"] |                10 | 5B225C7530303030225D |
|  2 | ["\u0001"] |                10 | 5B225C7530303031225D |
|  3 | [""]      |                 5 | 5B22C281225D         |
|  4 | [""]      |                 5 | 5B22C291225D         |
+----+------------+-------------------+----------------------+
4 rows in set (0.00 sec)

为什么 MySQL 选择将 \\u0081 解析为代码点,而将 \\u0001 保留为一系列简单字符?

或者换个说法,为什么MySQL将后一种情况下的“\\”解析为“这是一个文字反斜杠字符”,而将前一种情况下的“\\”解析为解释以下字符的原因?我可以看到任何一种方法的论据,但我对 \u0001 和 \u0081 之间行为的 变化 感到困惑。

这是关于“mysql Ver 14.14 Distrib 5.7.22, for Linux (x86_64) using EditLine wrapper”以及“mysql Ver 8.0.12 for macos10.13 on x86_64 (MySQL Community Server - GPL)”。它显示在 MySQL 命令行上,如此处所示,以及通过 PDO。

与往常一样,如果这个问题在其他地方得到解决,我深表歉意。我找到了manyrelatedissues,但没有一个解决这个不一致的问题(或者对于Bug 87722,它声称已经修复,但似乎没有)。

【问题讨论】:

  • data 的字符编码是什么?这取决于您的服务器设置。您可以使用SHOW CREATE TABLE test 找出UTF-8 中\u0080 以上的任何内容都是无效的,除非构造正确。该范围内的单个字节始终无效。
  • 我正在寻找那个命令!谢谢。它说“DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci”。但这里的奇怪之处在于我只是想在这些字段中输入直接文本:实际的反斜杠 (0x5C)、小写的 u (0x75)、一些数字 (0x30-39)。哪个 MySQL 正确处理反斜杠、u、零、零、零 (5C75303030);但由于某种原因,它对反斜杠、u、零、零、八的解释不同。

标签: mysql


【解决方案1】:

由于这里有两层转义,SQL 和 JSON,实际上你需要加倍反斜杠才能工作:

INSERT INTO test(data) VALUES ('["\\\\u0000\"]'), ('["\\\\u0001"]'), ('["\\\\u0081"]'), ('["\\\\u0091"]');

请注意,如果这些是简单的 VARCHAR 字段,则不需要这样做。 JSON 将 \ 视为特殊字符。

【讨论】:

  • 有趣!事实上,我曾尝试使用四个反斜杠作为实验,当我将其读回时,最终得到了两个,这至少是一致的,但仍然不是我想要的(记录数据中的一个反斜杠)。但是您是说记录数据中的单个反斜杠根本无法始终如一地创建因为它是 JSON 列,并且 JSON-colum-ness 导致它有时会解析 \uXXXX 而有时不会--- 对吗?
  • 我承认“有时”仍然令人讨厌,因为我很确定 \uXXXX 应该在 JSON (stackoverflow.com/questions/19176024/…) 中一致地解析。但是,如果您可以确认您的意思是将单个反斜杠作为 JSON 列中的独立字符根本不是一件好事,那么我将瞄准其他地方。
  • 这不是因为它是 JSON 列,而是因为它是在 SQL 字符串值中编码的 JSON 字符串值。当您 SELECT 它只有一层时,mysql 交互式外壳不会显示插入值所需的转义,而值(大约)是多少。所以插入一个 VARCHAR:\\u0000 但一个 JSON 字符串:'["\\\\u0000"]'
猜你喜欢
  • 2016-07-30
  • 1970-01-01
  • 1970-01-01
  • 2012-05-25
  • 2011-05-21
  • 1970-01-01
  • 1970-01-01
  • 2014-01-01
  • 2013-06-12
相关资源
最近更新 更多