首頁 >資料庫 >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