Ich habe eine Postgresql-Datenbank, in der ich einige kaskadierende Löschvorgänge ausführen möchte. Die Tabellen werden jedoch nicht mit der Regel ON DELETE CASCADE eingerichtet. Gibt es eine Möglichkeit, einen Löschvorgang durchzuführen und Postgresql anzuweisen, ihn nur einmal zu kaskadieren? Etwas Äquivalentes zu
DELETE FROM some_table CASCADE;
Die Antworten auf diese ältere Frage lassen den Eindruck entstehen, dass es keine solche Lösung gibt, aber ich dachte, ich würde diese Frage explizit stellen, nur um sicherzugehen.
postgresql
Eli Courtwright
quelle
quelle
Antworten:
Nein. Um dies nur einmal zu tun, schreiben Sie einfach die delete-Anweisung für die Tabelle, die Sie kaskadieren möchten.
quelle
Wenn Sie wirklich wollen,
DELETE FROM some_table CASCADE;
was bedeutet " Alle Zeilen aus der Tabelle entfernensome_table
", können SieTRUNCATE
anstelle vonDELETE
undCASCADE
wird immer unterstützt. Wenn Sie jedoch selektives Löschen mit einerwhere
Klausel verwenden möchten ,TRUNCATE
ist dies nicht gut genug.VERWENDUNG MIT PFLEGE - Hiermit werden alle Zeilen aller Tabellen gelöscht , für die eine Fremdschlüsseleinschränkung gilt,
some_table
sowie alle Tabellen, für die diese Tabellen usw. eingeschränkt sind.Postgres unterstützt
CASCADE
mit dem Befehl TRUNCATE :Handlich ist dies eine Transaktion (dh kann zurückgesetzt werden), obwohl sie nicht vollständig von anderen gleichzeitigen Transaktionen isoliert ist und mehrere andere Einschränkungen aufweist. Lesen Sie die Dokumente für Details.
quelle
Ich habe eine (rekursive) Funktion geschrieben, um jede Zeile basierend auf ihrem Primärschlüssel zu löschen. Ich habe dies geschrieben, weil ich meine Einschränkungen nicht als "On Delete Cascade" erstellen wollte. Ich wollte in der Lage sein, komplexe Datensätze (als DBA) zu löschen, aber meinen Programmierern nicht erlauben, das Löschen zu kaskadieren, ohne über alle Auswirkungen nachzudenken. Ich teste diese Funktion immer noch, daher kann es zu Fehlern kommen - aber versuchen Sie es bitte nicht, wenn Ihre Datenbank mehrspaltige Primärschlüssel (und damit Fremdschlüssel) enthält. Außerdem müssen alle Schlüssel in Zeichenfolgenform dargestellt werden können, sie können jedoch auch so geschrieben werden, dass diese Einschränkung nicht besteht. Ich benutze diese Funktion sowieso SEHR SPAREN, ich schätze meine Daten zu sehr, um die kaskadierenden Einschränkungen für alles zu aktivieren. Grundsätzlich wird diese Funktion im Schema, im Tabellennamen und im Primärwert (in Zeichenfolgenform) übergeben. Zunächst werden Fremdschlüssel in dieser Tabelle gefunden, und es wird sichergestellt, dass keine Daten vorhanden sind. Wenn dies der Fall ist, werden die gefundenen Daten rekursiv aufgerufen. Es verwendet ein Array von Daten, die bereits zum Löschen markiert sind, um Endlosschleifen zu verhindern. Bitte testen Sie es und lassen Sie mich wissen, wie es bei Ihnen funktioniert. Hinweis: Es ist etwas langsam. Ich nenne es so:
select delete_cascade('public','my_table','1');
quelle
IN
Operator mit Unterauswahl anstelle von=
(also Schritt zur Verwendung der Mengenlogik) verwenden. Es würde viel schneller werden.Wenn ich das richtig verstehe, sollten Sie in der Lage sein, das zu tun, was Sie wollen, indem Sie die Fremdschlüsseleinschränkung löschen, eine neue hinzufügen (die kaskadiert), Ihre Aufgaben erledigen und die einschränkende Fremdschlüsseleinschränkung neu erstellen.
Beispielsweise:
Natürlich sollten Sie solche Dinge aus Gründen Ihrer geistigen Gesundheit in ein Verfahren abstrahieren.
quelle
Ich kann die Antwort von Palehorse nicht kommentieren, also habe ich meine eigene Antwort hinzugefügt. Die Logik von Palehorse ist in Ordnung, aber die Effizienz kann bei großen Datenmengen schlecht sein.
Es ist schneller, wenn Sie Indizes für Spalten haben und der Datensatz größer als wenige Datensätze ist.
quelle
Ja, wie andere gesagt haben, gibt es kein praktisches 'DELETE FROM my_table ... CASCADE' (oder ein gleichwertiges). Um nicht kaskadierende fremdschlüsselgeschützte untergeordnete Datensätze und ihre referenzierten Vorfahren zu löschen, haben Sie folgende Möglichkeiten:
Ich gehe davon aus, dass das Umgehen von Fremdschlüsseleinschränkungen nicht bequem ist. aber ich verstehe, warum Sie es unter bestimmten Umständen tun möchten. Wenn es etwas ist, das Sie mit einer gewissen Häufigkeit tun, und wenn Sie bereit sind, die Weisheit von Datenbankadministratoren überall zu missachten, möchten Sie es möglicherweise mit einem Verfahren automatisieren.
Ich bin vor ein paar Monaten hierher gekommen, um eine Antwort auf die Frage "CASCADE DELETE nur einmal" zu suchen (ursprünglich vor über einem Jahrzehnt gestellt!). Ich habe einige Meilen aus der cleveren Lösung von Joe Love (und der Variante von Thomas CG de Vilhena) herausgeholt, aber am Ende hatte mein Anwendungsfall besondere Anforderungen (zum Beispiel die Behandlung von zirkularinternen Zirkelverweisen), die mich zu einem anderen Ansatz zwangen. Dieser Ansatz wurde letztendlich rekursiv gelöscht (PG 10.10).
Ich benutze recursively_delete jetzt schon eine Weile in der Produktion und fühle mich schließlich (vorsichtig) sicher genug, um es anderen zur Verfügung zu stellen, die hier auf der Suche nach Ideen landen könnten. Wie bei der Lösung von Joe Love können Sie ganze Datendiagramme löschen, als ob alle Fremdschlüsseleinschränkungen in Ihrer Datenbank vorübergehend auf CASCADE gesetzt wären, bietet jedoch einige zusätzliche Funktionen:
quelle
Um dies zu automatisieren, können Sie die Fremdschlüsseleinschränkung mit definieren
ON DELETE CASCADE
.Ich zitiere das Handbuch der Fremdschlüsseleinschränkungen :
quelle
Ich nahm die Antwort von Joe Love und schrieb sie mit dem
IN
Operator mit Unterauswahl neu, anstatt=
die Funktion schneller zu machen (gemäß Hubbitus 'Vorschlag):quelle
in
Operators und von Unterabfragen eine Beschleunigung in der Größenordnung von 10x festgestellt .Das Löschen mit der Kaskadenoption gilt nur für Tabellen mit definierten Fremdschlüsseln. Wenn Sie einen Löschvorgang ausführen und dies nicht möglich ist, da dies die Fremdschlüsseleinschränkung verletzen würde, führt die Kaskade dazu, dass die fehlerhaften Zeilen gelöscht werden.
Wenn Sie zugeordnete Zeilen auf diese Weise löschen möchten, müssen Sie zuerst die Fremdschlüssel definieren. Denken Sie auch daran, dass, wenn Sie es nicht ausdrücklich anweisen, eine Transaktion zu starten, oder wenn Sie die Standardeinstellungen ändern, eine automatische Festschreibung durchgeführt wird, deren Bereinigung sehr zeitaufwändig sein kann.
quelle