MySQL:将排序规则从utf8_bin更改为utf8_unicode_ce

4

如果给定了一个完整的表,我该如何将字符集从utf8_bin更改为utf8_unicode_ce?正常的“alter”查询不起作用,因为会出现“重复条目错误”。例如,有两个条目。

David Hussa

并且

David Hußa

我知道它们是一样的。有没有一种优雅的方式告诉MySQL“合并”这些条目?我应该提到,这些条目的ID在其他表中被用作引用,因此MySQL也必须尊重这一点。还是说我必须用冗长而烦人的方式来做这件事:手动合并每个重复项,然后更改排序规则?
表格如下:
delimiter $$

CREATE TABLE `authors` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) COLLATE utf8_bin NOT NULL,
  `count` int(11) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`),
  UNIQUE KEY `name_UNIQUE` (`name`),
  FULLTEXT KEY `name_FULLTEXT` (`name`)
) ENGINE=MyISAM AUTO_INCREMENT=930710 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Stores all authors from dblp.xml.'$$
1个回答

5
您可以删除重复条目:
DELETE  a2
FROM    authors a1
JOIN    authors a2
ON      a2.name COLLATE UTF8_GENERAL_CI = a1.name COLLATE UTF8_GENERAL_CI
        AND a2.id < a1.id

请注意,如果您的表很大,这可能需要很长时间。
最好做如下操作:
  • Drop the UNIQUE constraint

  • Change the collation

  • Create a plain, non-unique index on name

  • Run the query (without COLLATE clause):

    DELETE  a2
    FROM    authors a1
    JOIN    authors a2
    ON      a2.name = a1.name
            AND a2.id < a1.id
    
  • Drop the index

  • Recreate the UNIQUE constraint.

在删除条目之前,请运行以下查询以更新引用表:

UPDATE  child c
JOIN    (
        (
        SELECT  name COLLATE utf8_unicode_ci AS name_ci, MAX(id) AS mid
        FROM    authors
        GROUP BY
                name_ci
        ) pa
        JOIN    authors a
        ON      a.name COLLATE utf8_unicode_ci = name_ci
        )
ON      c.author = a.id
SET     author = mid;

对所有引用表格进行引用。


谢谢您的重新表述。但是还有一个问题:如果一个名称的ID在另一个表中被使用,而且这个名称是重复的。这个“其他”ID会自动更新吗?我的意思是,“John Doe”的ID为1,“John Doé”的ID为2,第二个ID会丢失,对吗? - Aufwind
@Aufwind:抱歉,一开始没明白你的意思。不,它不会自动更新名称。您需要运行我现在将要编写的查询。 - Quassnoi
非常感谢您的努力。它运行得非常顺畅。对于像我这样的新手,我想添加以下注释:child是一个引用表的名称,c是其缩写,在倒数第二行中使用了例如c.author。花了我一些时间才弄明白。^^ - Aufwind

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接