From: | Sigrid Thijs <sigrid(dot)thijs(at)gmail(dot)com> |
---|---|
To: | pgsql-sql(at)postgresql(dot)org |
Subject: | trigger before delete question |
Date: | 2009-04-21 12:03:50 |
Message-ID: | 23f7d19d0904210503h4eaaef70q96c4338d71f73fee@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-sql |
Hello,
I've bumped into a problem with a trigger before delete that I do not
immediately understand. I have made a simple example that also illustrates
the issue, but in reality the database structure is more complex.
Here's the database scheme:
create table club (
club_id serial not null primary key,
club_name text not null
);
create table member (
member_id serial not null primary key,
member_name text not null,
club_id integer not null references club(club_id) on delete
cascade on update cascade
);
alter table club add column contact_member_id integer references
member(member_id) on delete set null on update cascade;
create or replace function club_trigger_0() returns trigger as $$
begin
delete from member where club_id = old.club_id;
return old;
end;
$$ language plpgsql;
create trigger club_trigger_0 before delete on club for each row execute
procedure club_trigger_0();
It consists of a table club, which can have members assigned to it. A club
can also (but doesn't need to) have a contact
member. When it does, this is set in the contact_member_id field of the
club.
Now when I want to delete a club, all the members also have to be deleted. I
know this can be achieved with the 'on delete cascade', but I have a more
complex situation where some data needs to be deleted from other tables
before a member is deleted, and some data after a member has been deleted.
That's why a separate trigger is written to perform some operations before a
row is deleted from the club table.
Now, when I want to delete a club, and the contact_member_id field is null
for that row, the delete goes fine.
You can try this with the following sql:
-- create a new club
insert into club (club_name) values('club1');
-- create a new member for the new club
insert into member (member_name, club_id) values('member1', (select currval
('club_club_id_seq')));
-- delete the club with all it's members
delete from club where club_id = (select currval ('club_club_id_seq'));
select * from club;
But when a club has a contact_member_id value, all the operations in the
trigger functions are performed correctly, but the delete of the row itself
is not executed. You can try this with the following sql:
-- create a new club
insert into club (club_name) values('club2');
-- create a new member for the new club
insert into member (member_name, club_id) values('member2', (select currval
('club_club_id_seq')));
-- make the new member the contact member of the club
update club set contact_member_id = (select currval('member_member_id_seq'))
from member;
-- delete the club with all it's members
delete from club where club_id = (select currval ('club_club_id_seq'));
select * from club;
The last select statement will still return the row that should be deleted,
with the only difference that the
contact_member_id is set to null.
Is this what I should expect from plpgsql? If the subject to be deleted has
been modified during the before trigger, the delete operation will not be
executed? Is there a way to make sure the row will be deleted?
kind regards,
Sigrid
From | Date | Subject | |
---|---|---|---|
Next Message | Tom Lane | 2009-04-21 14:13:44 | Re: trigger before delete question |
Previous Message | Alban Hertroys | 2009-04-20 08:53:46 | Re: Frequently unable connecting to db "server doesn't listen" |