我的数据库是latin1,排序规则是latin1_swedish_ci。另外在我的php文件中我使用的是iso-8859-1。但是,如果我存储一些像'é'和其他一些字符,我在下载内容时遇到问题。所以我们在my.cnf文件中添加了默认字符集到utf8和skip-character-set-client-handshake。在每次建立连接之后和执行任何查询之前,还会在查询中添加“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/>
数据存储在数据库中的基础是什么?有时它以latin1格式存储,有时以utf8格式存储。 它是基于选项(我的意思是变量,如character_set_client,character_set_server等......)或On my.cnf配置??
考虑到所有8个案例我都没有得出结论。 我还经历了'SET Names','skip-character-set-client-handshake'的解释。但仍然处于困惑之中。存储时或在显示时是否发生转换?
$conn = mysqli_connect('<host>', '<username>', '<password>', 'table');<br/>
mysqli_query($conn, "SET NAMES 'utf8';");<br/>
mysqli_query($conn, 'insert into router.test values ("é");');<br/>
提前感谢您的回复。
答案 0 :(得分:2)
我的数据库位于latin1,排序规则为latin1_swedish_ci。
这些是默认设置。创建列和表后,每列都有一个字符集和一个排序规则。更改默认值不会更改现有列和表定义。
在我的php文件中我正在使用iso-8859-1。
没关系。 Latin1 === iso-8859-1
但如果我存储了一些像'é'这样的字符以及其他一些字符,我在下载内容方面遇到了问题。
我猜您的意思是从表中检索内容然后将其发送到Web浏览器进行渲染的两步过程。这可能是错误的第二步。尝试在php / html文件的head部分设置它。
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
如果你设置了并且所有内容都正确呈现,那么你就完成了。您也可以将其设置为unicode,看看会发生什么。如果您没有设置它,浏览器会尝试使用神秘规则进行猜测。
所以我们在my.cnf文件中添加了默认字符集到utf8和skip-character-set-client-handshake。
同样,这不会更改表格中的现有列。
数据存储在数据库中的基础是什么?
再次,根据为每列选择的字符集。
有时它以latin1格式存储,有时以utf8格式存储。
这是真的。
最佳实践:在创建时为每个表提及字符集和排序规则。如果某些列有例外情况,请在创建
列时为其添加列最佳实践:对于新数据库,请使用utfmb4。
最佳实践:始终设置数据库连接字符集。
最佳实践:阅读有关如何在php中创建和操作unicode字符串的内容。
最佳实践:在建立新的MySQL服务器时,将服务器范围的默认值设置为utfmb4和utfmb4_general_ci。
不幸的是,将现有的php应用程序迁移到unicode可能是一件痛苦的事。
答案 1 :(得分:1)
您的客户端发送C3A9
或E9
- 独立于MySQL所说的任何内容。
my.cnf
和/或SET NAMES
和/或连接参数确定SHOW VARIABLES LIKE 'character_set_%'
中的3个值。
这些设置说明解释 C3A9
或E9
为latin1
或utf8
:
C3A9
被解释为utf8:good(é
)
C3A9
被解释为latin1:Mojibake(é
)
E9
被解释为latin1:good(é
)
E8
解释为utf8:由于非utf8字节
但我们还没完成......
如果您是INSERTing
,则服务器会查看目标列的编码,将从上面(latin1或utf8)转换为列的声明。如果相同,则不需要转换,如果不同,则在存储期间发生转换。我很惊讶你没有偶然发现存储é
的“双重编码”。当utf8字节(C3A9
)被latin1
(等)错误地声明为SET NAMES
,然后存储到utf8列(因此进行另一次转换)时,会发生这种情况。
更多讨论:Trouble with UTF-8 characters; what I see is not what I stored和http://mysql.rjweb.org/doc.php/charcoll
答案 2 :(得分:0)
感谢@Rick James的回应和链接。
实际上,我从其他链接以及Rick James的上述共享链接中得到了我的问题的答案。这满足了以上所有8个案例。
如果连接(utf8)和存储字符集(latin1)之间存在差异,MySQL会将内容从一种编码转换为另一种编码。
案例1:这里我们实际上是将UTF-8字符写入latin1数据库,每个UTF-8字节序列将被解释为单独的latin1字符。组成UTF-8字符(Ã)的每个字节被解释为单独的latin1字符,并且在写入表格时将每个字符转换为UTF-8(à - - >é - &gt; c3 A9)
,即插入的字符串是é,在UTF-8(Ã)中,字符表示为两个字节,十六进制表示为C3A9。当我们将UTF-8数据插入此表时,它只将两个字节视为两个latin1字符,不进行转换,并将它们保存到表中。在对utf8执行SET-NAMES之前,它以C3A9格式插入
的MySQL&GT;插入test.test值('é');
查询正常,1行受影响(0.00秒)
的MySQL&GT;从test中选择hex(text);
+ ----------- +
| hex(文本)|
+ ----------- +
| C3A9 |
+ ----------- +
1行(0.00秒)
案例2:当我们将set-NAMES设置为utf8时,我们尝试将任何数据插入表中,它会将其视为utf8,因为目标列(文本)的类型为latin1,它将转换utf8数据(2字节 - &gt; C3E9)至latin1(1byte - > E9)。
的MySQL&GT;设置名称'utf8';
查询OK,0行受影响(0.00秒)
的MySQL&GT;插入test.test值('é');
查询正常,1行受影响(0.00秒)
的MySQL&GT;从测试中选择十六进制(文本);
+ ----------- +
| hex(文本)|
+ ----------- +
| C3A9 |
| E9 |
+ ----------- +
2行(0.00秒)
所以在对utf8执行SET-NAMES之后,从客户端发送的任何数据,尤其是像é这样的字符都会转换并以latin1格式存储,而不会被视为2个单独的latin1字符。
同时在获取数据时,它将转换回原始格式。
SET NAMES表示客户端将用于将SQL语句发送到服务器的字符集。因此,SET NAMES'utf8'告诉服务器,“来自此客户端的未来传入消息是字符集utf8。”它还指定了服务器用于将结果发送回客户端的字符集。
SET NAMES'charset_name'语句等同于这三个语句:
SET character_set_client = charset_name;
SET character_set_results = charset_name;
SET character_set_connection = charset_name;