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.