[英]PostgreSQL Cascade for columns (not foreign key)
create table parent (
child_type not null
child_id not null
);
create table child1(id not null);
create table child2(id not null);
create table child3(id not null);
父表中有一些行是這樣的:
child_type,child_id
"child1",1
"child1",2
"child2",1
"child3",1
我想在刪除父行時刪除子行。 有沒有辦法在刪除級聯上觸發這個觸發器?
我認為(child_type,child_id)
是parent
的主鍵(並且此建議僅在如下情況下才有效:如果您想刪除父行以通過 FK 級聯觸發子行中的刪除,則父級必須具有一個主鍵)
您可以像這樣創建關聯:
create table child1(
child_type VARCHAR(20) DEFAULT 'child1',
id INT not null
FOREIGN KEY (child_type,id) REFERENCES parent(child_type, child_id) ON DELETE CASCADE
);
create table child2(
child_type VARCHAR(20) DEFAULT 'child2',
id INT not null
FOREIGN KEY (child_type,id) REFERENCES parent(child_type, child_id) ON DELETE CASCADE
);
create table child3(
child_type VARCHAR(20) DEFAULT 'child3',
id INT not null
FOREIGN KEY (child_type,id) REFERENCES parent(child_type, child_id) ON DELETE CASCADE
);
您不能在父級復合 PK 的子級引用部分中只有id
; 子級必須具有與父級 PK 具有相同值的相同 N 列
FWIW 那個表結構真的很奇怪,它可能會一次又一次地咬你。
更喜歡更正常的東西,例如:
create table parent (
id PRIMARY KEY
);
create table child1(id PRIMARY KEY, parent_id REFERENCES parent(id));
create table child2(id PRIMARY KEY, parent_id REFERENCES parent(id));
create table child3(id PRIMARY KEY, parent_id REFERENCES parent(id));
我希望這對您的實際問題來說是一個人為的情況,因為它確實是一個糟糕的設計。 假設您實際上“想要在我刪除父行時刪除子行” 。 除非您更改數據模型並定義 FK 約束,否則您需要在父表上使用刪除觸發器。 你不能在沒有 FK 的情況下級聯刪除,因為這是你定義 Postgres 的地方。 順便說一句,您的表定義無效。 Not Null 是約束不是數據類型,你還沒有建立數據類型。 更正后,如果您的 child_type 列被理解為實際命名子表所在的表,您可以構建一個觸發器,從相應的子表中刪除相應的行。 一個非常糟糕的設計導致一個極其危險的假設,但是:
-- setup
create table parent (
child_type text not null
,child_id integer not null
);
create table child1(id integer not null);
create table child2(id integer not null);
create table child3(id integer not null)
insert into parent(child_type, child_id)
values ('child1',1),('child1',2),('child2',1),('child3',1);
insert into child1(id) values (1),(2);
insert into child2(id) values (1);
insert into child3(id) values (1);
現在創建觸發器函數,然后“附加”到父表。觸發器函數現在構建並動態執行適當的刪除語句。 注意我總是在執行之前生成一個提升通知來顯示實際語句,並在此處執行此操作。 你可以認為沒有必要。
-- build trigger function.
create or replace function parent_adr()
returns trigger
language plpgsql
as $$
declare
base_del_lk constant text = 'delete from %s where id = %s';
sql_delete_stmt_l text;
begin
sql_delete_stmt_l = format(base_del_lk,old.child_type, old.child_id);
raise notice 'Running statement==%', sql_delete_stmt_l;
EXECUTE sql_delete_stmt_l;
return old;
end;
$$;
-- and define the trigger on the parent table.
create trigger parent_adr_trig
after delete
on parent
for each row
execute procedure parent_adr();
--- test.
delete from parent where child_type = 'child1';
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.