Php 特殊字符上的MySQL错误

Php 特殊字符上的MySQL错误,php,mysql,mysql-workbench,Php,Mysql,Mysql Workbench,我有一个MySQL数据库托管在某个提供商中。在过去的三年里,一切正常,但从昨天起,所有特殊角色现在都显示为无效字符。例如: 'sugestão' now shows as 'sugestão' 我没有对数据库做任何更改,主办公司声称他们无能为力。最奇怪的是,新的夹杂物并没有受到这个问题的影响,只有昨天之前的数据 我知道主机后端发生了一些事情,但他们拒绝承认,因为他们声称没有任何日志来证明我没有更改DB字符集或排序规则。但当然,我知道我没有这样做,这是一个应用程序运行了3年,从来没有这个问题

我有一个MySQL数据库托管在某个提供商中。在过去的三年里,一切正常,但从昨天起,所有特殊角色现在都显示为无效字符。例如:

'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_替换,但直接在Mysql中替换

只是为了添加更多信息,数据库是由PHP应用程序访问的,但问题发生在直接从MySQL工作台访问数据库时,因此这不是与PHP相关的问题

提前谢谢

在ANSI(或其他非UTF)列中存储UTF-8数据时,这是一个非常典型(且经常出现)的结果。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)
您可以做的是为该列设置正确的编码(
charset
(在(我的)SQL中)。您可以使用
altertable
命令,但这会进一步弄乱现有值(它会尝试在UTF-8中重新编码已编码的UTF-8值)。因此,更好的方法是:

  • 添加具有UTF-8字符集+排序规则的新列
  • 更新表格并将新列的值设置为旧列的值。这里很重要的是旧列的字符集为其真实值(UTF-8)。这不会转换数据,而只是将现有字节存储在新列中,但这次使用正确的编码
  • 完成后,删除旧列并将新列重命名为旧名称
有了这个附加列,您可以确保不会丢失数据(仍然建议备份),如果出现问题,您可以删除它并重新开始。

这是在ANSI(或其他非UTF)列中存储UTF-8数据时出现的一个非常典型(且经常出现)的结果。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)
您可以做的是为该列设置正确的编码(
charset
(在(我的)SQL中)。您可以使用
altertable
命令,但这会进一步弄乱现有值(它会尝试在UTF-8中重新编码已编码的UTF-8值)。因此,更好的方法是:

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

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

我的猜测是,当您连接到MySQL并依赖默认值时,您没有在PHP中设置编码。正如我所说,问题发生在直接在MySQL Workbench中访问DB,调用该函数很方便。备选方案:使用您喜爱的编辑器/工具进行mysqldump、完整文本替换并重新导入。(然后你必须把你的页面往下看一点,并确保你的工具区分大小写)。如果您有一个旧的转储,您可以检查(并与当前转储进行比较)第一行中的条目,如
集合名称
、字符集或mysql服务器版本,以查看是否有更改。另一方面,它有时可能是主机配置页面中的一个简单切换。我只是猜测无效数据最初是如何到达数据库的。我猜当你连接到MySQL时,你没有在PHP中设置编码,并且依赖默认值。就像我说的,问题发生在直接在MySQL Workbench中访问DB,调用该函数很方便。备选方案:使用您喜爱的编辑器/工具进行mysqldump、完整文本替换并重新导入。(然后你必须把你的页面往下看一点,并确保你的工具区分大小写)。如果您有一个旧的转储,您可以检查(并与当前转储进行比较)第一行中的条目,如
集合名称
、字符集或mysql服务器版本,以查看是否有更改。另一方面,它有时可能是主机配置页面中的一个简单切换。我只是猜测无效数据最初是如何到达数据库的。谢谢您的建议。我不明白的是为什么这个问题不知从哪里冒出来;一切正常。东道主公司