我的数据库是拉丁文的,排序规则是拉丁文的。在我的php文件中,我也使用iso-8859-1。但是如果我存储一些字符,比如'é' 还有一些我在下载内容时遇到了问题。因此,我们将默认字符集添加到utf8中,并跳过my.cnf文件中的字符集客户端握手。在每次建立连接之后和执行任何查询之前,在查询中还添加了“set name utf8”。这就解决了问题。但我做了如下观察
Case 1:
Mysql conf file: No default character-set and no skip-character-set-client-handshake
Query: No set names
Result:
mysql> show variables like '%charac%';<br/>
+--------------------------+----------------------------+<br/>
| Variable_name | Value |<br/>
+--------------------------+----------------------------+<br/>
| character_set_client | latin1 |<br/>
| character_set_connection | latin1 |<br/>
| character_set_database | latin1 |<br/>
| character_set_filesystem | binary |<br/>
| character_set_results | latin1 |<br/>
| character_set_server | latin1 |<br/>
| character_set_system | utf8 |<br/>
| character_sets_dir | /usr/share/mysql/charsets/ |<br/>
+--------------------------+----------------------------+<br/>
stored ->é(utf8)(Hex->C3A9)<br/>
Case2:
Mysql conf file: Default character-set - utf8 and no skip-character-set-client-handshake
Query: No set names<br/>
Result:
mysql> show variables like '%charac%';<br/>
+--------------------------+----------------------------+<br/>
| Variable_name | Value |<br/>
+--------------------------+----------------------------+<br/>
| character_set_client | latin1 |<br/>
| character_set_connection | latin1 |<br/>
| character_set_database | utf8 |<br/>
| character_set_filesystem | binary |<br/>
| character_set_results | latin1 |<br/>
| character_set_server | utf8 |<br/>
| character_set_system | utf8 |<br/>
| character_sets_dir | /usr/share/mysql/charsets/ |<br/>
+--------------------------+----------------------------+<br/>
<br/>
stored ->é(utf8)(Hex->C3A9)<br/>
Case3:
Mysql conf file: Default character-set - utf8 and skip-character-set-client-handshake
Query: No set names<br/>
Result:
mysql> show variables like '%charac%';<br/>
+--------------------------+----------------------------+<br/>
| Variable_name | Value |<br/>
+--------------------------+----------------------------+<br/>
| character_set_client | utf8 |<br/>
| character_set_connection | utf8 |<br/>
| character_set_database | utf8 |<br/>
| character_set_filesystem | binary |<br/>
| character_set_results | utf8 |<br/>
| character_set_server | utf8 |<br/>
| character_set_system | utf8 |<br/>
| character_sets_dir | /usr/share/mysql/charsets/ |<br/>
+--------------------------+----------------------------+<br/>
8 rows in set (0.00 sec)<br/>
stored ->é(latin1)(Hex->E9)<br/>
Case4:
Mysql conf file: no Default characterset - utf8 and skip-character-set-client-handshake
Query: No set names<br/>
Result:
mysql> show variables like '%charac%';<br/>
+--------------------------+----------------------------+<br/>
| Variable_name | Value |<br/>
+--------------------------+----------------------------+<br/>
| character_set_client | utf8 |<br/>
| character_set_connection | utf8 |<br/>
| character_set_database | utf8 |<br/>
| character_set_filesystem | binary |<br/>
| character_set_results | utf8 |<br/>
| character_set_server | utf8 |<br/>
| character_set_system | utf8 |<br/>
| character_sets_dir | /usr/share/mysql/charsets/ |<br/>
+--------------------------+----------------------------+<br/>
8 rows in set (0.00 sec)<br/>
stored ->é(utf8)(Hex->C3A9)<br/>
Case5:
Mysql conf file: Default characterset - utf8 and skip-character-set-client-handshake
Query: set names utf8<br/>
Result:
mysql> show variables like '%charac%';<br/>
+--------------------------+----------------------------+<br/>
| Variable_name | Value |<br/>
+--------------------------+----------------------------+<br/>
| character_set_client | utf8 |<br/>
| character_set_connection | utf8 |<br/>
| character_set_database | utf8 |<br/>
| character_set_filesystem | binary |<br/>
| character_set_results | utf8 |<br/>
| character_set_server | utf8 |<br/>
| character_set_system | utf8 |<br/>
| character_sets_dir | /usr/share/mysql/charsets/ |<br/>
+--------------------------+----------------------------+<br/>
8 rows in set (0.00 sec)<br/>
stored ->é(latin1)(Hex->E9)<br/>
Case6:
Mysql conf file: Default characterset - utf8 and no skip-character-set-client-handshake
Query: set names utf8<br/>
Result:
mysql> show variables like '%charac%';<br/>
+--------------------------+----------------------------+<br/>
| Variable_name | Value |<br/>
+--------------------------+----------------------------+<br/>
| character_set_client | latin1 |<br/>
| character_set_connection | latin1 |<br/>
| character_set_database | utf8 |<br/>
| character_set_filesystem | binary |<br/>
| character_set_results | latin1 |<br/>
| character_set_server | utf8 |<br/>
| character_set_system | utf8 |<br/>
| character_sets_dir | /usr/share/mysql/charsets/ |<br/>
+--------------------------+----------------------------+<br/>
8 rows in set (0.00 sec)<br/>
stored ->é(latin1)(Hex->E9)<br/>
Case7:
Mysql conf file: no Default characterset and no skip-character-set-client-handshake
Query: set names utf8<br/>
Result:
mysql> show variables like '%charac%';<br/>
+--------------------------+----------------------------+<br/>
| Variable_name | Value |<br/>
+--------------------------+----------------------------+<br/>
| character_set_client | latin1 |<br/>
| character_set_connection | latin1 |<br/>
| character_set_database | latin1 |<br/>
| character_set_filesystem | binary |<br/>
| character_set_results | latin1 |<br/>
| character_set_server | latin1 |<br/>
| character_set_system | utf8 |<br/>
| character_sets_dir | /usr/share/mysql/charsets/ |<br/>
+--------------------------+----------------------------+<br/>
8 rows in set (0.00 sec)<br/>
stored ->é(latin1)(Hex->E9)<br/>
Case8:
Mysql conf file: no Default characterset and skip-character-set-client-handshake
Query: set names utf8<br/>
Result:
mysql> show variables like '%charac%';<br/>
+--------------------------+----------------------------+<br/>
| Variable_name | Value |<br/>
+--------------------------+----------------------------+<br/>
| character_set_client | latin1 |<br/>
| character_set_connection | latin1 |<br/>
| character_set_database | latin1 |<br/>
| character_set_filesystem | binary |<br/>
| character_set_results | latin1 |<br/>
| character_set_server | latin1 |<br/>
| character_set_system | utf8 |<br/>
| character_sets_dir | /usr/share/mysql/charsets/ |<br/>
+--------------------------+----------------------------+<br/>
8 rows in set (0.00 sec)<br/>
stored ->é(latin1)(Hex->E9)<br/>
Output containing all the 8 cases together<br/>
+-----------+------------------------------------------------------------------+<br/>
| HEX(name) | desc |<br/>
+-----------+------------------------------------------------------------------+<br/>
| C3A9 | no skip handshake and no default in conf and nothing in query |<br/>
| C3A9 | no skip handshake and default utf8 in conf and nothing in query |<br/>
| E9 | skip handshake and default utf8 in conf and nothing in query |<br/>
| C3A9 | skip handshake and no default in conf and nothing in query |<br/>
| E9 | skip handshake and default utf8 in conf and utf8 in query |<br/>
| E9 | no skip handshake and default utf8 in conf and utf8 in query |<br/>
| E9 | no skip handshake and no default in conf and utf8 in query |<br/>
| E9 | skip handshake and no default in conf and utf8 in query |<br/>
+-----------+------------------------------------------------------------------+<br/>
数据存储在数据库中的依据是什么?有时它以拉丁文1格式存储,有时以utf8格式存储。它是基于选项(我是指像character\u set\u client、character\u set\u server等变量)还是基于我的.cnf配置??
考虑到所有的8个案例,我还没有得出结论。我还对“set names”、“skip character set client handshake”进行了解释。但仍然困惑。存储或显示时是否发生转换??
上面的观察是使用包含以下行的php脚本完成的。
$conn = mysqli_connect('<host>', '<username>', '<password>', 'table');<br/>
mysqli_query($conn, "SET NAMES 'utf8';");<br/>
mysqli_query($conn, 'insert into router.test values ("é");');<br/>
提前感谢您的回复。
9条答案
按热度按时间omvjsjqw1#
-+
|c3a9型|
+
ajsxfq5m2#
感谢您的回复和链接@rick james。
事实上,我的问题的答案来自于其他的链接,也来自上面rick james的共享链接。满足上述8种情况。
如果连接(utf8)和存储字符集(latin1)之间存在差异,mysql会将内容从一种编码转换为另一种编码。
案例1:这里我们实际上是在将utf-8字符写入拉丁1数据库,每个utf-8字节序列都将被解释为单独的拉丁1字符。每个字节组成一个utf-8字符(ã©) 被解释为单独的拉丁文1字符,写入表时每个字符都转换为utf-8(ã © -> ム⩠-> c3(a9)
i、 例如,插入的字符串是é, 在utf-8中(ã©) 字符表示为两个字节,十六进制表示为c3a9。当我们将utf-8数据插入这个表时,它只将发送的两个字节作为两个拉丁字符处理,不进行转换,并将它们保存到表中。在执行此操作之前,将名称设置为utf8,并以c3a9格式插入
mysql>插入test.test values('é');
查询正常,1行受影响(0.00秒)
mysql>从test中选择hex(text);
+
vawmfj5a3#
-+
|十六进制(文本)|
+
c0vxltue4#
-+
设置2行(0.00秒)
所以在做了这些之后,将名称设置为utf8,不管从客户端发送什么数据,特别是像这样的字符é 转换并以拉丁文1格式存储,不作为两个独立的拉丁文1字符处理。
另外,在获取数据时,它将转换回原始格式。
set names指示客户端将使用哪个字符集向服务器发送sql语句。因此,set names'utf8'告诉服务器,“将来从这个客户机传入的消息是字符集utf8。”它还指定了服务器应该用来将结果发送回客户机的字符集。
set names“charset\u name”语句等价于以下三种语句:
set character\u set\u client=charset\u name;
set character\u set\u results=charset\u name;
set character\u set\u connection=charset\u name;
au9on6nz5#
我的数据库是拉丁文的,排序规则是拉丁文的。
这些是默认设置。创建列和表之后,每列都有一个字符集和一个排序规则。更改默认值不会更改现有的列和表定义。
在我的php文件中,我使用的是iso-8859-1。
没关系。拉丁文1===iso-8859-1
但是如果我存储一些字符,比如'é' 还有一些我在下载内容时遇到了问题。
我想您的意思是从表中检索内容并将其发送到web浏览器进行呈现的两步过程。这是第二步,可能是错误的。试着在php/html文件的head部分设置这个。
如果你设置好了,所有的渲染都正确,你就完成了。您还可以将其设置为unicode并查看发生了什么。如果你不设置它,浏览器会尝试猜测,使用神秘的规则。
因此,我们将默认字符集添加到utf8中,并跳过my.cnf文件中的字符集客户端握手。
同样,这不会更改表中现有的列。
数据存储在数据库中的依据是什么?
同样,根据为每列选择的字符集。
有时它以拉丁文1格式存储,有时以utf8格式存储。
这是真的。
最佳实践:在创建每个表时,提及每个表的字符集和排序规则。如果对某些列有异常,请在创建列时对其进行说明
最佳实践:对于新数据库,使用utfmb4。
最佳实践:始终设置数据库连接字符集。
最佳实践:阅读如何在php中创建和操作unicode字符串。
最佳实践:在建立新的mysql服务器时,将服务器范围的默认值设置为utfmb4和utfmb4\u general\u ci。
不幸的是,将现有的php应用程序迁移到unicode可能是一个棘手的问题。
db2dz4w86#
-+
一行一组(0.00秒)
案例2:当我们将名称设置为utf8时,无论我们试图插入到表中的数据是什么,它都会将其视为utf8,因为目标列(文本)的类型是latin1,它会将utf8数据(2bytes->c3e9)转换为latin1(1byte->e9)。
mysql>设置名称'utf8';
查询正常,0行受影响(0.00秒)
mysql>插入test.test values('é');
查询正常,1行受影响(0.00秒)
mysql>从test中选择hex(text);
+
3wabscal7#
-+
|十六进制(文本)|
+
qgzx9mmu8#
你的客户发送
C3A9
或者E9
--不管mysql说什么。my.cnf
和/或SET NAMES
和/或连接参数确定中的3个值SHOW VARIABLES LIKE 'character_set_%'
.这些设置说明是否要解释
C3A9
或者E9
作为latin1
或者utf8
:C3A9
解释为utf8:好(é
)C3A9
解释为拉丁语1:mojibake(é
)E9
解释为拉丁语1:好(é
)E8
解释为utf8:由于非utf8字节,字符串被截断但我们还没有结束。。。
如果你是
INSERTing
,然后服务器查看目标列的编码,并从上面的(latin1或utf8)转换为列的声明。如果相同,则不需要转换;如果不同,则在存储期间发生转换。我很惊讶你没有偶然发现“双重编码”é
已存储。当utf8字节(C3A9
)被错误地宣布为latin1
通过SET NAMES
(etc),然后存储到utf8列中(因此需要另一个转换)。更多讨论:utf-8字符的问题;我所看到的并不是我储存和储存的东西http://mysql.rjweb.org/doc.php/charcoll
p8h8hvxi9#
-+
|c3a9型|
|e9级|
+