user4135018
user4135018

Reputation:

How can I delete a record, child records and grandchildren records?

I have three tables - bands, gigs and assigns (which assigns a gig to the registered user that entered it to create a many-many relationship between gigs and users.)

The tables are:

Bands: bandID, bandname
Gigs: GigID, bandID, venue, date
Assigns: assignID, gigid, userid (which is then linked to the users table)

A function on the site is to delete a band, but then it goes "Oh, before you delete the band, it'll delete all these gigs", then the user chooses confirm and so on.

I need a query that deletes the band, then deletes the gigs where gigs.bandID = bands.bandID, and then deletes the assigns where assigns.gigID = gigs.gigID.

I've worked out the SELECT statement and this displays the record I want to delete from the assigns table by feeding it the bandid.

SELECT assigns.*
FROM   bands INNER JOIN
   gigs ON bands.bandid = gigs.bandid INNER JOIN
   gigsaccass ON gigs.gigid = gigsaccass.gigid AND bands.bandid = 91

But how do I create a DELETE statement from this?

Upvotes: 1

Views: 3223

Answers (4)

user2366842
user2366842

Reputation: 1216

There are two ways that this can be done, one as has been mentioned is a Cascading Delete. The other would be to effectively recreate a cascading deletion by use of several queries. Personally I prefer the second option, as it allows you a little bit more control over your data. Utilizing cascading deletions (especially in a production environment) can lead to rather disastrous consequences if you're not extremely careful. Undoing a single record deletion can be fairly easy (if it's a simple table), undoing a cascading delete that inadvertently hits against 20 different tables is all but impossible without a database backup.

Upvotes: 2

Eric J. Price
Eric J. Price

Reputation: 2785

There are a bunch of ways you could go about it, but this is the route I'd go if you don't want to do the ON DELETE CASCADE constraint option...

Declare @bandID Int
Set     @bandID = 91

--      Delete the associated gigsaccess records
DELETE  ga
FROM    bands As b
INNER   JOIN gigs As g  
        ON  b.bandid = g.bandid 
INNER   JOIN gigsaccass As ga 
        ON  g.gigid = ga.gigid 
WHERE   b.bandid = @bandID

--      Delete the associated gigs records
DELETE  g
FROM    bands As b
INNER   JOIN gigs As g  
        ON  b.bandid = g.bandid 
WHERE   b.bandid = @bandID

--      Delete the band record
DELETE  b
FROM    bands As b
WHERE   b.bandid = @bandID

Upvotes: 2

JamieD77
JamieD77

Reputation: 13949

Cascading deletes are nice and easy.. you just need to create your foreign keys a certain way.

-- foreign key constraint
ALTER TABLE [dbo].[Gigs]  WITH CHECK 
ADD CONSTRAINT [FK_Gigs_Band] FOREIGN KEY([BandID])
REFERENCES [dbo].[Bands] ([BandID])
ON DELETE CASCADE
GO

-- foreign key constraint
ALTER TABLE [dbo].[Assigns]  WITH CHECK 
ADD CONSTRAINT [FK_Assigns_Gigs] FOREIGN KEY([GigID])
REFERENCES [dbo].[Gigs] ([GigID])
ON DELETE CASCADE
GO

make sure you delete the current foreign key first if you have one..

another way is create triggers.. in particular, Instead of Delete triggers

CREATE TRIGGER [DELETE_Bands]
   ON dbo.[Bands]
   INSTEAD OF DELETE
AS 
BEGIN
 SET NOCOUNT ON;
 DELETE FROM [Gigs] WHERE BandID IN (SELECT BandID FROM DELETED)
 DELETE FROM [Bands] WHERE BandID IN (SELECT BandID FROM DELETED)
END
GO

CREATE TRIGGER [DELETE_Gigs]
   ON dbo.[Gigs]
   INSTEAD OF DELETE
AS 
BEGIN
 SET NOCOUNT ON;
 DELETE FROM [Assigns] WHERE GigID IN (SELECT GigID FROM DELETED)
 DELETE FROM [Gigs] WHERE GigID IN (SELECT GigID FROM DELETED)
END
GO

Upvotes: 0

As jae555 says, I would say that the ON DELETE CASCADE trigger is the way to go.

Upvotes: 0

Related Questions