Untuk menonaktifkan batasan kunci asing:
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;
Untuk mengaktifkan kembali:
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;
Namun, Anda tidak akan dapat memotong tabel, Anda harus menghapusnya dalam urutan yang benar. Jika Anda perlu memotong mereka, Anda harus menghilangkan batasan sepenuhnya, dan membuatnya kembali. Ini mudah dilakukan jika batasan kunci asing Anda semuanya sederhana, batasan kolom tunggal, tetapi pasti lebih kompleks jika ada banyak kolom yang terlibat.
Berikut adalah sesuatu yang dapat Anda coba. Untuk menjadikan ini bagian dari paket SSIS Anda, Anda memerlukan tempat untuk menyimpan definisi FK saat paket SSIS berjalan (Anda tidak akan dapat melakukan ini semua dalam satu skrip). Jadi di beberapa database utilitas, buat tabel:
CREATE TABLE dbo.PostCommand(cmd NVARCHAR(MAX));
Kemudian di database Anda, Anda dapat memiliki prosedur tersimpan yang melakukan ini:
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
Sekarang ketika paket SSIS Anda selesai, ia akan memanggil prosedur tersimpan yang berbeda, yaitu:
DECLARE @sql NVARCHAR(MAX);
SELECT @sql = cmd FROM other_database.dbo.PostCommand;
EXEC sp_executesql @sql;
Jika Anda melakukan semua ini hanya demi dapat memotong alih-alih menghapus, saya sarankan hanya mengambil hit dan menjalankan penghapusan. Mungkin menggunakan model pemulihan yang dicatat secara massal untuk meminimalkan dampak dari log. Secara umum saya tidak melihat bagaimana solusi ini akan jauh lebih cepat daripada hanya menggunakan penghapusan dalam urutan yang benar.
Pada tahun 2014 saya menerbitkan posting yang lebih rumit tentang ini di sini:
- Lepaskan dan Buat Ulang Semua Batasan Kunci Asing di SQL Server