简体   繁体   中英

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);

And there's some rows in table parent like this:

child_type,child_id
"child1",1
"child1",2
"child2",1
"child3",1

I want to delete child row when I delete parent row. Is there any way to make this trigger on delete cascade?

I presume that (child_type,child_id) is the primary key of parent (and this advice will only work if it is thus: if you want deleting of a parent row to trigger a delete in a child via a FK cascade, the parent must have a primary key)

You create associations like this:

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
);

You can't have just id in the child references part of the composite PK in the parent; child has to have the same N columns with the same values as the parent PK has


FWIW that table structure is really wonky, and it will probably come around to bite you time and again.

Prefer something more normal, like:

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));

I hope this is a contrived situation for you actual problem, as it really is a terrible design. Assuming you actually "want to delete child row when I delete parent row" . Unless you alter your data model and define FK constraints you require a delete trigger on table parent. You CANNOT cascade deletes without FK as that is where you define to Postgres to do so. BTW, your table definitions are invalid. Not Null is a constraint not a data type, you have not established a data type. After correcting that you can build a trigger which deletes the corresponding rows from the appropriate child table if your child_type column is understood to actually name the table in which the child resides. A very poor design leading to a extremely risky assumption, but:

-- 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);

Now create the trigger function then 'attach' to parent table' The trigger function now builds and dynamically executes the appropriate delete statement. Note I always generate a raise notice to display the actual statement before executing it, and do so here. You may consider it not necessary.

-- 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';

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM