2011-11-08 13 views
47

Próbuję usunąć duplikaty z tabeli MySQL za pomocą ALTER IGNORE TABLE + UNIKALNY KLUCZ. Dokumentacja MySQL mówi:MySQL: ALTER IGNORE TABLE daje "naruszenie ograniczenia integralności"

IGNORE jest rozszerzeniem MySQL do standardowego SQL. Kontroluje sposób działania ALTER TABLE, jeśli istnieją duplikaty na unikalnych klawiszach w nowej tabeli lub jeśli ostrzeżenia pojawią się, gdy włączony jest tryb ścisły. Jeśli IGNORE nie zostanie określony, kopia zostanie przerwana i wycofana, jeśli wystąpią błędy klucza duplikatu. Jeśli określono IGNORE, tylko pierwszy wiersz jest używany w wierszach z duplikatami na unikalnym kluczu. Pozostałe sprzeczne wiersze są usuwane. Niepoprawne wartości są obcinane do najbliższej pasującej wartości dopuszczalnej.

Kiedy uruchomić kwerendę ...

ALTER IGNORE TABLE table ADD UNIQUE INDEX dupidx (field) 

... I jeszcze dostać błąd # 1062 - Powielanie wejścia 'blabla' dla klucza 'dupidx'.

Odpowiedz

95

Rozszerzenie słowa kluczowego do MySQL na IGNORE wydaje się mieć numer bug in the InnoDB version w przypadku niektórych wersji MySQL.

Zawsze mógłby przekształcić się MyISAM, ignorowanych dodać indeks, a następnie przekonwertować z powrotem do InnoDB

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

Uwaga, jeśli masz klucz obcy to nie zadziała, trzeba będzie usunąć te pierwsze i dodaj je później.

+56

W tym linkiem do problemu InnoDB jest sugerowane obejście pierwszym uruchomieniu 'ustawiony sesji old_alter_table = 1;' to pracował! mnie. – Peter

+1

Dzięki Peter - to wydaje się teraz działać dla mnie. Nie miałem pojęcia o tym problemie - moja maszyna deweloperska to mariadb, ale kiedy musiałem uruchomić na produkcji (mysql 5.5) wpadłem na to. Ten stackoverflow uratował mój dzień! – spidie

+5

Jest to prawdopodobnie najgorsza zaakceptowana odpowiedź, jaką kiedykolwiek widziałem w Stack Overflow. Wymiana silników do przechowywania danych jest znaczącym przedsięwzięciem samo w sobie, nawet w przypadku średnich stołów. Te trzy zapytania mogą potencjalnie zablokować serwer bazy danych na wiele godzin. To nie jest niczym rozwiązanie. – Mikkel

2

Problem polega na tym, że w polu, które próbujesz indeksować, znajdują się duplikaty danych. Musisz usunąć obraźliwe duplikaty, zanim dodasz unikatowy indeks.

Jednym ze sposobów jest wykonanie następujących czynności:

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; 

ten pozwala wstawić tylko unikalne dane do tabeli

+0

Nie, słowo kluczowe IGNORE powinno zająć się tymi duplikatami. To byłoby piękno tego rozwiązania. Zobacz cytowane dokumenty w moim pytaniu. –

25

Lub spróbuj ustawić sesji old_alter_table = 1 (Nie zapomnij, aby ją ustawić back)

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

+2

To zadziałało dla mnie. Jest długa na dużych stołach, ale wydaje się dość liniowa. Na mojej maszynie udało się przetworzyć około 2 GB danych na godzinę, co stanowiło około dwóch dni. Zastanawiam się, jak to się ma do przyjętego rozwiązania, które miało zostać przekształcone w myISAM, dodać indeks i przekonwertować z powrotem. –

+0

Uwaga! Jeśli używasz replikacji, ustawienie 'old_alter_table' nie jest replikowane, więc' ALTER TABLE IGNORE' nie powiedzie się na slave i przerwie replikację.Aby to naprawić, ręcznie wykonałem 'ALTER' na slave'ie, a następnie pominąłem szkodliwą tablicę" ALTER TABLE ", używając' SET GLOBAL sql_slave_skip_counter = 1', a następnie wznowiono replikację. – thenickdude

Powiązane problemy