首页 >数据库 >mysql教程 >当没有子项引用父记录时,如何删除 PostgreSQL 中的父记录?

当没有子项引用父记录时,如何删除 PostgreSQL 中的父记录?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-10-29 07:20:021040浏览

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

级联父表删除:当子表不再引用时删除父表

在数据库系统中,当子表通过子表引用父表时外键,删除子行时会出现一个典型场景:如果没有其他子行引用父行,是否也应该删除父行?

PostgreSQL 9.1 及更高版本:数据修改 CTE 方法

对于 PostgreSQL 9.1 或更高版本,利用数据修改 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>

此语句删除指定的子行,并且如果生成的父行没有剩余的子引用,也删除父引用。 EXISTS 子查询中的关键条件确保只有在所有子查询都被删除后,父查询才会被删除。

消除竞争条件

要完全消除竞争条件,需要在发生任何删除之前锁定父行至关重要:

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

此方法可确保一次只有一个事务可以锁定同一父行,从而防止多个事务删除所有子级并留下悬空的父级。

以上是当没有子项引用父记录时,如何删除 PostgreSQL 中的父记录?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn