这是将 MySQL 表从 latin1 转换为 utf-8 的安全方法吗?

Posted

技术标签:

【中文标题】这是将 MySQL 表从 latin1 转换为 utf-8 的安全方法吗?【英文标题】:Is this a safe way to convert MySQL tables from latin1 to utf-8? 【发布时间】:2011-09-05 05:23:32 【问题描述】:

我需要将我的一个数据库中的所有表从 latin1 更改为 utf-8(使用 utf8_bin 排序规则)。

我已经转储了数据库,从中创建了一个测试数据库,然后运行以下命令,每个表都没有任何错误或警告:

ALTER TABLE tablename CONVERT TO CHARSET utf8 COLLATION utf8_bin

在真实数据库上重复此操作对我来说安全吗?通过检查数据似乎很好......

【问题讨论】:

不知何故,我认为转换还有很多...过去,我们总是不得不转储和重新整理数据。 是的,这就是我害怕的!我见过大约 100 个 php 脚本用于转储表、正则表达式 latin1,然后重新插入它。如果可能的话,我很想避免这种情况,而且我几乎可以肯定所有数据当前都是正常的字符(想想 ASCII 字符集),但并不真正了解 mysql 如何存储和转换它。 你为什么不把一些极端情况的例子放到一个示例数据库中并尝试转换...... 我认为如果将所有内容都变成 blob,进行转换然后将其转回原处,您就可以做到这一点 - 请参阅 dev.mysql.com/doc/refman/4.1/en/charset-conversion.html 【参考方案1】:

有 3 种不同的情况需要考虑:

这些值确实是使用 Latin1 编码的

这是一致的情况:声明的字符集和内容编码匹配。这是我在最初的回答中提到的唯一案例。

使用您建议的命令:

ALTER TABLE tablename CONVERT TO CHARSET utf8 COLLATE utf8_bin

请注意,CONVERT TO CHARACTER SET 命令仅出现在 MySQL 4.1.2 中,因此任何使用 2005 年之前安装的数据库的人都必须使用导出/导入技巧。这就是为什么 Internet 上有如此多的遗留脚本和文档以旧方式进行操作的原因。

这些值已经使用 utf8 编码

在这种情况下,你不希望mysql转换任何数据,你只需要更改列的元数据。

为此,您必须先将类型更改为 BLOB,然后将每列更改为 TEXT utf8,这样就没有值转换:

ALTER TABLE t1 CHANGE c1 c1 BLOB;
ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8

这是推荐的方式,在Alter Table Syntax Documentation 中有明确的说明。

在不同编码中使用的值

在某些 Linux 发行版上,默认编码是 Latin1 好几年了。在这种情况下,您必须结合使用两种技术:

使用 BLOB 类型技巧修复表元数据 使用CONVERT TO 转换值。

【讨论】:

瘙痒到-1。直接的转换会破坏任何现有的口音。 @Denis:你说得对,我认为表格内容是一致的(就像带有 latin1 内容的 Latin1 字符集),尽管 nfm 没有指定它。 @nfm:内容有效使用的字符集是什么? 我对这些东西不知所措,但用户数据来自一个带有<meta charset="utf8"> 的英文网站。我几乎可以肯定所有数据当前都使用英文字母和常见的 ASCII 符号(@、$ 等)。这能回答你的问题吗? 是的,在这种情况下,您不希望转换数据。我相应地更新了我的答案。 COLLATION 应该是 COLLATE(参见dev.mysql.com/doc/refman/5.1/en/alter-table.html)。【参考方案2】:

直接的转换可能会破坏任何非 utf7 字符的字符串。

如果你没有这些(即你所有的文字都是英文),你通常会没事的。

但是,如果您有任何这些,则需要在初始运行中将所有 char/varchar/text 字段转换为 blob,并在后续运行中将它们转换为 utf8。

详细步骤见这篇文章:

http://codex.wordpress.org/Converting_Database_Character_Sets

【讨论】:

请注意,链接的文章有点过时:它没有使用已经存在 6 年的单个 CONVERT TO,这让事情变得更容易。话虽如此,它是一个很好的参考,并且适用于较旧和较新的数据库。【参考方案3】:

我过去在生产数据库上做过几次(从旧的标准编码瑞典语转换为拉丁语),当 MySQL 遇到无法转换为目标编码的字符时,它会中止转换并保留在不变的状态。因此,我认为 ALTER TABLE 语句有效。

【讨论】:

以上是关于这是将 MySQL 表从 latin1 转换为 utf-8 的安全方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 将 latin1 数据转换为 UTF8

在 Redshift 中使用等效的 Latin1 进行转换

mysql中latin1编码中文转utf8

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

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

不同子系统采用不同MySQL编码LATIN1和UTF8的兼容