Home  >  Article  >  Database  >  How to Implement Cascading Parent Deletion with Foreign Key Constraints in PostgreSQL?

How to Implement Cascading Parent Deletion with Foreign Key Constraints in PostgreSQL?

Linda Hamilton
Linda HamiltonOriginal
2024-10-31 22:34:29868browse

How to Implement Cascading Parent Deletion with Foreign Key Constraints in PostgreSQL?

Cascading Parent Deletion with Foreign Key Constraint

In relational database systems, deleting a child row often necessitates the deletion of the parent if it is no longer referenced by any other child. This task can be accomplished in PostgreSQL versions 9.1 and later using a data-modifying CTE (Common Table Expression).

Data-Modifying CTE Approach

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

This CTE first deletes the specified child row. It then returns the parent ID and the deleted child ID. The second DELETE statement uses this information to delete the parent row if it has no other remaining children. The condition c.child_id <> x.child_id ensures that only children other than the one being deleted are considered.

Eliminating Race Conditions

To prevent potential race conditions where concurrent transactions may lead to unexpected results, the parent row can be locked before the deletion process. This is achieved by using the FOR NO KEY UPDATE clause in the CTE to lock the parent row.

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

This approach limits the execution of the risky DELETE operations to a single transaction, effectively eliminating the possibility of concurrent interference.

The above is the detailed content of How to Implement Cascading Parent Deletion with Foreign Key Constraints in PostgreSQL?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn