2009-03-05 7 views
17

Mam autoreferencyjna tabeli MySQL z rekurencyjnej parent_id:Jaki jest najlepszy sposób na opróżnienie samoodnawialnego stołu MySQL?

CREATE TABLE `recursive` (
    `id` int(11) NOT NULL auto_increment, 
    `parent_id` int(11) default NULL, 
    `name` varchar(100) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `data_categorysource_parent_id` (`parent_id`), 
    CONSTRAINT `parent_id_refs_id_627b4293` 
    FOREIGN KEY (`parent_id`) REFERENCES `data_categorysource` (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

Podczas testów, chcę go opróżnić ale TRUNCATE nie:

TRUNCATE `recursive` 
/* SQL Error: Cannot delete or update a parent row: a foreign key 
constraint fails... 

I obecnie trzeba ręcznie usunąć wszystkie rekordy, zaczynając od dołu drzewa, pracując w górę. To staje się uciążliwe nawet przy małych drzewach.

Czy istnieje prosty sposób obejścia tego? Nie mogę utworzyć tabeli i odtworzyć go ponownie tak jak inne tabele odwołują się do niego (już je skasowałem, aby nie było problemów z integralnością danych).

+0

Jeśli „DELETE FROM' recursive' ORDER BY ' id' "dostaniesz to działa. Jeśli jednak masz wiersze z samoczynnym odwoływaniem, prawie nie masz eleganckich wyborów: http://bugs.mysql.com/bug.php?id=7412. Ten, który tymczasowo wyłącza klucze foreign_keys, jest najlepszy. –

+1

Jeden z nielicznych przypadków, w których wyrocznia radzi sobie lepiej, tak jak w przypadku wyroczni, której możesz się dopuścić do sprawdzania ograniczeń, dopóki transakcja nie zostanie zatwierdzona. –

Odpowiedz

22

Dlaczego nie:

UPDATE 'recursive' SET 'parent_id' = NULL WHERE 'parent_id' IS NOT NULL; 
DELETE FROM 'recursive'; 

?

+0

Pytanie "Jaki jest najlepszy sposób na opróżnienie samoodnawialnego stołu MySQL?" lub jego forma pojawia się na wielu stronach internetowych, a nawet jest powielana wiele razy w SO, a jednak tak niewiele pytań ma tę prostą, elegancką i poprawną odpowiedź. +1 – Barzee

1

Cóż, można dodać definicję ON DELETE CASCADE do definicji FOREIGN KEY ... co najmniej tymczasowo. Umożliwiłoby to obcięcie tabeli przez usunięcie w pierwszej kolejności odwołanych wierszy.

Istnieją również inne typy ON DELETE; wartość domyślna to ON DELETE NO ACTION.

-1

Powtarzaj wybieranie wierszy, które nie są rodzicami i usuwaj je, dopóki tabela nie będzie pusta. (Zakładając, że nie ma cykli ...)

0

Lub po prostu usuń ograniczenie (rekurencyjne) klucza obcego, a następnie skróć tabelę, a następnie ponownie dodaj ograniczenie.

16

Jeśli chcesz po prostu opróżnić całą rzecz do celów testowych użyć:

SET FOREIGN_KEY_CHECKS = 0; 

// Execute Query 

SET FOREIGN_KEY_CHECKS = 1; 

Ten całkowicie omija żadnych kluczy obcych czeków.

-2

usunąć z table_1 gdzie data (table_1_TIME) < (wybierz T.t_Date z (select max (datę (table_1_TIME)) jako t_Date od table_1) jako T)

+0

Proszę sformatować kod jaśniej i odwołać się do identyfikatorów oryginalnego pytania. – gwaigh

Powiązane problemy