MySQL unicode литералы

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

Ответ 1

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

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

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

mysql> select _utf8 x'E28098';  
+---+  
| ‘ |  
+---+  

Ответ 2

Эта хранимая функция предоставляет функциональность 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

-- http://stackoverflow.com/questions/3632410/mysql-unicode-literals/30675371#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)

Ответ 3

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