views:

239

answers:

5

I want to be able to choose a groupID and do a cascading delete through three tables which are found in a MS SQL server database. The tables look like the following:

table 1 - GROUP
-------------------------------------------
groupID | description | etc


table 2 - MEMBER
-------------------------------------------
memberID | name | etc


table 3 - MAPPINGTABLE 
-------------------------------------------
mappingID | groupID | memberID

I'm thinking that since I know the groupID, I could probably select the memberID's from the mapping table based off of the groupID and delete those from the member table, but I usually end up with an error of:

"The DELETE statement conflicted with the REFERENCE constraint...[FK constraint in table]".

Would anyone be able to give me some guidance on the best way to delete from all three of these tables at the same time?

Thanks.

+4  A: 

You are running into Referential Integrity. No worries, RI is your friend. It is meant to protect you.

Based on your structure, you cannot delete from the Member or the Group table if the row that you are attempting to delete has a corresponding row in the MappingTable.

If the system were to allow you to do that, you would have orphan data in the MappingTable without corresponding data in the Member or Group tables. The database is preventing you from deleting the data because a Referential Integrity constraint has been placed on the data using the Foreign Key constraint.

There are options like ON DELETE CASCADE, but they are potentially very deadly and can cause massive data loss. I personally never implement cascading deletes.

You should first remove the rows from the MappingTable and then delete any data from the lookup tables (Member, Group)

Having said that, I must say the following:

  1. Make backups (and ensure you have a valid backup) of your data before you delete it.
  2. Make another backup cause data once deleted is gone forever.
  3. Check with the business / SME to validate that you are doing the right thing by removing the data
Raj More
Agree I also never use cascading deletes because it can cause massive performance problems if someone deletes are large batch of records.
HLGEM
The data is safe to delete, it's all temp working stuff until the user actually saves it to other tables.
Chris
Thanks! A little discussion got the juices going this morning. I used a temp table to hold the memeber Id's while I deleted from the mapping table and then from the other two tables after the mapping row was gone.
Chris
+3  A: 

You need to work your way back up the tables, so start at the very bottom and then delete from table 3 working back to table 1.

Ardman
A: 

Cascade deletes are implemented differently in different SQL servers. What are you using for server software?

In oracle, you can specify cascade deletes when you create the tables so they will automatically delete data from other tables when the main record is deleted. Here's an example:

ALTER TABLE MAPPINGTABLE ADD CONSTRAINT FK_GROUPID
    FOREIGN KEY (groupID) REFERENCES GROUP(groupID)
ON DELETE CASCADE
;
Kieveli
A: 

The easiest thing is when you're setting up your foreign keys, you set them to ON DELETE CASCADE

ALTER TABLE mappingtable ADD CONSTRAINT fk_group_id FOREIGN KEY(groupID) REFERENCES group(groupID) ON DELETE CASCADE

The other option is ON UPDATE CASCADE if you wanted to add it, but it wouldn't help here.

What this does is it makes it so when you delete the parent from GROUP it will automatically delete any reference to it in the table MAPPINGTABLE

To delete from users as well, you would need to do a second delete statement.

Slokun
Have to be very careful using cascading deletes... I never use them myself out of fear.
RenderIn
Cascading deletes are your friends.
Pontus Gagge
`ON DELETE CASCADE` is like fire -- a tool that can be use for great benefit, or great harm. Oracle's implementation of `DELETE CASCADE` is functionally a nested-loop delete (it issues a `DELETE FROM CHILD_TABLE WHERE KEY_VALUE = :parent_key` for each row) and in some cases you'd be better off finding the children yourselves with a `DELETE FROM CHILD_TABLE WHERE KEY_VALUE IN (SELECT PARENT_KEY FROM PARENT WHERE DELETE_CONDITION IS TRUE)`.
Adam Musch
+1  A: 

in order to use the an cascade delete you must specify a delete rule in the the foreign key. the "ON DELETE CASCADE" option is what you need.

see this example

CREATE TABLE table_child
(
fieldkeyparent int,
field1 INT,
FOREIGN KEY ([fieldkeyparent]) REFERENCES Table_parent
ON DELETE CASCADE)

check this link for SQL Server. Cascading Referential Integrity Constraints

RRUZ
Thanks for the idea. Your create table gave me the idea to create a temp table to hold some values while I delete from the other tables.
Chris