我试图使用UTF-8遇到麻烦。
我尝试了很多事情;这是我得到的结果:
????
而不是亚洲字符。即使是欧洲文字,我也能Se?or
接受Señor
。- 奇怪的乱码(变为乱码?),如
Señor
或新浪新闻
为新浪新闻
。 - 黑钻石,例如Seor。
- 最终,我陷入了数据丢失或至少被截断的情况:
Se
forSeñor
。 - 即使我看到正确的文本,它也无法正确排序。
我究竟做错了什么?我该如何修复代码?我可以恢复数据吗?
Answers:
这个问题困扰着该站点的参与者以及其他许多人。
您列出了五个主要的CHARACTER SET
麻烦案例。
最佳实践
展望未来,最好使用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>
在HTML的开头有关计算机语言的更多详细信息(及其后续部分)
测试数据
使用工具或工具查看数据SELECT
是不可信的。太多这样的客户端,尤其是浏览器,试图补偿不正确的编码,并向您显示正确的文本,即使数据库已损坏。因此,选择一个包含非英语文本的表和列,然后执行
SELECT col, HEX(col) FROM tbl WHERE ...
正确存储的UTF-8的十六进制将为
20
4x
,5x
,6x
,或者7x
Cxyy
Dxyy
Exyyzz
F0yyzzww
出现问题的具体原因和解决方法
截断的文字(Se
为Señor
):
黑钻石与问号(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
。)Mojibake(Señor
for Señor
):(此讨论也适用于Double Encoding,它不一定可见。)
INSERTing
和SELECTing
文本的连接需要指定utf8或utf8mb4。解决这个问题。CHARACTER SET utf8
(或utf8mb4)。解决这个问题。<meta charset=UTF-8>
。如果数据看起来正确,但排序不正确,则说明您选择了错误的排序规则,或者没有适合您的排序规则,或者您使用了Double Encoding。
通过执行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种不同修复;请谨慎选择):http : //mysql.rjweb.org/doc.php/charcoll#fixes_for_various_cases
SET NAMES utf8mb4
在连接之后立即执行,第二好。毕竟,这是在client中声明编码。
utf8mb4
和utf8mb4_0900_ai_ci
。大多数用户应在不考虑其他字符集和排序规则的情况下使用它们。
FUNCTION
或,STORED PROCEDURE
则在创建所需的字符集时可能没有使用过。 DROP
它SET NAMES
;重新CREATE
。
服务器迁移后,我的两个项目也遇到了类似的问题。在搜索并尝试了许多解决方案之后,我遇到了这个解决方案:
mysqli_set_charset($con,"utf8");
将这一行添加到我的配置文件后,一切正常!
当我想从html查询中解决插入问题时,我找到了针对mysqli https://www.w3schools.com/PHP/func_mysqli_set_charset.asp的解决方案
祝好运!
mysqli
无效PDO
。
有趣的是你如何回答自己的问题:)
将您的代码IDE语言设置为UTF8
添加到您收集数据表单的网页标题中。
检查您的MySQL表定义如下所示:
CREATE TABLE your_table (
...
) ENGINE=InnoDB DEFAULT CHARSET=utf8
如果您使用的是PDO,请确保
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND=>'SET NAMES utf8');
$dbL = new PDO($pdo, $user, $pass, $options);
如果您已经有一个具有上述问题的大型数据库,则可以尝试使用正确的字符集导出SIDU,然后使用UTF8导入回来。祝好运
DEFAULT CHARSET
一个表,只是,一个默认。在列定义中可以覆盖它,有时应该覆盖它。
$db = new PDO('dblib:host=host;dbname=db;charset=UTF8', $user, $pwd);
这在我的'charcoll'文档的链接中列出。)
ALTER DATABASE
语句不需要重新启动MySQL即可生效。但是,更改数据库的默认字符集不会影响数据库中当前存在的任何表。它仅对新表有影响,例如CREATE TABLE
不为该表指定默认字符集;这就是数据库默认字符集起作用的时候。没有指定列字符集时,它只有在添加到表中,列的效果;(类似地,改变所述表中的默认字符集不存在于表影响列已经。
我也在寻找相同的问题,我花了近一个月的时间才找到合适的解决方案。首先,您必须更新数据库,将所有最近的CHARACTER和COLLATION更新为支持utf-8数据的utf8mb4或atleast。
对于Java:
在进行JDBC连接时,将此参数添加到连接URL中,使用Unicode = yes&characterEncoding = UTF-8作为参数,它将起作用。
对于python:
在查询数据库之前,请尝试通过游标强制执行此操作*
cursor.execute('SET NAMES utf8mb4')
cursor.execute("SET CHARACTER SET utf8mb4")
cursor.execute("SET character_set_connection=utf8mb4")
*
如果不起作用,请寻找正确的解决方案。
SETs
不是Python的“正确”方法;参见mysql.rjweb.org/doc.php/charcoll#python 该博客的其他地方讨论了许多其他语言。
SET
语句基本上可以解决。
根据服务器的设置方式,您必须相应地更改编码。您所说的utf8应该效果最好,但是如果您遇到奇怪的字符,则可以将网页编码更改为Ansi。当我设置PHP MYSQL时,这对我有所帮助,这可能有助于您了解更多/superuser/762473/ansi-to-utf-8-in-notepad
ANSI
可能最接近MySQL latin1
。该链接中的0x93“
可能来自Word之类的地方。您可以转换为utf8(hex E2809C
),也可以告诉MySQL数据是正确的,latin1
并希望您不要在其他地方绊倒。
utf8mb4
我看来能够存储表情符号很好。一些博客建议也设置collation-server
和character-set-server
mysqld中。我真的需要更改mysqld
服务器设置有什么区别吗?