如果我在MySQL中更改列的排序规则,现有数据会发生什么?

时间:2011-04-07 03:08:44

标签: mysql phpmyadmin collation

我正在使用MySQL数据库服务器运行生产应用程序。我忘记将列的排序规则从latin设置为utf8_unicode,这会在保存到具有多语言数据的列时导致奇怪的数据。

我的问题是,如果我现在将校对更改为utf8_unicode,我的现有数据会发生什么?它会破坏或破坏现有数据还是数据仍然存在,但新数据将保存为utf8应该是什么?

我将使用phpMyAdmin网络客户端进行更改。

5 个答案:

答案 0 :(得分:6)

文章http://mysqldump.azundris.com/archives/60-Handling-character-sets.html详细讨论了这一点,并展示了将会发生的事情。

请注意,您正在将CHARACTER SET(实际上是编码)与COLLATION混合。

字符集定义磁盘上字符串的物理表示形式。您可以使用HEX()函数(例如SELECT HEX(str) FROM t WHERE id = 1)使其可见,以查看MySQL如何存储字符串的字节。 MySQL提供给您的内容可能会有所不同,具体取决于您使用SET NAMES ....定义的连接的字符集。

排序规则是排序顺序。它取决于字符集。例如,您的数据可能是latin1字符集,但可以根据两个德语排序顺序latin1_german1_ci或latin1_german2_ci中的任何一个进行排序。根据您的选择,诸如ö的元音符号将分为oe或o。

更改字符集时,需要重写表中的数据。 MySQL将读取表中的所有数据和所有索引,制作临时占用磁盘空间的表的隐藏副本,然后将旧表移动到隐藏位置,将隐藏表移动到位,然后删除旧数据,释放磁盘空间。在中间的一段时间内,你需要两倍的存储空间。

更改排序规则时,数据的排序顺序会更改,但不会更改数据本身。如果您要更改的列不是索引的一部分,除了重写frm文件之外不需要做任何事情,并且MySQL的最新版本不应该做更多。

当您更改作为索引一部分的列的排序规则时,需要重写索引,因为索引是表的排序摘录。这将再次触发上面概述的ALTER TABLE表复制逻辑。

MySQL会尝试保留这样做的数据:只要您拥有的数据可以在目标字符集中表示,转换就不会有损。如果发生数据截断,将打印警告,并且目标字符集中无法表示的数据将替换为?

答案 1 :(得分:4)

在MySQL 5.1中运行快速测试,VARCHAR列设置为latin1_bin我插入了一些非拉丁字符

INSERT INTO Test VALUES ('英國華僑');

我选择它们并得到垃圾(如预期的那样)。

SELECT text from Test;

给出

text
????

然后我将列的排序规则更改为utf8_unicode并重新运行SELECT并显示相同的结果

text
????

这就是我所期望的 - 它将保持数据和数据仍然是垃圾,因为当插入数据时,列丢失了额外的字符信息,只是插入了一个?对于每个非拉丁字符并没有办法????再次成为英国华侨。

您的数据将保留在原位,但不会修复。

答案 2 :(得分:1)

有效的数据将被正确转换:

  

使用时更改数据类型   更改或修改,MySQL尝试   将现有列值转换为   新型也是可能的。警告:   这种转换可能会导致   改变数据。

http://dev.mysql.com/doc/refman/5.5/en/alter-table.html

......更具体地说:

  

转换二进制或非二进制   字符串列使用特定的   字符集,使用ALTER TABLE。对于   成功转换发生之一   必须满足以下条件   apply:[...]如果列有一个   非二进制数据类型(CHAR,VARCHAR,   TEXT),其内容应编码   在列字符集中,不是一些   其他字符集。如果是内容   以不同的字符编码   设置,您可以转换要使用的列   首先是二进制数据类型,然后是   具有所需的非二进制列   字符集。

http://dev.mysql.com/doc/refman/5.1/en/charset-conversion.html

因此,您的问题是无效的数据,例如,以不同字符集编码的数据。我已经尝试过文档建议的提示,它基本上破坏了我的数据,但原因是我的数据已经丢失:运行SELECT column, HEX(column) FROM table显示多字节字符已插入为0x3F(即, Latin1中的?符号。我的MySQL堆栈非常智能,可以检测到输入数据不是Latin1并将其转换为“兼容”的东西。一旦数据消失,你无法取回它。

总结一下:

  1. 使用HEX()查看您是否仍有数据。
  2. 在表格的副本中进行测试。

答案 3 :(得分:0)

  

我的问题是,如果我改变了我的现有数据将会发生什么   现在整理到utf8_unicode?

答案:如果您更改为utf8_unicode_ci,您的现有数据(已经损坏并且在您修改之前仍然会损坏)将发生任何事情。

  

它会破坏或破坏现有数据还是数据仍然存在,   但新数据将保存为utf8应该是什么?

答案:更改为utf8_unicode_ci后,现有数据不会被销毁。它将像以前一样保持不变(像????)。但是,如果插入包含Unicode字符的新数据,则会正确存储。

  

我将使用phpMyAdmin网络客户端进行更改。

答案:当然,您可以通过转到操作>更改与phpMyAdmin的排序规则。表格选项

答案 4 :(得分:0)

小心! 一些问题通过

解决
ALTER TABLE ... CONVERT TO ...

部分通过两步流程解决

ALTER TABLE ... MODIFY ... VARBINARY...
ALTER TABLE ... MODIFY ... VARCHAR...

如果你做错了,你会有一个更糟的混乱

  1. SELECT HEX(col), col ...查看您的真实情况。
  2. 研究一下,看看你有什么案例:Trouble with utf8 characters; what I see is not what I stored
  3. 根据以下情况执行正确的修复:http://mysql.rjweb.org/doc.php/charcoll#fixes_for_various_cases