[英]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.