Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL Script to alter ALL Foreign Keys to add ON DELETE CASCADE

I have a SQL 2005 database with approx 250 tables.

I want to temporarily enable ON DELETE CASCADE to all of the Foreign Keys so that I can do a bulk delete easily.

I then want to turn off ON DELETE CASCADE on all Foreign Keys.

The only way I know of doing this, is to use Management Studio to generate a full database create script, do some kind of search and replace to strip out everything but Foreign Keys, save the script, then do some more search and replacing to add the ON DELETE CASCADE.

Then I run the script, do my delete, and then run the other script.

Is there an easier way to produce this script? This method seems far too prone to error and I will have to keep the script up to date with any other changes we make to the database, or re-generate it manually each time I may need to use it.

Is an alternative option to run a select on the system tables to "generate" the script for me? Could it even be possible to run an update on a system table that enables and disables ON DELETE CASCADE?

like image 521
Robin Day Avatar asked May 15 '09 13:05

Robin Day


People also ask

How do you write on delete cascade in SQL?

Use the ON DELETE CASCADE option to specify whether you want rows deleted in a child table when corresponding rows are deleted in the parent table. If you do not specify cascading deletes, the default behavior of the database server prevents you from deleting data in a table if other tables reference it.

How do I add a cascade to a foreign key?

If you want to add an on delete cascade to an existing foreign key constraint, you are going to need two statements. The first statement will drop the constraint and the second statement will recreate it with the addition of the on delete clause.

How do I delete a row in a table that contains foreign keys to other tables?

DELETE FROM ReferencingTable WHERE NOT EXISTS ( SELECT * FROM MainTable AS T1 WHERE T1. pk_col_1 = ReferencingTable. pk_col_1 ); Second, as a one-time schema-alteration exercise, add the ON DELETE CASCADE referential action to the foreign key on the referencing table e.g.


1 Answers

Here's a script I used for a similiar purpose. It does not support composite foreign keys (which use more than one field.) And it would probably need some tweaking before it will work for your situation. EDIT: In particular it does not handle multi-column foreign keys correctly.

select   DropStmt = 'ALTER TABLE [' + ForeignKeys.ForeignTableSchema +        '].[' + ForeignKeys.ForeignTableName +        '] DROP CONSTRAINT [' + ForeignKeys.ForeignKeyName + ']; ' ,  CreateStmt = 'ALTER TABLE [' + ForeignKeys.ForeignTableSchema +        '].[' + ForeignKeys.ForeignTableName +        '] WITH CHECK ADD CONSTRAINT [' +  ForeignKeys.ForeignKeyName +        '] FOREIGN KEY([' + ForeignKeys.ForeignTableColumn +        ']) REFERENCES [' + schema_name(sys.objects.schema_id) + '].[' +   sys.objects.[name] + ']([' +   sys.columns.[name] + ']) ON DELETE CASCADE; '  from sys.objects   inner join sys.columns     on (sys.columns.[object_id] = sys.objects.[object_id])   inner join (     select sys.foreign_keys.[name] as ForeignKeyName      ,schema_name(sys.objects.schema_id) as ForeignTableSchema      ,sys.objects.[name] as ForeignTableName      ,sys.columns.[name]  as ForeignTableColumn      ,sys.foreign_keys.referenced_object_id as referenced_object_id      ,sys.foreign_key_columns.referenced_column_id as referenced_column_id      from sys.foreign_keys       inner join sys.foreign_key_columns         on (sys.foreign_key_columns.constraint_object_id           = sys.foreign_keys.[object_id])       inner join sys.objects         on (sys.objects.[object_id]           = sys.foreign_keys.parent_object_id)         inner join sys.columns           on (sys.columns.[object_id]             = sys.objects.[object_id])            and (sys.columns.column_id             = sys.foreign_key_columns.parent_column_id)     ) ForeignKeys     on (ForeignKeys.referenced_object_id = sys.objects.[object_id])      and (ForeignKeys.referenced_column_id = sys.columns.column_id)  where (sys.objects.[type] = 'U')   and (sys.objects.[name] not in ('sysdiagrams')) 
like image 116
Andomar Avatar answered Oct 08 '22 18:10

Andomar