php—数据将存储在数据库中的字符集

pu3pd22g  于 2021-06-25  发布在  Mysql
关注(0)|答案(9)|浏览(373)

我的数据库是拉丁文的,排序规则是拉丁文的。在我的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/>

提前感谢您的回复。

ajsxfq5m

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);
+

vawmfj5a

vawmfj5a3#

-+
|十六进制(文本)|
+

c0vxltue

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;

au9on6nz

au9on6nz5#

我的数据库是拉丁文的,排序规则是拉丁文的。
这些是默认设置。创建列和表之后,每列都有一个字符集和一个排序规则。更改默认值不会更改现有的列和表定义。
在我的php文件中,我使用的是iso-8859-1。
没关系。拉丁文1===iso-8859-1
但是如果我存储一些字符,比如'é' 还有一些我在下载内容时遇到了问题。
我想您的意思是从表中检索内容并将其发送到web浏览器进行呈现的两步过程。这是第二步,可能是错误的。试着在php/html文件的head部分设置这个。

<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">

如果你设置好了,所有的渲染都正确,你就完成了。您还可以将其设置为unicode并查看发生了什么。如果你不设置它,浏览器会尝试猜测,使用神秘的规则。
因此,我们将默认字符集添加到utf8中,并跳过my.cnf文件中的字符集客户端握手。
同样,这不会更改表中现有的列。
数据存储在数据库中的依据是什么?
同样,根据为每列选择的字符集。
有时它以拉丁文1格式存储,有时以utf8格式存储。
这是真的。
最佳实践:在创建每个表时,提及每个表的字符集和排序规则。如果对某些列有异常,请在创建列时对其进行说明
最佳实践:对于新数据库,使用utfmb4。
最佳实践:始终设置数据库连接字符集。
最佳实践:阅读如何在php中创建和操作unicode字符串。
最佳实践:在建立新的mysql服务器时,将服务器范围的默认值设置为utfmb4和utfmb4\u general\u ci。
不幸的是,将现有的php应用程序迁移到unicode可能是一个棘手的问题。

db2dz4w8

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);
+

3wabscal

3wabscal7#

-+
|十六进制(文本)|
+

qgzx9mmu

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

相关问题