将 UTF8 表上的 latin1 字符转换为 UTF8

Posted

技术标签:

【中文标题】将 UTF8 表上的 latin1 字符转换为 UTF8【英文标题】:Convert latin1 characters on a UTF8 table into UTF8 【发布时间】:2012-03-13 13:12:41 【问题描述】:

直到今天我才意识到我的 php 脚本中缺少这个:

mysql_set_charset('utf8');

我所有的表都是 InnoDB,排序规则“utf8_unicode_ci”,我所有的 VARCHAR 列也是“utf8_unicode_ci”。我的 PHP 脚本中有mb_internal_encoding('UTF-8');,我所有的 PHP 文件都编码为 UTF-8。

所以,直到现在,每次我“插入”带有变音符号的东西时,例如:

mysql_query('INSERT INTO `table` SET `name`="Jáuò Iñe"');

在本例中,“名称”内容为:Jáuò Iñe

由于我修复了 PHP 和 MySQL 之间的字符集,新的 INSERT 现在可以正确存储。但是,我想修复目前“混乱”的所有旧行。我已经尝试了很多东西,但它总是会破坏第一个“非法”字符的字符串。这是我当前的代码:

$m = mysql_real_escape_string('¿<?php echo "¬<b>\'PHP &aacute; (á)ţăriîş </b>"; ?> ă-ţi abcdd;//;ñç´พดแทฝใจคçăâξβψδπλξξςαยนñ ;');
mysql_set_charset('utf8');
mysql_query('INSERT INTO `table` SET `name`="'.$m.'"');
mysql_set_charset('latin1');
mysql_query('INSERT INTO `table` SET `name`="'.$m.'"');
mysql_set_charset('utf8');

$result = mysql_iquery('SELECT * FROM `table`');
while ($row = mysql_fetch_assoc($result)) 
    $message = $row['name'];
    $message = mb_convert_encoding($message, 'ISO-8859-15', 'UTF-8');
    //$message = iconv("UTF-8", "ISO-8859-1//IGNORE", $message);
    mysql_iquery('UPDATE `table` SET `name`="'.mysql_real_escape_string($message).'" WHERE `a1`="'.$row['a1'].'"');

它使用预期的字符“更新”,除了字符串在字符“ă”之后被截断。我的意思是,该字符和后面的字符不包含在字符串中。

此外,使用“iconv()”(在代码上注释)进行测试也是如此,即使使用 //IGNORE 和 //TRANSLIT

我还测试了几个字符集,介于 ISO-8859-1 和 ISO-8859-15 之间。

【问题讨论】:

【参考方案1】:

根据您的描述,您似乎有最初存储为 Latin-1 的 UTF-8 数据,然后没有正确转换为 UTF-8。数据可恢复;你需要一个像

这样的 MySQL 函数
convert(cast(convert(name using  latin1) as binary) using utf8)

您可能需要省略内部转换,具体取决于编码转换期间数据的更改方式。

【讨论】:

哇,你拯救了我的一天!我从未使用过这些功能,现在在 UPDATE 上使用并且它有效。非常感谢! 谢谢!我已经构建了一个小的 php 脚本,它遍历每个表中的所有列。成功了吗:) 非常感谢 ABS!!!!很多相关的 SO 问题,但只有这一个包含正确转换为 UTF-8 的功能 您的回答对我的修复很有帮助。谢谢 5 年多后,这个很棒的答案让我免于心痛。你简直太棒了。但是,我有一个问题:如果要转换的列很多,通配符可以代替名称吗?【参考方案2】:

在我搜索了大约一两个小时来寻找这个答案之后,我需要将一个旧的 tt_news 数据库从打字错误迁移到一个新的打字错误版本。我尝试转换导出文件中的字符集并将其导入回来,但没有得到它的工作。

然后我从 ABS 尝试了上面的答案,并开始在桌子上更新:

UPDATE tt_news SET 
    title=convert(cast(convert(title using  latin1) as binary) using utf8), 
    short=convert(cast(convert(short using  latin1) as binary) using utf8), 
    bodytext=convert(cast(convert(bodytext using  latin1) as binary) using utf8)
WHERE 1

如果需要,您还可以转换 imagecaption、imagealttext、imagetitletext 和关键字。 希望这将有助于有人将 tt_news 迁移到新的typo3 版本。

【讨论】:

在我找到你的答案之前,我没有得到 ABS 的答案。 确实,ABS 的答案是答案的“关键”。马塞尔的回答在一个完整的例子中使用了那个“钥匙”。两个都投赞成票! 赞成任何跨数据库导出/导入的关键查询。拯救了我的一天!【参考方案3】:

方法更好 使用连接拖你的数据库正常

然后使用此代码来制作您需要的东西 您必须在 header cod html 中通过 meta 使您的页面编码 utf-8(不要忘记这一点)

然后使用此代码

    $result = mysql_query('SELECT * FROM shops');
    while ($row = mysql_fetch_assoc($ 
    $name= iconv("windows-1256", "UTF-8", $row['name']);

   mysql_query("SET NAMES 'utf8'"); 
   mysql_query("update   `shops` SET `name`='".$name."'  where ID='$row[ID]'  ");
    

【讨论】:

这不是更好,而且当名称第一次包含撇号时,您的方式就会中断。另外,为什么要为每一行执行“SET NAMES”?【参考方案4】:

我强烈建议使用 'utf8mb4' 而不是 'utf8',因为 utf8 不能存储一些汉字和表情符号。

【讨论】:

True,但不是问题的答案。

以上是关于将 UTF8 表上的 latin1 字符转换为 UTF8的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 将 latin1 数据转换为 UTF8

FAQ系列 | utf8表存储latin1乱码字符转换

数据库从 latin1 到 utf8mb4 的转换,索引呢?

MySQL Convert latin1 to utf8, cp1252 0x80-0x9F 错误

python2.7 怎样将中文字符串转为字节流?

将数据字符串转换为 UTF8 的问题