0

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

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

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

有没有一种简单的方法可以通过以下方式之一解决此问题:

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

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

该应用程序是高效的,编码问题对用户来说是不可见的,因为正确的编码在每条语句之前都被告知 mysqli。但我觉得这不是一个好习惯。

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

4

2 回答 2

0

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

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

在每笔交易之前发送 SET CHARACTER SET utf8。

那没用。而是SET NAMES utf8在连接后执行一次。

Ãœ是 Mojibake 的Ü。在此论坛中搜索 Mojibake。

有一些带有 utf8 字节的 latin1 表,而其他表是 utf8 - 这将是一个痛苦的混乱。现在停下来收拾烂摊子。一路转utf8。

Mojibake总结:

  • 您在客户端中的字节已正确编码为 utf8(好)。
  • 您可能默认连接到SET NAMES latin1(或set_charset('latin1')或...)。(应该是utf8。)
  • xx 表中的列已声明CHARACTER SET latin1。(或者它可能是从表/数据库继承的。)(应该是utf8。)
  • 表中的列可能是,也可能不是CHARACTER SET utf8,但它应该是。

如果您需要修复数据,则需要“2-step ALTER”,例如

ALTER TABLE Tbl MODIFY COLUMN col VARBINARY(...) ...;
ALTER TABLE Tbl MODIFY COLUMN col VARCHAR(...) ... CHARACTER SET utf8 ...;
于 2015-08-28T16:13:05.073 回答
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 查询注释掉!

于 2015-08-28T16:13:33.530 回答