簡體   English   中英

在Postgres中使用自引用外鍵刪除

[英]Deleting with self-referential foreign key in Postgres

使用具有自引用外鍵的表:

CREATE TABLE tree (  
    id INTEGER,
    parent_id INTEGER,
    PRIMARY KEY (id)  
);

ALTER TABLE tree 
   ADD CONSTRAINT fk_tree
   FOREIGN KEY (parent_id) 
   REFERENCES tree(id);

INSERT INTO tree (id, parent_id)
VALUES (1, null),
       (2, 1),
       (3, 1),
       (4, 2),
       (5, null),
       (6, 5);

我希望通過遞歸遍歷樹來刪除分支,因為我可能不使用ON DELETE CASCADE

WITH RECURSIVE branch (id, parent_id) AS (
      SELECT id, parent_id
      FROM tree
      WHERE id = 1 -- Delete branch with root id = 1

      UNION ALL SELECT c.id, c.parent_id
      FROM tree c -- child
      JOIN branch p -- parent
            ON c.parent_id = p.id
)
DELETE FROM tree t
USING branch b
WHERE t.id = b.id;

使用Postgres中的公用表表達式是否安全,或者我是否必須擔心刪除記錄的順序? Postgres會將所有行刪除為單個集合,還是逐個刪除?

如果答案取決於版本,從哪個版本刪除安全?

不,您不必擔心選擇中的順序。

外鍵(與唯一約束不同)是按語句計算的 ,而不是按行計算。 並且公共表表達式仍然是單個語句,即使您有多個SELECT和DELETE。

因此,如果語句結束時所有約束仍然有效,則一切正常。


您可以通過以下簡單測試輕松查看:

CREATE TABLE fk_test
(
  id          integer PRIMARY KEY,
  parent_id   integer,
  FOREIGN KEY (parent_id) REFERENCES fk_test (id)
);

INSERT INTO fk_test (id, parent_id) 
VALUES 
  (1, null),
  (2, 1),
  (3, 2),
  (4, 1);

因此,即使以“錯誤”順序指定ID,以下內容顯然也有效:

DELETE FROM fk_test
WHERE id IN (1,2,3,4);

以下有效 - 顯示CTE仍然是單個語句:

with c1 as (
  delete from fk_test where id = 1
), c2 as (
  delete from fk_test where id = 2
), c3 as (
  delete from fk_test where id = 3
)
delete from fk_test where id = 4;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM