簡體   English   中英

列的 PostgreSQL 級聯(不是外鍵)

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

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