MySQL Unicode литералы - PullRequest
       17

MySQL Unicode литералы

14 голосов
/ 03 сентября 2010

Я хочу вставить в MySQL запись, которая имеет не-ASCII-символ Unicode, но я на терминале, который не позволяет мне легко вводить символы не-ASCII.Как мне избежать литерала Unicode в синтаксисе SQL MySQL?

Ответы [ 3 ]

7 голосов
/ 03 сентября 2010

См .: http://bugs.mysql.com/bug.php?id=10199 (Ошибка № 10199: «Разрешить escape-последовательность Unicode для строковых литералов».) Этот запрос является «Открытым» с 2005 года. Подробнее в Задача рабочего журнала # 3529: последовательности перехода Unicode .

С https://web.archive.org/web/20091117221116/http://eng.kaching.com/2009/10/mysql-unicode-escape-sequences.html тем не менее, вы можете увидеть следующий пример, который действительно работает, но требует, чтобы вы знали фактическую побайтную кодировку UTF8:

Вы также можете использовать представление UTF-8 переменной длины (удобно, например, при копировании из URL-значения в кодировке utf-8, такого как% E2% 80% 98).

mysql> select _utf8 x'E28098';  
+---+  
| ‘ |  
+---+  
1 голос
/ 05 июня 2015

Эта хранимая функция обеспечивает функциональность, которая (по-видимому) отсутствует в MySQL, и позволяет преобразовывать буквенную кодовую точку в символ без необходимости уже знать кодировку UTF-8.

Если VARCHAR(1) кажется странным, так как символы utf8 в MySQL могут иметь длину до 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

-- /2873165/mysql-unicode-literaly

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)
0 голосов
/ 27 июня 2019

Если цель состоит в том, чтобы указать кодовую точку вместо закодированной последовательности байтов (то есть 0x0F02 вместо UTF-8 0xE0BC82 для "& # x0F02;"), то вам необходимо использовать кодировку, в которой значение кодовой точки просто является кодированной последовательностью байтов. Например, «0xE28098» является байтовой последовательностью в кодировке UTF-8 для символа « & # x2018; » (как показано в ответе 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

возвращает: & # x1F47E;

Для использования кодировок UTF-8 или UTF-16 для этого же дополнительного символа потребуется следующее:

_utf8mb4 0xF09F91BE

_utf16 0xD83DDC7E

ОДНАКО, если у вас возникли проблемы с добавлением этого в строку, уже являющуюся utf8, вам нужно будет преобразовать ее в utf8 (или в utf8mb4 при создании дополнительных символов, так как кодировка / кодировка utf8 может обрабатывать только символы BMP):

CONVERT(_utf32 0x1F47E USING utf8mb4)

Или, используя пример символа из Майкл - ответ 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).

Более подробную информацию об этих параметрах, а также escape-последовательности Unicode для других языков и платформ см. В моем сообщении:

Unicode Escape-последовательности на разных языках и платформах (включая дополнительные символы)

...