Mam bazę danych Postgresql, na której chcę wykonać kilka kaskadowych operacji usuwania. Jednak tabele nie są konfigurowane z regułą ON DELETE CASCADE. Czy jest jakiś sposób, aby wykonać operację usunięcia i powiedzieć Postgresqlowi, aby wykonała kaskadę tylko raz? Coś równoważnego z
DELETE FROM some_table CASCADE;
Odpowiedzi na to starsze pytanie sprawiają, że wydaje się, że nie ma takiego rozwiązania, ale pomyślałem, że zadam to pytanie wprost, aby się upewnić.
postgresql
Eli Courtwright
źródło
źródło
Odpowiedzi:
Nie. Aby to zrobić, wystarczy napisać instrukcję delete dla tabeli, którą chcesz kaskadować.
źródło
Jeśli naprawdę chcesz,
DELETE FROM some_table CASCADE;
co oznacza „ usuń wszystkie wiersze z tabelisome_table
”, możesz użyćTRUNCATE
zamiastDELETE
iCASCADE
zawsze jest obsługiwane. Jednak jeśli chcesz użyć selektywnego usuwania zwhere
klauzulą,TRUNCATE
nie jest wystarczająco dobre.UŻYWAJ Z PIELĘGNACJĄ - Spowoduje to upuszczenie wszystkich wierszy wszystkich tabel, które mają ograniczenia na klucz obcy
some_table
i wszystkich tabel, które mają ograniczenia na tych tabelach itp.Obsługa Postgres
CASCADE
z poleceniem TRUNCATE :Jest to zręcznie transakcyjne (tzn. Może zostać wycofane), chociaż nie jest w pełni odizolowane od innych równoczesnych transakcji i ma kilka innych zastrzeżeń. Przeczytaj dokumentację, aby uzyskać szczegółowe informacje.
źródło
Napisałem funkcję (rekurencyjną), aby usunąć dowolny wiersz na podstawie jego klucza podstawowego. Napisałem to, ponieważ nie chciałem tworzyć moich ograniczeń jako „przy kasowaniu kasowania”. Chciałem być w stanie usunąć złożone zestawy danych (jako DBA), ale nie pozwolić moim programistom na kaskadowe usuwanie bez przemyślenia wszystkich konsekwencji. Wciąż testuję tę funkcję, więc mogą być w niej błędy - ale proszę nie próbuj jej, jeśli twoja baza danych ma wiele kolumn podstawowych (a więc obcych) kluczy. Ponadto wszystkie klucze muszą być reprezentowane w postaci ciągu, ale można je zapisać w sposób, który nie ma tego ograniczenia. Używam tej funkcji BARDZO Oszczędnie, zbyt cenię swoje dane, aby umożliwić kaskadowe ograniczenia na wszystko. Zasadniczo ta funkcja jest przekazywana w schemacie, nazwie tabeli i wartości podstawowej (w postaci ciągu), i zacznie od znalezienia jakichkolwiek obcych kluczy w tej tabeli i upewni się, że dane nie istnieją - jeśli tak, rekurencyjnie wywołuje się na znalezionych danych. Wykorzystuje tablicę danych już zaznaczonych do usunięcia, aby zapobiec nieskończonym pętlom. Sprawdź to i daj mi znać, jak to działa. Uwaga: jest trochę powolny. Nazywam to tak:
select delete_cascade('public','my_table','1');
źródło
IN
operatora z podselekcjami zamiast=
(więc krok do użycia logiki zbiorów) stałoby się znacznie szybsze.Jeśli dobrze rozumiem, powinieneś być w stanie zrobić, co chcesz, usuwając ograniczenie klucza obcego, dodając nowe (które będzie kaskadowo), robiąc swoje rzeczy i odtwarzając ograniczenia klucza obcego.
Na przykład:
Oczywiście, ze względu na swoje zdrowie psychiczne, powinieneś streścić takie rzeczy w procedurze.
źródło
Nie mogę skomentować odpowiedzi Palehorse, więc dodałem własną odpowiedź. Logika Palehorse jest dobra, ale wydajność może być zła w przypadku dużych zbiorów danych.
Jest to szybsze, jeśli masz indeksy na kolumnach, a zestaw danych jest większy niż kilka rekordów.
źródło
Tak, jak powiedzieli inni, nie ma wygodnego „USUŃ Z mojej_tabeli ... KASKADA” (lub odpowiednika). Aby usunąć niekaskadowe rekordy potomne chronione kluczem obcym i ich przodków, do których się odwołujesz, masz następujące opcje:
Zakładam, że obchodzenie ograniczeń klucza obcego nie jest wygodne. ale rozumiem, dlaczego w określonych okolicznościach chcesz to zrobić. Jeśli robisz to z pewną częstotliwością, a jeśli chcesz zignorować mądrość DBA wszędzie, możesz zautomatyzować to za pomocą procedury.
Przybyłem tu kilka miesięcy temu, szukając odpowiedzi na pytanie „KASKADA USUŃ tylko raz” (pierwotnie zadane ponad dekadę temu!). Przebiegłem trochę przez sprytne rozwiązanie Joe Love (i wariant Thomasa CG de Vilhena), ale ostatecznie mój przypadek użycia miał szczególne wymagania (na przykład obsługę okólnych odniesień wewnątrz tabeli), które zmusiły mnie do innego podejścia. To podejście ostatecznie stało się rekurencyjnie_delete (PG 10.10).
Od jakiegoś czasu używam rekursywnie_kasowania w produkcji i nareszcie czuję się (ostrożnie) na tyle pewny siebie, aby udostępnić go innym, którzy mogą tu znaleźć pomysły. Podobnie jak w przypadku rozwiązania Joe Love, pozwala on usuwać całe wykresy danych, tak jakby wszystkie ograniczenia kluczy obcych w bazie danych były chwilowo ustawione na CASCADE, ale oferuje kilka dodatkowych funkcji:
źródło
Możesz użyć do zautomatyzowania tego, możesz zdefiniować ograniczenie klucza obcego za pomocą
ON DELETE CASCADE
.Cytuję instrukcję ograniczeń klucza obcego :
źródło
Wziąłem odpowiedź Joe Love i przepisałem ją za pomocą
IN
operatora z=
podselekcjami zamiast przyspieszyć funkcję (zgodnie z sugestią Hubbitusa):źródło
in
operatora i zapytań podrzędnych.Usuń z opcją kaskady zastosowaną tylko do tabel ze zdefiniowanymi kluczami obcymi. Jeśli wykonasz operację usuwania, która mówi, że nie możesz, ponieważ naruszyłaby to ograniczenie klucza obcego, kaskada spowoduje usunięcie niepoprawnych wierszy.
Jeśli chcesz usunąć powiązane wiersze w ten sposób, musisz najpierw zdefiniować klucze obce. Pamiętaj też, że jeśli nie wydasz wyraźnego polecenia rozpoczęcia transakcji lub nie zmienisz ustawień domyślnych, nastąpi automatyczne zatwierdzenie, którego oczyszczenie może zająć dużo czasu.
źródło