MySQL returns 仅在某些情况下不正确的 UTF8 扩展字符
MySQL returns incorrect UTF8 extended characters in some cases only
注意:在下面的问题中你可能会看到 ?或块而不是字符,这是因为您没有合适的字体。请无视。
背景
我有一个 table 数据结构如下:
CREATE TABLE `decomposition_dup` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`structure` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`child` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `parent` (`parent`),
KEY `child` (`child`),
KEY `parent_2` (`parent`,`child`)
) ENGINE=InnoDB AUTO_INCREMENT=211929 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
以及一些示例数据:
INSERT INTO `decomposition_dup` (`id`, `parent`, `structure`, `child`) VALUES
(154647, '锦', 'a', '钅'),
(154648, '锦', 'a', '帛'),
(185775, '钅', 'd', '二'),
(185774, '钅', 'd', '㇟'),
(21195, '钅', 'd', ''),
(21178, '⻐', 'd', '乇'),
(21177, '⻐', 'd', '');
并且字符集设置正确:
问题
请注意非常重要:
- 154647, 185775, 185774 & 21195指的是这个字符:http://unicode.scarfboy.com/?s=%E9%92%85
- 21178和21177指的是这个字符:http://unicode.scarfboy.com/?s=%E2%BB%90
如你所见,他们是不同的角色。但是,在某些情况下,它们被视为 相同的字符 。
案例一
当我 运行 以下查询时,它只有 return 是正确的 child (即 return 不是 similar-looking 而是不同的字符child):
SELECT *
FROM decomposition_dup
WHERE parent = '锦'
这是正确的行为。
案例二
但是,当我 运行 使用钅 (http://unicode.scarfboy.com/?s=%E9%92%85) 进行以下查询时,它 return 两个相似的字符:
SELECT *
FROM decomposition_dup
WHERE parent = '钅'
这应该只有 return 185775、185774 和 21195。
案例三
并且当我 运行 使用 ⻐ (http://unicode.scarfboy.com/?s=%E2%BB%90) 进行以下查询时,它也 return 两个相似的字符:
SELECT *
FROM decomposition_dup
WHERE parent = '⻐'
这应该只有 return 21178 和 21177。
案例4
如果我将损坏的查询(即案例 2 和案例 3)的 =
替换为 LIKE
,它们会 return 正确。
例如,以下查询与案例 3 相同,但使用 LIKE
:
SELECT *
FROM decomposition_dup
WHERE parent LIKE '⻐'
这 return 是正确的字符,但会减慢查询速度。
问题
这是 MySQL 中的错误还是在查询 UTF8 扩展字符时我忽略了什么?
据我所知,问题出在事物的 SQL 方面,经过研究,您会发现此错误代码意味着
MySQL's utf8 permits only the Unicode characters that can be
represented with 3 bytes in UTF-8.
所以这可能是您在 SQL
的情况下使用的字符
如果您希望它们相同,请将列的 COLLATION
设置为 utf8mb4_unicode_ci
或 utf8mb4_unicode_520_ci
。
如果您希望它们不同,请使用 utf8mb4_general_ci
,而不是:
mysql> SELECT CONVERT(UNHEX('e99285') USING utf8mb4) =
-> CONVERT(UNHEX('e2bb90') USING utf8mb4) COLLATE utf8mb4_general_ci AS general;
+---------+
| general |
+---------+
| 0 |
+---------+
mysql> SELECT CONVERT(UNHEX('e99285') USING utf8mb4) =
-> CONVERT(UNHEX('e2bb90') USING utf8mb4) COLLATE utf8mb4_unicode_ci AS unicode;
+---------+
| unicode |
+---------+
| 1 |
+---------+
mysql> SELECT CONVERT(UNHEX('e99285') USING utf8mb4) =
-> CONVERT(UNHEX('e2bb90') USING utf8mb4) COLLATE utf8mb4_unicode_520_ci AS unicode_520;
+-------------+
| unicode_520 |
+-------------+
| 1 |
+-------------+
注意:在下面的问题中你可能会看到 ?或块而不是字符,这是因为您没有合适的字体。请无视。
背景
我有一个 table 数据结构如下:
CREATE TABLE `decomposition_dup` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`structure` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`child` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `parent` (`parent`),
KEY `child` (`child`),
KEY `parent_2` (`parent`,`child`)
) ENGINE=InnoDB AUTO_INCREMENT=211929 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
以及一些示例数据:
INSERT INTO `decomposition_dup` (`id`, `parent`, `structure`, `child`) VALUES
(154647, '锦', 'a', '钅'),
(154648, '锦', 'a', '帛'),
(185775, '钅', 'd', '二'),
(185774, '钅', 'd', '㇟'),
(21195, '钅', 'd', ''),
(21178, '⻐', 'd', '乇'),
(21177, '⻐', 'd', '');
并且字符集设置正确:
问题
请注意非常重要:
- 154647, 185775, 185774 & 21195指的是这个字符:http://unicode.scarfboy.com/?s=%E9%92%85
- 21178和21177指的是这个字符:http://unicode.scarfboy.com/?s=%E2%BB%90
如你所见,他们是不同的角色。但是,在某些情况下,它们被视为 相同的字符 。
案例一
当我 运行 以下查询时,它只有 return 是正确的 child (即 return 不是 similar-looking 而是不同的字符child):
SELECT *
FROM decomposition_dup
WHERE parent = '锦'
这是正确的行为。
案例二
但是,当我 运行 使用钅 (http://unicode.scarfboy.com/?s=%E9%92%85) 进行以下查询时,它 return 两个相似的字符:
SELECT *
FROM decomposition_dup
WHERE parent = '钅'
这应该只有 return 185775、185774 和 21195。
案例三
并且当我 运行 使用 ⻐ (http://unicode.scarfboy.com/?s=%E2%BB%90) 进行以下查询时,它也 return 两个相似的字符:
SELECT *
FROM decomposition_dup
WHERE parent = '⻐'
这应该只有 return 21178 和 21177。
案例4
如果我将损坏的查询(即案例 2 和案例 3)的 =
替换为 LIKE
,它们会 return 正确。
例如,以下查询与案例 3 相同,但使用 LIKE
:
SELECT *
FROM decomposition_dup
WHERE parent LIKE '⻐'
这 return 是正确的字符,但会减慢查询速度。
问题
这是 MySQL 中的错误还是在查询 UTF8 扩展字符时我忽略了什么?
据我所知,问题出在事物的 SQL 方面,经过研究,您会发现此错误代码意味着
MySQL's utf8 permits only the Unicode characters that can be represented with 3 bytes in UTF-8.
所以这可能是您在 SQL
的情况下使用的字符如果您希望它们相同,请将列的 COLLATION
设置为 utf8mb4_unicode_ci
或 utf8mb4_unicode_520_ci
。
如果您希望它们不同,请使用 utf8mb4_general_ci
,而不是:
mysql> SELECT CONVERT(UNHEX('e99285') USING utf8mb4) =
-> CONVERT(UNHEX('e2bb90') USING utf8mb4) COLLATE utf8mb4_general_ci AS general;
+---------+
| general |
+---------+
| 0 |
+---------+
mysql> SELECT CONVERT(UNHEX('e99285') USING utf8mb4) =
-> CONVERT(UNHEX('e2bb90') USING utf8mb4) COLLATE utf8mb4_unicode_ci AS unicode;
+---------+
| unicode |
+---------+
| 1 |
+---------+
mysql> SELECT CONVERT(UNHEX('e99285') USING utf8mb4) =
-> CONVERT(UNHEX('e2bb90') USING utf8mb4) COLLATE utf8mb4_unicode_520_ci AS unicode_520;
+-------------+
| unicode_520 |
+-------------+
| 1 |
+-------------+