Thread: Foreign Key Constraint Deletion Order
I have found from a small number of tests that deletions executed by foreign key constraint does NOT guarantee the detail table to be deleted BEFORE master table. This makes some of my trigger functions assocated with the detail table mulfunction because the trigger function can't find its parent record. Is there any plan to change the foreign key constraint deletion (and update in master-then-detail) order? Thanks you all! CN -------------------------------------------------------- You too can have your own email address from Eurosport. http://www.eurosport.com
On Mon, 19 Nov 2001 cnliou@eurosport.com wrote: > I have found from a small number of tests that > deletions executed by foreign key constraint does NOT > guarantee the detail table to be deleted BEFORE > master table. This makes some of my trigger functions > assocated with the detail table mulfunction because > the trigger function can't find its parent record. The detail table rows are currently deleted at end of statement or end of transaction (based on deferrability). Technically the time is indeterminate in regards to user triggers on the master table. We've been having discussions on hackers about the behavior, but it's unlikely that the rows will be deleted before the master row.
Thanks! Stephan, > We've been having discussions on hackers about the behavior, > but it's unlikely that the rows will be deleted before > the master row. Then I am in big big trouble! Please imagine a very usual scenario: create table PurchaseMaster (book text primary key, UnitPrice float); create table PurchaseDetail ( CONSTRAINT fk_abc FOREIGN KEY (book) REFERENCES PurchaseMaster (book) on delete cascade on update cascade, primary key (book,buyer), book text, buyer text, quantity smallint ); create table HowMuchIOwe (buyer text primary key,amount float); CREATE FUNCTION MyTrigger() RETURNS opaque AS ' BEGIN UPDATE HowMuchIOwe set amount=amount-old.quantity*(select UnitPrice from PurchaseMaster where book=old.book) where buyer=old.buyer; END; CREATE TRIGGER TriggerDetail AFTER DELETE ON PurchaseDetail FOR EACH ROW EXECUTE PROCEDURE MyTrigger( ); Now when a row in PurchaseMaster is deleted by user, because: (1) getting rid of fk_abc constraint and replacing it with a custom trigger function associated with PurchaseMaster in order to delete PurchaseDetail "manually" does not work either since PurchaseMaster row may be deleted BEFORE this custom trigger function is called; (2) and row in PurchaseMaster may be deleted before PurchaseDetail. so I have no way out! CN -------------------------------------------------------- You too can have your own email address from Eurosport. http://www.eurosport.com
On Mon, 19 Nov 2001 cnliou@eurosport.com wrote: > Then I am in big big trouble! Please imagine a very > usual scenario: > [example snipped] I think you can do this as part of a trigger on PurchaseMaster and something that doesn't do the subtraction if the subselect returns a NULL in the detail trigger (or subtracts 0), not as pretty, but it should function. The master trigger would subtract as necessary for the details for the user.
Thanks again! Stephan, > I think you can do this as part of a trigger on PurchaseMaster and > something that doesn't do the subtraction if the subselect returns > a NULL in the detail trigger (or subtracts 0), not as pretty, but > it should function. The master trigger would subtract as necessary > for the details for the user. This is really a pain though it works. Since delete from PurchaseMaster and PurchaseDetail are both possible, two subtraction trigger functions must be written for PurchaseMaster and PurchaseDetail, respectively. It also seems unwise not to use the powerful-but-easy-to-use RI capability (on delete cascade on update cascade) but to implement it with my own trigger to be fired by PurchaseMaster. If the delete was always done on PurchaseDetail before PurchaseMaster, then one subtraction function for PurchaseDetail along with the RI would settle down everything. Am I asking for too much, or RI and triggers were not designed for operations like this example in the first place? CN -------------------------------------------------------- You too can have your own email address from Eurosport. http://www.eurosport.com
<cnliou@eurosport.com> writes: > Am I asking for too much, or RI and triggers were not > designed for operations like this example in the > first place? The problem is that RI is implemented by triggers, and there's no guarantees about the firing order of multiple triggers. So you don't know whether your custom triggers will fire before or after the RI actions occur. We've had some discussions in the past about arranging things so that trigger firing order could be predicted/controlled. But nothing's been done about it yet. Search the archives if you want to see the prior discussions. regards, tom lane
On Mon, 19 Nov 2001, Tom Lane wrote: > <cnliou@eurosport.com> writes: > > Am I asking for too much, or RI and triggers were not > > designed for operations like this example in the > > first place? > > The problem is that RI is implemented by triggers, and there's > no guarantees about the firing order of multiple triggers. > So you don't know whether your custom triggers will fire > before or after the RI actions occur. Even specifying the after trigger order wouldn't help him I think. He'd want the deletion of the details rows and their associated triggers to run before the actual deletion of the master row. I'd guess that would require the cascade delete to be being done as a before delete trigger.
On Tue, 20 Nov 2001 cnliou@eurosport.com wrote: > This is really a pain though it works. > > Since delete from PurchaseMaster and PurchaseDetail > are both possible, two subtraction trigger functions > must be written for PurchaseMaster and > PurchaseDetail, respectively. > > It also seems unwise not to use the > powerful-but-easy-to-use RI capability (on delete > cascade on update cascade) but to implement it with > my own trigger to be fired by PurchaseMaster. Yeah, there's also some locking gotchas involved so while the RI stuff isn't nearly perfect it's probably a good idea to stick with it unless you're running one of the problem cases. > If the delete was always done on PurchaseDetail > before PurchaseMaster, then one subtraction function > for PurchaseDetail along with the RI would settle > down everything. > > Am I asking for too much, or RI and triggers were not > designed for operations like this example in the > first place? For the particular case you're looking for I don't think so. It sounds like it'd make sense, but I don't think it'd fit the spec wording (given that we've been arguing how far after the deletion that the cascade occurs, I don't think anyone's argued for before the deletion).