Ich habe die folgenden zwei Skripte zum Deaktivieren von Fremdschlüsseln verwendet. Ich habe sie nicht erstellt, ich habe sie auf Interwebs gefunden, aber sie haben in den letzten Jahren perfekt für mich funktioniert. Leider kann ich die Quelle nicht mehr finden.
reference_sp.sql ist eine gespeicherte Prozedur, die erstellt werden muss, bevor das andere Skript ausgeführt wird.
reference_run.sql ist ein Skript, das ein Skript zum Deaktivieren/Aktivieren von Fremdschlüsseln generiert.
Beachten Sie, dass es sicher ist, das hier bereitgestellte Skript auszuführen – es ändert die Datenbank nicht (abgesehen vom Erstellen und anschließenden Löschen temporärer Tabellen), es generiert nur ein weiteres Skript, das die Fremdschlüssel löscht und neu erstellt.
Und jetzt die Skripte.
reference_sp.sql:
USE [master]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
/*********************************************************************************************
Copyright SQLServerNation.com
* Author: Tim Chapman
***********************************************************************************************/
CREATE PROCEDURE [dbo].[sp_ShowForeignKeyObjects]
AS
SELECT
OBJECT_NAME(constid) AS ConstraintName,
OBJECT_SCHEMA_NAME(fkeyid) + '.' + OBJECT_NAME(fkeyid) + '.' + COL_NAME(fkeyid, fkey) AS ForeignKeyObject,
OBJECT_SCHEMA_NAME(rkeyid) + '.' + OBJECT_NAME(rkeyid) + '.' + COL_NAME(rkeyid, rkey) AS ReferenceKeyObject,
COL_NAME(fkeyid, fkey) AS ForeignKeyColumn,
COL_NAME(rkeyid, rkey) AS ReferenceKeyColumn,
constid AS ConstraintID,
OBJECT_SCHEMA_NAME(fkeyid) + '.' + OBJECT_NAME(fkeyid) AS ForeignKeyTable,
fkeyid AS ForeignKeyID,
OBJECT_SCHEMA_NAME(rkeyid) + '.' + OBJECT_NAME(rkeyid) AS ReferenceKeyTable,
rkeyid AS ReferenceKeyID,
keyno AS KeySequenceNumber
FROM
sysforeignkeys
ORDER BY
OBJECT_NAME(rkeyid) ASC, COL_NAME(rkeyid, rkey)
GO
reference_run.sql:
IF OBJECT_ID('tempdb..#FK')>0
DROP TABLE #FK
IF OBJECT_ID('tempdb..#Const')>0
DROP TABLE #Const
CREATE TABLE #FK
(
ConstraintName VARCHAR(255),
ForeignKeyObject VARCHAR(255),
ReferenceObject VARCHAR(255),
ForeignKeyColumn VARCHAR(255),
ReferenceKeyColumn VARCHAR(255),
ConstraintID INT,
ForeignKeyTable VARCHAR(255),
ForeignKeyID INT,
ReferenceKeyTable VARCHAR(255),
ReferenceKeyID INT,
KeySequenceNumber SMALLINT
)
CREATE TABLE #Const
(
ConstraintID INT,
FBuildField VARCHAR(2000) DEFAULT(''),
RBuildField VARCHAR(2000) DEFAULT(''),
CountField SMALLINT
)
INSERT INTO #FK
EXEC sp_Showforeignkeyobjects
SET NOCOUNT ON
DECLARE tempcursor
CURSOR
READ_ONLY
FOR
SELECT
f.ConstraintName ,
f.ForeignKeyObject ,
f.ReferenceObject ,
f.ForeignKeyColumn ,
f.ReferenceKeyColumn,
f.ConstraintID ,
f.ForeignKeyID ,
f.ReferenceKeyID ,
f.KeySequenceNumber,
f.ForeignKeyTable,
f.ReferenceKeyTable
FROM #FK AS f
INNER JOIN
(
SELECT ConstraintID, MAX(KeySequenceNumber) AS MaxSeq
FROM #FK AS k
GROUP BY k.ConstraintID
)b ON f.ConstraintID = b.ConstraintID AND f.KeySequenceNumber = b.MaxSeq
DECLARE
@ConstraintName VARCHAR(255),
@ForeignKeyObject VARCHAR(255),
@ReferenceObject VARCHAR(255),
@ForeignKeyColumn VARCHAR(255),
@ReferenceKeyColumn VARCHAR(255),
@ConstraintID INT,
@ForeignKeyID INT,
@ReferenceKeyID INT,
@KeySequenceNumber SMALLINT,
@ForeignKeyTable VARCHAR(255),
@ReferenceKeyTable VARCHAR(255)
OPEN tempcursor
FETCH NEXT FROM tempCursor INTO
@ConstraintName ,
@ForeignKeyObject ,
@ReferenceObject ,
@ForeignKeyColumn ,
@ReferenceKeyColumn,
@ConstraintID ,
@ForeignKeyID ,
@ReferenceKeyID,
@KeySequenceNumber,
@ForeignKeyTable ,
@ReferenceKeyTable
WHILE (@@fetch_status <> -1)
BEGIN
DECLARE tempcursor2
CURSOR
READ_ONLY
FOR
SELECT ConstraintID, ForeignKeyColumn, ReferenceKeyColumn, KeySequenceNumber
FROM #FK
WHERE ConstraintID = @ConstraintID
ORDER BY ConstraintID, KeySequenceNumber ASC
DECLARE @ConstraintID2 INT, @ForeignKeyColumn2 VARCHAR(255), @ReferenceKeyColumn2 VARCHAR(255), @KeySequenceNumber2 SMALLINT
DECLARE @FKeyBuildField VARCHAR(1000), @RKeyBuildField VARCHAR(1000), @Cnt SMALLINT
OPEN tempcursor2
SELECT @FKeyBuildField = '', @RKeyBuildField = '', @Cnt = 0
FETCH NEXT FROM tempcursor2 INTO @ConstraintID2 , @ForeignKeyColumn2 , @ReferenceKeyColumn2 , @KeySequenceNumber2
WHILE (@@fetch_status <> -1)
BEGIN
SET @Cnt = @Cnt + 1
SELECT @FKeyBuildField = @FKeyBuildField + ISNULL(@ForeignKeyColumn2,'')+
CASE
WHEN @ForeignKeyColumn2 IS NULL THEN ''
ELSE
CASE WHEN @KeySequenceNumber = @KeySequenceNumber2 THEN '' ELSE ',' END
END
SELECT @RKeyBuildField = @RKeyBuildField + ISNULL(@ReferenceKeyColumn2,'')+
CASE
WHEN @ReferenceKeyColumn2 IS NULL THEN ''
ELSE
CASE WHEN @KeySequenceNumber = @KeySequenceNumber2 THEN '' ELSE ',' END
END
INSERT INTO #Const
(
ConstraintID ,
FBuildField ,
RBuildField,
CountField
)
VALUES
(
@ConstraintID,
@FKeyBuildField,
@RKeyBuildField,
@Cnt
)
FETCH NEXT FROM tempcursor2 INTO @ConstraintID2 , @ForeignKeyColumn2 , @ReferenceKeyColumn2 , @KeySequenceNumber2
END
CLOSE tempcursor2
DEALLOCATE tempcursor2
FETCH NEXT FROM tempCursor INTO
@ConstraintName ,
@ForeignKeyObject ,
@ReferenceObject ,
@ForeignKeyColumn ,
@ReferenceKeyColumn,
@ConstraintID ,
@ForeignKeyID ,
@ReferenceKeyID ,
@KeySequenceNumber ,
@ForeignKeyTable ,
@ReferenceKeyTable
END
CLOSE tempcursor
DEALLOCATE tempcursor
SELECT 'ALTER TABLE ' + FKTable + ' DROP CONSTRAINT ' + OBJECT_NAME(a.ConstraintID) AS DropKeys,
'ALTER TABLE ' + FKTable + ' WITH NOCHECK ADD CONSTRAINT ' + OBJECT_NAME(a.ConstraintID) + ' FOREIGN KEY(' + FBuildField + ') REFERENCES ' + RKTable + '(' + RBuildField+')' AS BuildKeys
,*
FROM #Const a
JOIN
(
SELECT ConstraintID, MAX(countfield) AS maxcount
FROM #Const
GROUP BY ConstraintID
) b ON a.ConstraintID = b.ConstraintID AND a.countfield = b.maxcount
JOIN
(
SELECT DISTINCT constraintid, '[' + OBJECT_SCHEMA_NAME(foreignkeyid) + '].[' + OBJECT_NAME(foreignkeyid) + ']' AS FKTable, '[' + OBJECT_SCHEMA_NAME(referencekeyid) + '].[' + OBJECT_NAME(referencekeyid) + ']' AS RKTable FROM #fk
) c ON a.constraintid = c.constraintid
DROP TABLE #Const