MySQL Unicode 文字字面量

21

我想在MySQL中插入一条包含非ASCII Unicode字符的记录,但我处于一个不允许我轻松输入非ASCII字符的终端。我该如何在MySQL的SQL语法中转义Unicode字面量?

3个回答

11

参见: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';  
+---+  
||  
+---+  

第二个链接已经失效。 - Stephen M -on strike-

3

如果目标是指定字符的代码点而不是编码字节序列(即使用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)


2
这个存储函数提供了MySQL似乎缺失的功能,即可以将文字代码点转换为字符,而不需要已知UTF-8编码。如果VARCHAR(1)看起来有些奇怪,因为MySQL中的utf8字符可以长达3个字节,请记住VARCHAR的大小是“字符”,而不是“字节”。该函数返回输入值中的单个UTF-8编码字符。对于十六进制字面量,请在前面添加0x。
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)

@DieterRehbein和Michael:自定义函数不是必需的,至少在MySQL 8.0中不需要。您可以通过CONVERT(_utf32 0x2192 USING utf8)为BMP字符或者甚至使用CONVERT(_utf32 0x1F47E USING utf8mb4)为补充字符创建一个UTF8编码的字符串。请参见我的答案以获取详细信息和工作演示的链接。尽管如此,在CONVERT()无法工作的版本中,这仍然是一个好的解决方案,所以+1 :-) - Solomon Rutzky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接