2011-11-08 77 views
47

我试图使用ALTER IGNORE TABLE +一个唯一键从MySQL表中删除重复项。 MySQL文档说:MySQL:ALTER IGNORE TABLE给出“完整性约束违规”

IGNORE是对标准SQL的MySQL扩展。它控制着ALTER TABLE如何在新表中的唯一键上存在重复或如果启用严格模式时发生警告。如果未指定IGNORE,则复制将被中止并在发生重复键错误时回退。如果指定IGNORE,则只有第一行用于具有唯一键上的重复项的行。其他冲突的行被删除。不正确的值将被截断为最接近的匹配可接受值。

当我运行查询...

ALTER IGNORE TABLE table ADD UNIQUE INDEX dupidx (field) 

...我仍然得到错误#1062 - 重复项 '布拉布拉' 关键 'dupidx'

回答

95

对于MySQL的IGNORE关键字扩展似乎在某些版本的MySQL上有bug in the InnoDB version

你总是可以,转换为MyISAM数据,忽略 - 添加索引,然后再转换回InnoDB的

ALTER TABLE table ENGINE MyISAM; 
ALTER IGNORE TABLE table ADD UNIQUE INDEX dupidx (field); 
ALTER TABLE table ENGINE InnoDB; 

注意,如果你有外键约束这是不行的,你必须先删除这些,并在稍后添加它们。

+56

在链接到InnoDB的错误有一个建议的解决方法,以第一次运行'设置会话old_alter_table = 1;'这工作了!我。 – Peter

+1

感谢彼得 - 这似乎现在正在为我工​​作。不知道这个问题 - 我的开发机器是mariadb,但是当我不得不在生产上运行时(mysql 5.5)遇到了这个问题。这stackoverflow救了我的一天! – spidie

+5

这很可能是我见过的Stack Overflow上最糟糕的答案。更改存储引擎本身就是一个重要的任务,即使是中等大小的表格也是如此。这三个查询可能会将数据库服务器锁定数小时。这不是一个解决方案。 – Mikkel

2

问题是您试图索引的字段中有重复的数据。在添加唯一索引之前,您需要删除违规副本。

一种方法是做到以下几点:

CREATE TABLE tmp_table LIKE table; 
    ALTER IGNORE TABLE tmp_table ADD UNIQUE INDEX dupidx (field); 
    INSERT IGNORE INTO tmp_table SELECT * FROM table; 
    DROP TABLE table; 
    RENAME TABLE tmp_table TO table; 

这可以让你只独特的数据插入到表

+0

不,IGNORE关键字应该照顾那些重复。这将是这个解决方案的美妙之处。请参阅我的问题中引用的文档。 –

25

或者尝试设置会话old_alter_table = 1(不要忘记设置回)

参见:http://mysqlolyk.wordpress.com/2012/02/18/alter-ignore-table-add-index-always-give-errors/

+2

这确实对我有用。它在大桌子上很长,但看起来相当线性。在我的机器上,它每小时能够处理大约2GiB的数据,这大概是两天。我想知道如何比较接受的解决方案,即将其转换为myISAM,添加索引并将其转换回来。 –

+0

小心!如果使用复制,'old_alter_table'设置不会复制,所以'ALTER TABLE IGNORE'将在从属设备上失败并中断复制。为了解决这个问题,我在slave上手动执行了'ALTER',然后使用'SET GLOBAL sql_slave_skip_counter = 1'跳过了违规的'ALTER TABLE',然后恢复了复制。 – thenickdude

相关问题