MySQL 'set names latin1', кажется, заставляет данные храниться как utf8 - PullRequest
0 голосов
/ 15 ноября 2018

У меня есть таблица, определенная следующим образом:

mysql> show create table temptest;
+------------+-----------------------------------------------------------------------------------------------------------+
| Table      | Create Table                                                                                                  |
+------------+-----------------------------------------------------------------------------------------------------------+
| temptest | CREATE TABLE `temptest` (
  `mystring` varchar(100) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
+------------+-----------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

Когда я использую консоль mysql (через mysql temptest) и вставляю символ через

insert into temptest values ("é");

Я вижу, что он сохраняется как кодировка "latin1"

mysql> select hex(mystring) from temptest;
+---------------+
| hex(mystring) |
+---------------+
| E9            |
+---------------+

Но если я выдаю «set names latin1» и выполняю ту же операцию, я вижу, что он хранит тот же символ в кодировке utf8.

mysql> set names latin1;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into temptest values ("é");
Query OK, 1 row affected (0.01 sec)

mysql> select hex(mystring) from temptest;
+---------------+
| hex(mystring) |
+---------------+
| E9            |
| C3A9          |
+---------------+

Насколько я понимаю, "имена наборов" не должны влиять на то, как mysql хранит данные (https://dev.mysql.com/doc/refman/8.0/en/set-names.html). Что мне здесь не хватает? Любое понимание этого было бы очень признательно. Спасибо.

1 Ответ

0 голосов
/ 16 ноября 2018
  1. SET NAMES latin1 объявляет, что кодировка в вашем клиенте является латиницей 1.
  2. Но (по-видимому) на самом деле это utf8.
  3. Итак, когда вывведите é, клиент генерирует 2 байта C3 A9.
  4. Затем они отправляются , как если бы они были латинскими на сервер (mysqld).
  5. Сервер говорит: «О, я получаю несколько латиниц 1 байтов, и я буду помещать их в столбец латиниц 1, поэтому мне не нужно их преобразовывать.
  6. В ходу два латинских1 символа é (шестнадцатеричный C3A9). Это называется Мохибаке.
  7. Если вы наберете SET NAMES utf8 и SELECT текст, вы увидите "é и это будет4 байта (шестнадцатеричное C383C2A9)!

Итог: ваша клиентская кодировка была действительно utf8, поэтому вы должны были сказать SET NAMES utf8 (или utf8mb4).в клуб.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...