Comment supprimer une ligne parent si aucun autre enfant n'y fait référence
Lors de la suppression d'une ligne enfant dans une table de base de données, cela peut être nécessaire pour supprimer également la ligne parent si aucun autre enfant n'y fait référence. Cela garantit que la base de données maintient l'intégrité référentielle et évite les pointeurs suspendus.
Utilisation d'un CTE de modification des données
PostgreSQL 9.1 et versions ultérieures offrent une solution pratique utilisant un CTE de modification des données expression de table commune (CTE) :
<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>
Principales caractéristiques :
Élimination des conditions de concurrence
Pour éliminer complètement les conditions de concurrence, verrouillez la ligne parent avant de la supprimer :
<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 approche garantit qu'une seule transaction peut cibler le même parent à la fois, évitant ainsi des résultats inattendus.
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!