DELETE-Zeilen, auf die in anderen Tabellen nicht verwiesen wird

14

Ich habe zwei Tabellen in einer PostgreSQL 9.3-Datenbank: Tabelle link_replyhat einen Fremdschlüssel mit dem Namen which_group, der auf Tabelle zeigt link_group.

Ich möchte alle Zeilen löschen, in link_groupdenen keine verwandte Zeile link_replyvorhanden ist. Klingt einfach genug, aber ich habe damit zu kämpfen.

Wird es so etwas Einfaches sein (funktioniert nicht)?

DELETE FROM link_group WHERE link_reply = NULL;
Hassan Baig
quelle
Haben Sie eine DDL, die jeder ansehen kann?
Dizzystar
Schauen Sie sich den MINUS-Operator an. Sie müssen ein Feld in links_reply angeben.
Vérace
DELETE FROM links_group USING links_group AS lg LEFT JOIN links_reply AS lr ON lg.col= lr.some_other_col WHERE links_reply.some_other_col IS NULL
Mihai
Ich hatte eine ähnliche Frage, die auch die Parallelität berücksichtigt. Siehe dba.stackexchange.com/questions/251875 .
pbillen

Antworten:

18

Zitat des Handbuchs:

Es gibt zwei Möglichkeiten, Zeilen in einer Tabelle mithilfe von Informationen zu löschen, die in anderen Tabellen in der Datenbank enthalten sind: mithilfe von Unterauswahl oder Angabe zusätzlicher Tabellen in der USINGKlausel . Welche Technik besser geeignet ist, hängt von den jeweiligen Umständen ab.

Meine kühne Betonung. Die Verwendung von Informationen, die nicht in einer anderen Tabelle enthalten sind, ist etwas schwierig, aber es gibt einfache Lösungen. Vom Arsenal der Standardtechniken bis zum ...

... ein NOT EXISTSAnti-Semi-Join ist wahrscheinlich am einfachsten und effizientesten für DELETE:

DELETE FROM link_group lg
WHERE  NOT EXISTS (
   SELECT FROM link_reply lr
   WHERE  lr.which_group = lg.link_group_id
   );

Angenommen (da keine Tabellendefinitionen angegeben sind) link_group_idals Spaltenname für den Primärschlüssel von link_group.

Die von @Mihai kommentierte Technik funktioniert ebenfalls (richtig angewendet):

DELETE FROM link_group lg
USING  link_group      lg1
LEFT   JOIN link_reply lr ON lr.which_group = lg1.link_group_id
WHERE  lg1.link_group_id = lg.link_group_id
AND    lr.which_group IS NULL;

Da der Tabellenausdruck in der USINGKlausel jedoch mit a mit der Zieltabelle ( lgim Beispiel) verknüpft ist CROSS JOIN, benötigen Sie eine andere Instanz derselben Tabelle als Sprungbrett ( lg1im Beispiel) für die LEFT JOIN, die weniger elegant und normalerweise langsamer ist.

Erwin Brandstetter
quelle