2016-04-15 82 views
4

我在兩個表字段A,B,C,D之間插入,相信我在A,B,C,D上創建了唯一索引以防止重複項。然而,我不知何故只是對這些做了一個正常的索引。所以重複插入。它是2000萬條記錄表。刪除具有唯一索引的重複項

如果我將現有的索引從正常狀態更改爲唯一狀態,或者只是爲A,B,C,D添加新的唯一索引,那麼是否會刪除重複項或將添加失敗,因爲存在唯一記錄?我會測試它,但它是30萬條記錄,我不想把桌子搞亂或複製它。

+1

您需要使用'IGNORE'關鍵字 - 否則會失敗。在一個小測試桌上測試它。 –

+0

「IGNORE是標準SQL的MySQL擴展,它控制着ALTER TABLE如何在新表中的唯一鍵上存在重複或如果啓用嚴格模式時發生警告......」 - [ALTER TABLE語法](http: //dev.mysql.com/doc/refman/5.7/en/alter-table.html) –

+0

@PaulSpiegel這很有道理。我嘗試複製Table1,僅結構,並添加一個唯一的索引,然後在原始索引表和新索引表之間插入,但確實失敗。我這樣做是因爲在30萬條記錄上更改或添加獨特索引需要很長時間。因此,現在我在「插入」後添加了「忽略」,它效果很好。 – user3649739

回答

21

如果你在你的表格重複和使用

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

查詢將失敗,錯誤1062(重複鍵)。

但是如果你使用IGNORE

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

的副本將被刪除。但文件沒有指定哪些行將被保留:

  • IGNORE是一個MySQL擴展到標準SQL。它控制ALTER TABLE如果新表中的唯一鍵上有重複項,或者如果啓用嚴格模式時發生警告,將如何工作ALTER TABLE。如果IGNORE不是 指定,則複製被中止並回滾,如果重複鍵錯誤 發生。如果指定了IGNORE,則只有一行用於具有唯一密鑰上 重複項的行。其他衝突的行被刪除。 不正確的值被截斷爲最接近匹配的可接受的 值。

    從MySQL 5.7.4開始,ALTER TABLE的IGNORE子句被刪除, 的使用產生錯誤。

ALTER TABLE Syntax

如果你的版本是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 Syntax)

另見:INSERT ... SELECT SyntaxComparison of the IGNORE Keyword and Strict SQL Mode

+0

這是一個啓示。在我修改一個獨特的索引以使用以前的不同列之前,我正在拉我的頭髮,試圖擺脫雙眸。幫我卸載 - 謝謝。 – Utkanos

+0

看來他們「固定」了這個功能,所以無論你是否使用IGNORE,它仍然會拋出一個'無法寫入;表中的重複鍵' – RVP

+0

@RVP對於5.7.4及更高版本,您仍然可以使用'INSERT IGNORE ... SELECT ...'複製數據。查看更新。 –

2

如果您認爲會有重複項,則添加唯一索引將會失敗。 先檢查什麼複製有:

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行),您應該可以安全地添加主索引。

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' 
*/ 
1

而是不理你可以使用對重複密鑰更新,這將讓你控制哪些值爲準。

相關問題