views:

16187

answers:

7

Are disabling and enabling FK constraints supported in SQL Server? Or is my only option to 'drop and then re-'create' the constraints?

+23  A: 

http://www.sqljunkies.com/WebLog/roman/archive/2005/01/30/7037.aspx

-- Disable all table constraints

ALTER TABLE MyTable NOCHECK CONSTRAINT ALL

-- Enable all table constraints

ALTER TABLE MyTable CHECK CONSTRAINT ALL

-- Disable single constraint

ALTER TABLE MyTable NOCHECK CONSTRAINT MyConstraint

-- Enable single constraint

ALTER TABLE MyTable CHECK CONSTRAINT MyConstraint
ScottStonehouse
a good find, but note that you still cannot truncate the table without removing the foreign key constraints
Steven A. Lowe
and you will also need to be aware that when you turn the constraints back on and do a data integrity check, your data may fail and fixng an issue like that can be a nightmare if the failing data is at the end of a long string of linked constraints.
A: 

I'm supporting ScottStonehouse - you most definitely can disable constraints when manipulating data. HOWEVER: as a general rule you should NEVER do this. One of the only exceptions would be when you are performing large scale data manipulations where allowing the database to perform constraint checks for every record affected will hurt performance too much. In this case you disable the constraints to load the data quickly, but then you must perform data validation at the end and reinstate the constraints.

Dr8k
Never? Seems a bit extreme. Like - I'm in the prototype development stage and I'm syncing up subsets of various instances of the database. It would be a nightmare to do this in any other way.
hamlin11
+49  A: 

If you want to disable all constraints in the database just run this code:

-- disable all constraints
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"

to switch them back on, run: (the print is optional of course and it is just listing the tables)

-- enable all constraints
exec sp_msforeachtable @command1="print '?'", @command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"

I find it useful when populating data from one database to another. It is much better approach then dropping constraints. As you mentioned it comes handy when dropping all the data the database and repopulating it (say in test environment).

If you are deleting all the data you may find this solution to be helpful.

Also sometimes it is handy to disable all triggers as well, you can see the complete solution here

kristof
I had to make a mass migration because I created a new Sql Server database to restructure, and this code was very helpful to make my migration code work
Tony Peterson
This is a pretty extreme solution. I like it!
hamlin11
A: 

The SQL-92 standard allows for a constaint to be declared as DEFERRABLE so that it can be deferred (implicitly or explicitly) within the scope of a transaction. Sadly, SQL Server is still missing this SQL-92 functionality.

For me, changing a constraint to NOCHECK is akin to changing the database structure on the fly -- dropping constraints certainly is -- and something to be avoided (e.g. users require increased privileges).

onedaywhen
+1  A: 

Or check this link

YordanGeorgiev
Thanks that worked. Minor change needed, wrap the f.name in brackets.
AlexanderN
A: 

I have tried with the following command but still i am not able to change the datatype of the columns

ALTER TABLE MyTable NOCHECK CONSTRAINT ALL

wht could be the reason

D.mahesh
This is not the appropriate place to ask this question - this area is for answers. The original question has nothing to do with changing data types. I suggest you open a new question with more clarity as to what you are asking.
Nathan
A: 

I had a similar situation where I had no time to analyze the entire schema, so I did what YourdanGeorgiev suggested.

--
-- DROP CONSTRAINTS 
--
SELECT 'ALTER TABLE ' + '[' + OBJECT_NAME(f.parent_object_id)+ ']'+
' DROP  CONSTRAINT ' + '[' + f.name  + ']'
FROM .sys.foreign_keys AS f
INNER JOIN .sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id


-- 
-- RECREATE CONSTRAINTS
--
SELECT 'ALTER TABLE [' + OBJECT_NAME(f.parent_object_id)+ ']' +
' ADD CONSTRAINT ' + '[' +  f.name  +']'+ ' FOREIGN KEY'+'('+COL_NAME(fc.parent_object_id,fc.parent_column_id)+')'
+'REFERENCES ['+OBJECT_NAME (f.referenced_object_id)+']('+COL_NAME(fc.referenced_object_id,
fc.referenced_column_id)+')' as Scripts
FROM .sys.foreign_keys AS f
INNER JOIN .sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id

Run the code above and save the results for both drop and recreate, then execute all the drops followed by your code and then recreate the constraints using the results from the second query.

AlexanderN