Maison >base de données >tutoriel mysql >Comment supprimer les enregistrements parents dans PostgreSQL lorsqu'aucun enfant n'y fait référence ?

Comment supprimer les enregistrements parents dans PostgreSQL lorsqu'aucun enfant n'y fait référence ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-10-29 07:20:021040parcourir

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

Suppression de parent en cascade : suppression d'un parent lorsqu'il n'est plus référencé par les enfants

Dans les systèmes de bases de données, lorsqu'une table enfant fait référence à une table parent via un clé étrangère, un scénario typique se produit lors de la suppression d'une ligne enfant : la ligne parent doit-elle également être supprimée si aucun autre enfant ne la référence ?

PostgreSQL 9.1 et versions ultérieures : approche CTE de modification des données

Pour PostgreSQL versions 9.1 ou ultérieures, une seule instruction utilisant un CTE de modification des données peut efficacement y parvenir :

<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>

Cette instruction supprime la ligne enfant spécifiée et, si le parent résultant n'a pas les références enfants restantes, supprime également le parent. La condition clé de la sous-requête EXISTS garantit que le parent n'est supprimé que si tous ses enfants ont été supprimés.

Élimination des conditions de concurrence

Pour éliminer complètement les conditions de concurrence, il est Il est crucial de verrouiller la ligne parent avant toute suppression :

<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>

Cette méthode garantit qu'une seule transaction peut verrouiller le même parent à la fois, empêchant ainsi plusieurs transactions de supprimer tous les enfants et de laisser un parent en suspens.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn