我想在MySQL中插入一条包含非ASCII Unicode字符的记录,但我处于一个不允许我轻松输入非ASCII字符的终端。我该如何在MySQL的SQL语法中转义Unicode字面量?
我想在MySQL中插入一条包含非ASCII Unicode字符的记录,但我处于一个不允许我轻松输入非ASCII字符的终端。我该如何在MySQL的SQL语法中转义Unicode字面量?
参见:http://bugs.mysql.com/bug.php?id=10199 (Bug #10199:“允许在字符串文字中使用Unicode转义序列”) 自2005年以来,此请求一直处于“开放”状态。更多详细信息请参见工作日志任务#3529:Unicode转义序列。
但从https://web.archive.org/web/20091117221116/http://eng.kaching.com/2009/10/mysql-unicode-escape-sequences.html可以看到以下示例,似乎确实有效,但需要您了解实际的逐字节UTF8编码:
您还可以使用可变长度的UTF-8表示形式(例如,在从类似于%E2%80%98的utf-8 URL编码值复制时非常方便)。
mysql> select _utf8 x'E28098'; +---+ | ‘ | +---+
如果目标是指定字符的代码点而不是编码字节序列(即使用0x0F02
代替"༂"的UTF-8编码0xE0BC82
),那么您需要使用一个编码,其中代码点值恰好是编码的字节序列。例如,“‘”字符的UTF-8编码字节序列为“0xE28098”(如dkamins的答案所示),对应着代码点U+2018。但是,0x2018
既是‘
的代码点值,也是ucs2
/utf16
编码的编码字节序列(它们对于BMP字符来说实际上是相同的编码,但我更喜欢使用“utf16”,因为它与“utf8”和“utf32”一致,保持了“utf”主题的一致性)。因此:
_utf16 0x2018
返回与以下相同的'
字符:
_utf8 0xE0BC82
然而,utf16
只适用于BMP字符(代码点 U+0000 - U+FFFF),以指定代码点值。如果您想使用补充字符(通过指定代码点而不是特定编码的字节序列),那么您需要使用 utf32
编码。不仅 _utf32 0x2018
返回 ‘
,而且:
_utf32 0x1F47E
返�结�:👾
è¦�使用UTF-8或UTF-16ç¼–ç �æ�¥è¡¨ç¤ºå�Œä¸€ä¸ªè¡¥å……å—符,需è¦�进行以下æ“�作:
_utf8mb4 0xF09F91BE
_utf16 0xD83DDC7E
但是,如果您在将此添加到已经 utf8 的字符串时遇到问题,则需要将其转换为 utf8
(或在创建 Supplementary Characters 时将其转换为 utf8mb4
,因为 utf8
编码/字符集只能处理 BMP 字符):
CONVERT(_utf32 0x1F47E USING utf8mb4)
或者,以Michael - sqlbot的答案中的示例字符为例:
CONVERT(_utf32 0x2192 USING utf8)
返回一个→
。因此,为了从其代码点创建一个UTF-8编码字符,不需要自定义函数(至少在MySQL 8.0中不需要)。以下是一个测试查询
SELECT _utf32 0x1F47E AS "Supplementary Character in utf32",
CONVERT(_utf32 0x1F47E USING utf8mb4) AS "Supplementary Character in utf8mb4",
CHARSET(CONVERT(_utf32 0x1F47E USING utf8mb4)) AS "Proof",
"---" AS "---",
_utf32 0x2192 AS "BMP character in utf32",
CONVERT(_utf32 0x2192 USING utf8) AS "BMP character in utf8",
CHARSET(CONVERT(_utf32 0x2192 USING utf8)) AS "Proof";
你可以在db<>fiddle上看到其运行情况(在MySQL 8.0之前版本可能不起作用)。
如需了解更多有关这些选项的详细信息以及其他语言和平台的Unicode转义序列,请参阅我的文章:
Unicode Escape Sequences Across Various Languages and Platforms (including Supplementary Characters)
DELIMITER $$
DROP FUNCTION IF EXISTS `utf8_char` $$
CREATE FUNCTION `utf8_char`(v smallint unsigned) RETURNS VARCHAR(1) CHARSET utf8
NO SQL
DETERMINISTIC
BEGIN
-- https://dev59.com/T3A65IYBdhLWcg3wyR2k#30675371
RETURN CHAR(CASE
WHEN v <= 0x7F THEN v
WHEN v <= 0x7FF THEN 0xC080 | ((v >> 6) << 8) | (v & 0x3F)
WHEN v <= 0xFFFF THEN 0xE08080 | (((v >> 12) & 0x0F ) << 16) | (((v >> 6) & 0x3F ) << 8) | (v & 0x3F)
ELSE NULL END);
END $$
DELIMITER ;
示例输出:
mysql> select utf8_char(8592) AS 'leftwards_arrow';
+-----------------+
| leftwards_arrow |
+-----------------+
| ← |
+-----------------+
1 row in set (0.00 sec)
mysql> select utf8_char(0x2192) AS 'rightwards_arrow_hex';
+----------------------+
| rightwards_arrow_hex |
+----------------------+
| → |
+----------------------+
1 row in set (0.00 sec)
CONVERT(_utf32 0x2192 USING utf8)
为BMP字符或者甚至使用CONVERT(_utf32 0x1F47E USING utf8mb4)
为补充字符创建一个UTF8编码的字符串。请参见我的答案以获取详细信息和工作演示的链接。尽管如此,在CONVERT()
无法工作的版本中,这仍然是一个好的解决方案,所以+1 :-) - Solomon Rutzky