简体   繁体   中英

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?

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.

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

正如jae555所说,我要说的是ON DELETE CASCADE触发器。

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

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM