Heim >Datenbank >MySQL-Tutorial >Wie lösche ich übergeordnete Datensätze in PostgreSQL, wenn keine untergeordneten Datensätze darauf verweisen?

Wie lösche ich übergeordnete Datensätze in PostgreSQL, wenn keine untergeordneten Datensätze darauf verweisen?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-10-29 07:20:021040Durchsuche

How to Delete Parent Records in PostgreSQL When No Children Refer to Them?

Kaskadierende übergeordnete Löschung: Löschen eines übergeordneten Elements, wenn es nicht mehr von untergeordneten Elementen referenziert wird

Wenn in Datenbanksystemen eine untergeordnete Tabelle über a auf eine übergeordnete Tabelle verweist Fremdschlüssel ergibt sich ein typisches Szenario beim Löschen einer untergeordneten Zeile: Sollte die übergeordnete Zeile auch gelöscht werden, wenn kein anderes untergeordnetes Element darauf verweist?

PostgreSQL 9.1 und höher: Datenmodifizierender CTE-Ansatz

Für PostgreSQL-Versionen 9.1 oder höher kann eine einzelne Anweisung, die einen datenmodifizierenden CTE verwendet, dies effizient erreichen:

<code class="sql">WITH del_child AS (
    DELETE FROM child
    WHERE  child_id = 1
    RETURNING parent_id, child_id
    )
DELETE FROM parent p
USING  del_child x
WHERE  p.parent_id = x.parent_id
AND    NOT EXISTS (
   SELECT FROM child c
   WHERE  c.parent_id = x.parent_id
   AND    c.child_id <> x.child_id   -- !
   );</code>

Diese Anweisung löscht die angegebene untergeordnete Zeile und, wenn das resultierende übergeordnete Element keine hat verbleibende untergeordnete Referenzen, löscht auch das übergeordnete Element. Die Schlüsselbedingung in der EXISTS-Unterabfrage stellt sicher, dass das übergeordnete Element nur gelöscht wird, wenn alle seine untergeordneten Elemente gelöscht wurden.

Race Conditions beseitigen

Race Conditions vollständig eliminieren Es ist wichtig, die übergeordnete Zeile zu sperren, bevor eine Löschung erfolgt:

<code class="sql">WITH lock_parent AS (
   SELECT p.parent_id, c.child_id
   FROM   child  c
   JOIN   parent p ON p.parent_id = c.parent_id
   WHERE  c.child_id = 12              -- provide child_id here once
   FOR    NO KEY UPDATE                -- locks parent row.
   )
 , del_child AS (
   DELETE FROM child c
   USING  lock_parent l
   WHERE  c.child_id = l.child_id
   )
DELETE FROM parent p
USING  lock_parent l
WHERE  p.parent_id = l.parent_id
AND    NOT EXISTS (
   SELECT FROM child c
   WHERE  c.parent_id = l.parent_id
   AND    c.child_id <> l.child_id   -- !
   );</code>

Diese Methode stellt sicher, dass jeweils nur eine Transaktion dasselbe übergeordnete Element sperren kann, wodurch verhindert wird, dass mehrere Transaktionen alle untergeordneten Elemente löschen und ein übergeordnetes Element frei bleibt.

Das obige ist der detaillierte Inhalt vonWie lösche ich übergeordnete Datensätze in PostgreSQL, wenn keine untergeordneten Datensätze darauf verweisen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn