一尘不染

使用唯一索引删除重复项

mysql

我相信在A,B,C,D的两个表字段之间插入了唯一索引,以防止重复。但是我以某种方式简单地对它们做了一个普通索引。因此插入了重复项。它是2000万个记录表。

如果我将现有索引从普通索引更改为唯一索引,或者只是为A,B,C,D添加新的唯一索引,由于存在唯一记录,重复项将被删除还是添加失败?我将对其进行测试,但它已达到3000万条记录,并且我既不希望将表弄乱或复制它。


阅读 476

收藏
2020-05-17

共1个答案

一尘不染

如果表中有重复项,则使用

ALTER TABLE mytable ADD UNIQUE INDEX myindex (A, B, C, D);

该查询将失败,并显示错误1062(重复键)。

但是如果你用 IGNORE

-- (only works before MySQL 5.7.4)
ALTER IGNORE TABLE mytable ADD UNIQUE INDEX myindex (A, B, C, D);

重复项将被删除。但是文档没有指定要保留的行:

  • IGNORE是标准SQL的MySQL扩展。它控制ALTER TABLE新表中唯一键上是否有重复项或启用严格模式时是否出现警告的工作方式。如果IGNORE未指定,则复制副本将中止并在发生重复键错误时回滚。如果IGNORE指定,则仅一行使用唯一键重复的行。其他冲突的行将被删除。不正确的值将被截断为最接近的匹配可接受值。

从MySQL 5.7.4开始,ALTER TABLE的IGNORE子句被删除,使用它会产生错误。

ALTER TABLE语法

如果您的版本是5.7.4或更高版本-您可以:

  • 将数据复制到临时表中(从技术上讲,它不需要是临时表)。
  • 截断原始表。
  • 创建唯一索引。
  • 并将数据复制回INSERT IGNORE(仍然可用)。

    CREATE TABLE tmp_data SELECT * FROM mytable;
    TRUNCATE TABLE mytable;
    ALTER TABLE mytable ADD UNIQUE INDEX myindex (A, B, C, D);
    INSERT IGNORE INTO mytable SELECT * from tmp_data;
    DROP TABLE tmp_data;

如果使用IGNORE修饰符,则执行INSERT语句时发生的错误将
被忽略。例如,如果不IGNORE使用,则复制表中现有UNIQUE索引或PRIMARY KEY值的行将导致重复键错误,并且该语句将中止。使用
IGNORE,该行将被丢弃,并且不会发生错误。被忽略的错误会生成警告。

(插入语法)

另请参见:INSERT … SELECT语法以及IGNORE关键字和严格SQL模式的比较

2020-05-17