如何清理MySQL表中的编码

时间:2015-08-25 13:23:27

标签: php mysql mysqli encoding heidisql

系统是访问MySQL数据库的PHP应用程序。第一个表是使用标准的latin1编码创建的,并通过PHP中的mysqli填充,而不设置任何编码。 PHP脚本和数据都以UTF-8工作。

较新的表格已将编码设置为utf8_bin,并且在每个事务SET CHARACTER SET utf8之前都会发送。

如果我查看mysql数据库中的较新表(通过像HeidiSQL这样的sql explorer),每个特殊字符都会正确显示。但是,在每个旧表中,典型的latin1-utf8错误都可见,如ü为ü。

是否可以通过以下方式之一轻松解决此问题:

  • 修复每个表的编码,以便在sql explorer中正确显示,但保持PHP代码不变(在每个语句前面加SET CHARACTER SET utf8latin1,使表编码符合要求(仅仅是一种解决方法)
  • 将所有表格的编码切换为utf8 - >现在SET CHARACTER SET utf8必须在每个mysqli连接的开头发送(或者可能有办法将其设置为标准?)
  • 将所有表格的转换为latin1 - >无需再在事务前发送SET CHARACTER SET utf8,但在数据库资源管理器中编码错误。

似乎数据库将所有表格都视为utf8并显示latin1表格因此错误的字符。如果没有说出不同的话,Mysqli会将所有表格作为latin1。

应用程序非常高效,编码问题对用户不可见,因为正确的编码会在每个语句前面告诉mysqli。但我觉得这不是一个好习惯。

我认识到数据库的设置方式存在问题,我希望了解解决此问题的最佳做法。

2 个答案:

答案 0 :(得分:0)

  

第一个表是使用标准的latin1编码创建的,并通过PHP中的mysqli填充

所以,那些表有垃圾。你需要恢复数据吗?

  

在每个交易前面发送SET CHARACTER SET utf8。

那没用。相反,请在连接后执行SET NAMES utf8

ÃœÜ的Mojibake。在这个论坛搜索Mojibake。

有一些表latin1与utf8字节,而其他表是utf8 - 这将是一个痛苦的混乱继续。现在停下来清理乱七八糟的东西。一直走到utf8。

Mojibake摘要:

  • 客户端中的字节在utf8(正常)中正确编码。
  • 您可能默认与SET NAMES latin1(或set_charset('latin1')或...)相关联。 (应该是utf8。)
  • xx表中的列已声明为CHARACTER SET latin1。 (或者它可能是从表/数据库继承的。)(应该是utf8。)
  • 表格中的列可能是CHARACTER SET utf8,也可能不是ALTER TABLE Tbl MODIFY COLUMN col VARBINARY(...) ...; ALTER TABLE Tbl MODIFY COLUMN col VARCHAR(...) ... CHARACTER SET utf8 ...; ,但应该是这样。

如果您需要修复数据,则需要“两步更改”,例如

{{1}}

答案 1 :(得分:0)

好的,您不能使用mysqldump创建带有相关表的.sql文件,因为它会为您提供与HeidiSQL相同的垃圾字符。

但您可以使用PHP脚本执行此操作,使用与PHP应用程序中相同的错误字符集创建.sql文件。该PHP脚本应该执行以下操作:

mb_internal_encoding("UTF-8");
$link = mysqli_connect('localhost', 'root', '');

mysqli_set_charset($link, "latin1");

$result = mysqli_query($link, "SELECT * FROM table1", MYSQLI_USE_RESULT);
while($row = mysqli_fetch_assoc($result))
{
  # Generate INSERT statements for table1 using some PHP logic, and write these into a new file, named e.g. fixencoding.sql
}
mysqli_free_result($result);
mysqli_query($link, "DELETE * FROM table1");
mysqli_query($link, "ALTER TABLE table1 COLLATE='utf8_general_ci'");

$result = mysqli_query($link, "SELECT * FROM table2", MYSQLI_USE_RESULT);
while($row = mysqli_fetch_assoc($result))
{
  # Generate INSERT statements for table2 and append these into the .sql file created above
}
mysqli_free_result($result);
mysqli_query($link, "DELETE * FROM table2");
mysqli_query($link, "ALTER TABLE table2 COLLATE='utf8_general_ci'");

# etc. - repeat above steps for every broken table

mysqli_close($link);

创建的fixencoding.sql文件现在是一个没有BOM的utf-8编码文件,您可以使用mysql.exe导入该文件:

C:\path\to\mysql\bin\mysql.exe -hlocalhost -uroot name-of-database <fixencoding.sql 

如果一切顺利,您的PHP应用程序应包含正确的MySQL字符集:

mysqli_set_charset($link, 'utf8');

此外,HeidiSQL和其他客户端应该显示真正的utf-8字符。

这都没有经过测试!不要忘记先通过注释DELETE和ALTER查询来进行干运行!