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

时间:2016-04-15 12:22:07

标签: mysql duplicates unique-index

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

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

4 个答案:

答案 0 :(得分:47)

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

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 Syntax

如果您的版本是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;
  

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

(INSERT Syntax)

另请参阅:INSERT ... SELECT SyntaxComparison of the IGNORE Keyword and Strict SQL Mode

答案 1 :(得分:4)

如果您认为会有重复项,添加唯一索引将失败。 首先检查有哪些重复:

select * from
(select a,b,c,d,count(*) as n from table_name group by a,b,c,d) x
where x.n > 1

对于20M行,这可能是一个昂贵的查询,但会为您提供所有重复的密钥,这将阻止您添加主索引。 如果在子查询中执行某个位置,则可以将其拆分为更小的块:where a='some_value'

对于检索到的记录,您必须更改某些内容以使行唯一。如果这样做(查询返回0行),您应该可以安全地添加主索引。

答案 2 :(得分:1)

您可以使用ON DUPLICATE KEY UPDATE而不是IGNORE,这样可以控制哪些值占优势。

答案 3 :(得分:0)

要回答您的问题 - 在具有重复值的列上添加UNIQUE约束会引发错误。

例如,您可以尝试以下脚本:

CREATE TABLE `USER` (
  `USER_ID` INT NOT NULL,
  `USERNAME` VARCHAR(45) NOT NULL,
  `NAME` VARCHAR(45) NULL,
  PRIMARY KEY (`USER_ID`));

INSERT INTO USER VALUES(1,'apple', 'woz'),(2,'apple', 'jobs'),
(3,'google', 'sergey'),(4,'google', 'larry');

ALTER TABLE `USER` 
ADD UNIQUE INDEX `USERNAME_UNIQUE` (`USERNAME` ASC);
/*
Operation failed: There was an error while applying the SQL script to the database.
ERROR 1062: Duplicate entry 'apple' for key 'USERNAME_UNIQUE'
*/