我尝试使用UTF-8遇到了麻烦。
我尝试了很多方法,以下是我的尝试结果:
- 亚洲字符被替换成了
????
。即使对于欧洲文本,也会得到Se?or
而不是Señor
。 - 出现了奇怪的乱码(Mojibake),例如
Señor
或新浪新闻
代替新浪新闻
。 - 出现了黑色菱形,如Se�or。
- 最后,我陷入了一种情况,数据丢失了,或者至少被截断了:
Se
代替Señor
。 - 即使我让文本看起来正确,它也不能正确排序。
我错在哪里了?如何修复代码?如果可以,我可以恢复数据吗?
我尝试使用UTF-8遇到了麻烦。
我尝试了很多方法,以下是我的尝试结果:
????
。即使对于欧洲文本,也会得到Se?or
而不是Señor
。Señor
或新浪新闻
代替新浪新闻
。Se
代替Señor
。我错在哪里了?如何修复代码?如果可以,我可以恢复数据吗?
这个问题困扰着该网站的参与者和许多其他人。
您列出了五种主要的字符集
问题。
最佳实践
从现在开始,最好使用CHARACTER SET utf8mb4
和COLLATION utf8mb4_unicode_520_ci
。(有一个新版本的Unicode排序正在进行中。)
utf8mb4
是utf8
的超集,因为它处理需要表情符号和一些汉字的4字节utf8代码。
在MySQL之外,“UTF-8”指所有大小编码,因此有效地与MySQL的utf8mb4
相同,而不是utf8
。
我将尝试使用这些拼写和大写来区分以下MySQL内部和外部。
您应该做什么的概述
<form accept-charset="UTF-8">
。CHARACTER SET utf8mb4
(通过SHOW CREATE TABLE
来检查)。<meta charset=UTF-8>
计算机语言的更多详细信息(以及后续章节)
测试数据
使用工具或SELECT
查看数据是不能完全信任的。太多这样的客户端,特别是浏览器,会尝试补偿不正确的编码,并在数据库被破坏时展示正确的文本。因此,请选择一个包含一些非英语文本的表和列,并执行以下操作:
SELECT col, HEX(col) FROM tbl WHERE ...
正确存储UTF-8的十六进制为:
20
4x
、5x
、6x
或7x
Cxyy
Dxyy
Exyyzz
F0yyzzww
问题的具体原因和解决方法
截断的文本(Señor
的Se
):
黑色菱形带问号(Se�or
代表Señor
); 存在以下情况之一:
情况1(原始字节不是UTF-8):
SET NAMES
)用于INSERT
和SELECT
的字符集不是utf8 / utf8mb4。 请修复此问题。CHARACTER SET utf8
(或utf8mb4)。情况2(原始字节是UTF-8):
SET NAMES
)用于SELECT
的字符集不是utf8 / utf8mb4。 请修复此问题。CHARACTER SET utf8
(或utf8mb4)。只有当浏览器设置为<meta charset=UTF-8>
时,才会出现黑色菱形。
问号(普通的,不是黑色菱形)(Se?or
表示 Señor
):
CHARACTER SET utf8
(或 utf8mb4)。请修复此问题。(使用 SHOW CREATE TABLE
。)乱码(Señor
表示 Señor
):
(此讨论也适用于双重编码,其不一定可见。)
INSERT
和SELECT
文本时的连接需要指定utf8或utf8mb4。请修复此问题。CHARACTER SET utf8
(或utf8mb4)。请修复此问题。<meta charset=UTF-8>
开头。如果数据看起来正确,但无法正确排序,则可能是选择了错误的排序规则, 或者没有适合您需求的排序规则, 或者存在双重编码。
可以通过执行上述SELECT .. HEX ..
来确认双重编码。
é should come back C3A9, but instead shows C383C2A9
The Emoji should come back F09F91BD, but comes back C3B0C5B8E28098C2BD
也就是说,十六进制长度大约是应该长度的两倍。
这是由于从latin1(或其他编码)转换为utf8,然后将这些字节视为latin1并重复转换所导致的。
排序(和比较)不正确,因为例如按照字符串Señor
排序。
尽可能修复数据
对于截断和问号,数据丢失。
对于Mojibake / 双重编码,...
对于黑色菱形,...
在此列出了修复方法:5种不同情况的5种不同修复方法;请谨慎选择
相关:字符集混合错误
在服务器迁移后,我的两个项目也遇到了类似的问题。在经过大量搜索和尝试各种解决方案之后,我找到了这个:
mysqli_set_charset($con,"utf8mb4");
在我的配置文件中添加了这行后,一切正常!
当我想解决从HTML查询中插入数据时,我发现了这个适用于MySQLi的解决方案——PHP mysqli set_charset()函数。
mysqli
而非PDO
时有效。 - Rick Jamescursor.execute("SET NAMES utf8mb4")
cursor.execute("SET CHARACTER SET utf8mb4")
cursor.execute("SET character_set_connection=utf8mb4")
SETs
不是Python的“正确”方式;请参见http://mysql.rjweb.org/doc.php/charcoll#python。许多其他语言在该博客的其他地方都有讨论。 - Rick JamesSet your code IDE language to UTF-8
Add <meta charset="utf-8"> to your webpage header where you collect data form.
Check your MySQL table definition looks like this:
CREATE TABLE your_table (
...
) ENGINE=InnoDB DEFAULT CHARSET=utf8
If you are using PDO, make sure
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND=>'SET NAMES utf8');
$dbL = new PDO($pdo, $user, $pass, $options);
$db = new PDO('dblib:host=host;dbname=db;charset=UTF8', $user, $pwd);
(这在我的“charcoll”文档链接中列出)。 - Rick JamesALTER DATABASE
语句生效。但是,更改数据库的默认字符集不会影响当前数据库中的任何表;它只对新表(例如CREATE TABLE
)产生影响,这些表没有为表指定默认字符集时,才会使用数据库默认字符集。(同样地,更改表的默认字符集不会影响已经存在于表中的列;它只对添加到表中的列产生影响,当没有指定列字符集时。 - spencer7593根据服务器的设置,您必须相应地更改编码。从您所说的来看,utf8 应该是最好的选择。但是,如果您遇到奇怪的字符,将网页编码更改为 ANSI 可能会有所帮助。
当我设置 PHP MySQLi 时,这对我很有帮助。这可能会帮助您更好地理解:在 Notepad++ 中将 ANSI 转换为 UTF-8
E2809C
),或者告诉 MySQL 数据是 “latin1”,希望你不会在其他地方出现问题。 - Rick James
utf8mb4
,我似乎可以很好地存储表情符号。一些博客建议在 mysqld 中设置collation-server
和character-set-server
。我真的需要更改mysqld
吗?服务器设置有什么区别吗? - david_adlerSET NAMES utf8mb4
。毕竟,这是在客户端中声明编码方式。 - Rick JamesFUNCTION
或者STORED PROCEDURE
,你可能在创建它时没有使用所需的字符集。请将其DROP
掉,然后通过SET NAMES
重新CREATE
。 - Rick James