विदेशी कुंजी बाधाओं को अक्षम करने के लिए:
DECLARE @sql NVARCHAR(MAX) = N'';
;WITH x AS
(
SELECT DISTINCT obj =
QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id)) + '.'
+ QUOTENAME(OBJECT_NAME(parent_object_id))
FROM sys.foreign_keys
)
SELECT @sql += N'ALTER TABLE ' + obj + ' NOCHECK CONSTRAINT ALL;
' FROM x;
EXEC sp_executesql @sql;
पुन:सक्षम करने के लिए:
DECLARE @sql NVARCHAR(MAX) = N'';
;WITH x AS
(
SELECT DISTINCT obj =
QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id)) + '.'
+ QUOTENAME(OBJECT_NAME(parent_object_id))
FROM sys.foreign_keys
)
SELECT @sql += N'ALTER TABLE ' + obj + ' WITH CHECK CHECK CONSTRAINT ALL;
' FROM x;
EXEC sp_executesql @sql;
हालांकि, आप छंटनी . नहीं कर पाएंगे तालिकाओं, आपको उनमें से सही क्रम में हटाना होगा। अगर आपको काटना . करना है उन्हें, आपको बाधाओं को पूरी तरह से छोड़ने और उन्हें फिर से बनाने की आवश्यकता है। यह करना आसान है यदि आपकी विदेशी कुंजी बाधाएं सभी सरल, एकल-स्तंभ बाधाएं हैं, लेकिन निश्चित रूप से अधिक जटिल हैं यदि इसमें कई कॉलम शामिल हैं।
यहां कुछ ऐसा है जिसे आप आजमा सकते हैं। इसे अपने एसएसआईएस पैकेज का एक हिस्सा बनाने के लिए आपको एसएसआईएस पैकेज चलने के दौरान एफके परिभाषाओं को स्टोर करने के लिए एक जगह की आवश्यकता होगी (आप यह सब एक स्क्रिप्ट में नहीं कर पाएंगे)। तो कुछ उपयोगिता डेटाबेस में, एक टेबल बनाएं:
CREATE TABLE dbo.PostCommand(cmd NVARCHAR(MAX));
फिर आपके डेटाबेस में, आपके पास एक संग्रहीत कार्यविधि हो सकती है जो ऐसा करती है:
DELETE other_database.dbo.PostCommand;
DECLARE @sql NVARCHAR(MAX) = N'';
SELECT @sql += N'ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(fk.parent_object_id))
+ '.' + QUOTENAME(OBJECT_NAME(fk.parent_object_id))
+ ' ADD CONSTRAINT ' + fk.name + ' FOREIGN KEY ('
+ STUFF((SELECT ',' + c.name
FROM sys.columns AS c
INNER JOIN sys.foreign_key_columns AS fkc
ON fkc.parent_column_id = c.column_id
AND fkc.parent_object_id = c.[object_id]
WHERE fkc.constraint_object_id = fk.[object_id]
ORDER BY fkc.constraint_column_id
FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '')
+ ') REFERENCES ' +
QUOTENAME(OBJECT_SCHEMA_NAME(fk.referenced_object_id))
+ '.' + QUOTENAME(OBJECT_NAME(fk.referenced_object_id))
+ '(' +
STUFF((SELECT ',' + c.name
FROM sys.columns AS c
INNER JOIN sys.foreign_key_columns AS fkc
ON fkc.referenced_column_id = c.column_id
AND fkc.referenced_object_id = c.[object_id]
WHERE fkc.constraint_object_id = fk.[object_id]
ORDER BY fkc.constraint_column_id
FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '') + ');
' FROM sys.foreign_keys AS fk
WHERE OBJECTPROPERTY(parent_object_id, 'IsMsShipped') = 0;
INSERT other_database.dbo.PostCommand(cmd) SELECT @sql;
IF @@ROWCOUNT = 1
BEGIN
SET @sql = N'';
SELECT @sql += N'ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(fk.parent_object_id))
+ '.' + QUOTENAME(OBJECT_NAME(fk.parent_object_id))
+ ' DROP CONSTRAINT ' + fk.name + ';
' FROM sys.foreign_keys AS fk;
EXEC sp_executesql @sql;
END
अब जब आपका एसएसआईएस पैकेज समाप्त हो गया है, तो उसे एक अलग संग्रहित प्रक्रिया को कॉल करना चाहिए, जो करता है:
DECLARE @sql NVARCHAR(MAX);
SELECT @sql = cmd FROM other_database.dbo.PostCommand;
EXEC sp_executesql @sql;
यदि आप यह सब केवल डिलीट करने के बजाय काट-छाँट करने में सक्षम होने के लिए कर रहे हैं, तो मेरा सुझाव है कि बस हिट लें और डिलीट चलाएँ। शायद लॉग के प्रभाव को कम करने के लिए बल्क-लॉग किए गए पुनर्प्राप्ति मॉडल का उपयोग करें। सामान्य तौर पर मैं यह नहीं देखता कि यह समाधान सही क्रम में केवल डिलीट का उपयोग करने की तुलना में कितना तेज होगा।
2014 में मैंने इसके बारे में एक और विस्तृत पोस्ट यहाँ प्रकाशित की:
- SQL सर्वर में सभी विदेशी कुंजी बाधाओं को छोड़ें और फिर से बनाएं