删除具有唯一索引的重复项

use*_*739 19 mysql duplicates unique-index

我在两个表格A,B,C,D之间插入,相信我在A,B,C,D上创建了一个唯一索引以防止重复.但是我不知何故简单地在那些上做了一个正常的索引.所以插入了重复项.这是2000万的记录表.

如果我将现有索引从正常更改为唯一,或者只是为A,B,C添加新的唯一索引,D将删除重复项还是由于存在唯一记录而添加失败?我测试它是30密耳的记录,我不想弄乱桌子或复制它.

Pau*_*gel 56

如果您的表中有重复项并且您使用了

ALTER TABLE mytable ADD UNIQUE INDEX myindex (A, B, C, D);
Run Code Online (Sandbox Code Playgroud)

查询将失败,错误1062(重复键).

但如果你使用 IGNORE

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

重复项将被删除.但是文档没有指定将保留哪一行:

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

    从MySQL 5.7.4开始,删除了ALTER TABLE的IGNORE子句,并且它的使用会产生错误.

(ALTER TABLE语法)

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

  • 将数据复制到临时表中(从技术上讲,它不需要是临时的).
  • 截断原始表格.
  • 创建UNIQUE INDEX.
  • 然后将数据复制回来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;
Run Code Online (Sandbox Code Playgroud)

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

(INSERT语法)

另请参阅:INSERT ... SELECT IGNORE关键字和严格SQL模式的语法比较