MySQL的特殊字符错误


MySQL error on special chars

我有一个MySQL数据库托管在一些提供商。过去3年一切正常,但不知何故,从昨天开始,所有特殊字符现在都显示为无效字符。例如:

'sugestão' now shows as 'sugestão'

我没有对数据库做任何更改,主机公司声称他们无能为力。最奇怪的是,新包含的数据没有受到这个问题的影响,只有昨天之前包含的数据才受到影响。

我知道主机后端发生了一些事情,但他们拒绝承认,因为他们声称他们没有任何日志来证明我没有更改DB字符集或排序。当然,我知道我没有这样做,这是一个运行了3年的应用程序,从来没有出现过这个问题。

所以我自己来解决这个问题,通过更新所有的列与这种问题手动,在每个表。是否有一种方法可以在MySql工作台本身内更快地做到这一点,而不是创建一些应用程序?

例如,我有一个名为"CRM"的表。下面是一些示例结果集:

select * from crm;
cr_date     cr_history
2016-07-11  Quer sugestão 
2016-07-11  País de destino : Canadá

下面是这个结果集在问题出现之前的样子,以及我需要如何修复它才能再次回头看:

select * from crm;
cr_date     cr_history
2016-07-11  Quer sugestão 
2016-07-11  País de destino : Canadá

是否有办法做一个更新查询更改所有'ã'字符串内的列'ã',保持其余的列内容完好无损?

类似这样:将字段中'ã'的所有货币替换为'ã'。类似于PHP的str_replace,但是直接在Mysql中。

只是为了添加更多的信息,数据库是由PHP应用程序访问的,但是问题发生在直接从MySQL Workbench访问数据库,所以这不是PHP相关的问题。

当某些东西将UTF-8数据存储在ANSI(或其他非utf)列中时,这是一个非常典型的(并且经常看到的)结果。PHP似乎特别容易出现这种类型的错误(我以前见过几次)。因此,在检索数据时,它被解释为列的编码而不是其真实编码-因此显示错误。

你可以很容易地看到这样:

mysql> SELECT CAST(_latin1'müller' AS CHAR CHARACTER SET utf8);
+---------------------------------------------------+
| CAST(_latin1'müller' AS CHAR CHARACTER SET utf8)  |
+---------------------------------------------------+
| müller                                           |
+---------------------------------------------------+
1 row in set (0,00 sec)
mysql> SELECT CAST('müller' AS CHAR CHARACTER SET utf8);
+--------------------------------------------+
| CAST('müller' AS CHAR CHARACTER SET utf8)  |
+--------------------------------------------+
| müller                                     |
+--------------------------------------------+
1 row in set (0,00 sec)

您可以做的是为该列设置正确的编码((My)SQL中的charset)。您可以使用ALTER TABLE命令,但这将进一步打乱现有的值(它将尝试在UTF-8中重新编码已经编码的值)。所以一个更好的方法是:

  • 使用UTF-8字符集+排序规则添加新列。
  • 更新表并将新列的值设置为旧列的值。这里重要的是将旧列的字符集转换为其真实值(UTF-8)。这将不会转换数据,而只是将现有字节存储在新列中,但这一次使用正确的编码。
  • 一旦完成,删除旧列并将新列重命名为旧名。

有了这个额外的列,您可以确保您不会丢失数据(备份仍然是可取的),如果出现问题,您可以删除它并重新开始。