Author |
Topic |
bartman_z
Starting Member
11 Posts |
Posted - 2005-12-16 : 08:38:46
|
Hi there,I have a table with the following type of dataMasterID ---- RelatedRecordID1 -------------- NULL2 --------------- 13 --------------- 14 --------------- 25 --------------- 26 --------------- 4etc etc you get the general idea.I want to be able to delete the record with MasterID 1 and a trigger or something to automatically 'cascade' down all the related records and delete them.I have tried (unsuccessfully) to create relationships with cascade deletes and to create a trigger but all to no avail.Any help or pointers in the right direction would be much appreciated.Bartmanwww.meridiantd.co.uk |
|
TG
Master Smack Fu Yak Hacker
6065 Posts |
Posted - 2005-12-16 : 11:25:08
|
Yeah, sql doesn't like cascade deletes for hierarchal relationships. You can cascade throught the whole table. You can get around it using an INSTEAD of trigger but I wouldn't. I would urge you not to use this approach, its too easy to wipe out all your data.set nocount oncreate table junk (masterid int primary key ,rid int references junk (masterid) /*on delete cascade*/) --sql doesn't like a delete cascade for hierarchal relationshipgo--so need to use an instead of triggercreate trigger tr_junk_del on junk instead of deleteasbegin set nocount on declare @tb table (masterid int) insert @tb (masterid) select masterid from deleted insert @tb (masterid) select j.masterid from deleted d join junk j on j.rid = d.masterid group by j.masterid while @@rowcount > 0 begin insert @tb (masterid) select j.masterid from @tb d join junk j on j.rid = d.masterid left join @tb ex on ex.masterid = j.masterid where ex.masterid is null group by j.masterid end delete j from junk j join @tb t on t.masterid = j.masteridendgoinsert junk values (1,null)insert junk values (2,1)insert junk values (3,2)insert junk values (4,3)insert junk values (5,4)insert junk values (6,5)goprint 'junk before delete:'select * from junkset nocount offprint 'perform delete'delete junk where masterid = 1set nocount onprint 'shows 1 row affected but really wiped out whole table'print 'junk after delete:'select * from Junkgodrop table junk Be One with the OptimizerTG |
 |
|
blindman
Master Smack Fu Yak Hacker
2365 Posts |
Posted - 2005-12-16 : 12:59:03
|
A case could be made that this logic is complex enough that it would be better suited to a stored procedure than a trigger (you ARE preventing users from directly accessing tables, right?), but here is a method you can use either way:In your trigger or sproc, create a temporary table for holding ID values of records to be deleted.Seed it with the ID of the record being deleted.Append child records of all IDs in your temporary table that are not already in the table, and loop until no new IDs are added.Perform a single DELETE against your production table to remove all records corresponding IDs in your temporary table. |
 |
|
TG
Master Smack Fu Yak Hacker
6065 Posts |
Posted - 2005-12-16 : 13:24:09
|
quote: In your trigger or sproc, create a temporary table for holding ID values of records to be deleted.Seed it with the ID of the record being deleted.Append child records of all IDs in your temporary table that are not already in the table, and loop until no new IDs are added.Perform a single DELETE against your production table to remove all records corresponding IDs in your temporary table.
I like your logic. Maybe because it's identical to what I used in my post . Is that why they call you blindman? Be One with the OptimizerTG |
 |
|
blindman
Master Smack Fu Yak Hacker
2365 Posts |
Posted - 2005-12-16 : 14:48:12
|
I don't see your point.Ha ha Actually, I stopped reading your post at "INSTEAD OF", because I don't implement it this way and so assumed that your entire solution was different. My bad. |
 |
|
TG
Master Smack Fu Yak Hacker
6065 Posts |
Posted - 2005-12-16 : 15:26:27
|
No bad. It just validated the choice of logic. It's funny to me because it really is identical (line by line)The only reason I chose "instead of" trigger is because I thought if he wanted to put the constraint on there, then a normal "after" trigger may never fire if the delete violated the constraint. I don't know if that's true or not but that was the reason...Anyway keep up the good work!Be One with the OptimizerTG |
 |
|
cmschick
Starting Member
20 Posts |
Posted - 2005-12-30 : 22:41:37
|
quote: quote:--------------------------------------------------------------------------------In your trigger or sproc, create a temporary table for holding ID values of records to be deleted.Seed it with the ID of the record being deleted.Append child records of all IDs in your temporary table that are not already in the table, and loop until no new IDs are added.Perform a single DELETE against your production table to remove all records corresponding IDs in your temporary table.--------------------------------------------------------------------------------I like your logic. Maybe because it's identical to what I used in my post . Is that why they call you blindman? Be One with the OptimizerTG
Hi TG, I'm hoping you are subscribed to this post. Can you spell out exactly how to do this? I don't know what you mean when you say "Seed it with the ID of the record being deleted" The same goes for "Append child records of all IDs in your temporary table that are not already in the table, and loop until no new IDs are added." Thank you.Christopher SchickThe Schickster |
 |
|
TG
Master Smack Fu Yak Hacker
6065 Posts |
Posted - 2005-12-31 : 09:39:39
|
Hey Chris,The verbal description (quoted) is from blindman, but it is exactly the technique I used in my 1st post on this thread.>>Seed it with the ID of the record being deleted insert @tb (masterid) select masterid from deleted >>Append child records of all IDs in your temporary table that are not already in the table insert @tb (masterid) select j.masterid from deleted d join junk j on j.rid = d.masterid group by j.masterid >>and loop until no new IDs are added while @@rowcount > 0 begin insert @tb (masterid) select j.masterid from @tb d join junk j on j.rid = d.masterid --this section just insures the added IDs don't already exist in the table left join @tb ex on ex.masterid = j.masterid where ex.masterid is null group by j.masterid end Finally, delete all affected rows from the real table (including the row that the user inteneded to delete - the row we first seeded - since this is an INSTEAD of trigger) delete j from junk j join @tb t on t.masterid = j.masterid Be One with the OptimizerTG |
 |
|
cmschick
Starting Member
20 Posts |
Posted - 2005-12-31 : 10:54:34
|
Thanks TG,You're a big help.ChrisThe Schickster |
 |
|
|