我有一个表定义如下:
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 test)并通过
insert into temptest values ("é");
我可以看到它被保存为“拉丁1”编码
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 |
+---------------+
据我所知,“set names”不应该影响mysql存储数据的方式(https://dev.mysql.com/doc/refman/8.0/en/set-names.html). 我错过了什么?对此有任何见解都将不胜感激。谢谢您。
1条答案
按热度按时间hkmswyz61#
SET NAMES latin1
声明客户端中的编码为拉丁1。但是(显然)它实际上是utf8。
所以,当你打字的时候
é
,客户端生成2个字节C3 A9
.然后将它们发送到服务器(mysqld),就好像它们是拉丁文1一样。
服务器说:“哦,我得到了一些拉丁1字节,我将把它们放入拉丁1列,所以我不需要转换它们。
两个拉丁字符
é
(六角c3a9)。这叫莫吉巴克。如果你这样做了
SET NAMES utf8
以及SELECT
文本,你会“看到”é
它将是4个字节(十六进制)C383C2A9
)!一句话:您的客户机编码实际上是utf8,所以您应该说
SET NAMES utf8
(或utf8mb4)。困惑的?欢迎来到俱乐部。