Wird das Deaktivieren und Aktivieren von Fremdschlüssel-Beschränkungen in SQL Server unterstützt? Oder ist meine einzige Option drop
und dann re- create
die Zwänge?
Antworten
Zu viele Anzeigen? --Drop and Recreate Foreign Key Constraints
SET NOCOUNT ON
DECLARE @table TABLE(
RowId INT PRIMARY KEY IDENTITY(1, 1),
ForeignKeyConstraintName NVARCHAR(200),
ForeignKeyConstraintTableSchema NVARCHAR(200),
ForeignKeyConstraintTableName NVARCHAR(200),
ForeignKeyConstraintColumnName NVARCHAR(200),
PrimaryKeyConstraintName NVARCHAR(200),
PrimaryKeyConstraintTableSchema NVARCHAR(200),
PrimaryKeyConstraintTableName NVARCHAR(200),
PrimaryKeyConstraintColumnName NVARCHAR(200)
)
INSERT INTO @table(ForeignKeyConstraintName, ForeignKeyConstraintTableSchema, ForeignKeyConstraintTableName, ForeignKeyConstraintColumnName)
SELECT
U.CONSTRAINT_NAME,
U.TABLE_SCHEMA,
U.TABLE_NAME,
U.COLUMN_NAME
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE U
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
ON U.CONSTRAINT_NAME = C.CONSTRAINT_NAME
WHERE
C.CONSTRAINT_TYPE = 'FOREIGN KEY'
UPDATE @table SET
PrimaryKeyConstraintName = UNIQUE_CONSTRAINT_NAME
FROM
@table T
INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R
ON T.ForeignKeyConstraintName = R.CONSTRAINT_NAME
UPDATE @table SET
PrimaryKeyConstraintTableSchema = TABLE_SCHEMA,
PrimaryKeyConstraintTableName = TABLE_NAME
FROM @table T
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
ON T.PrimaryKeyConstraintName = C.CONSTRAINT_NAME
UPDATE @table SET
PrimaryKeyConstraintColumnName = COLUMN_NAME
FROM @table T
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE U
ON T.PrimaryKeyConstraintName = U.CONSTRAINT_NAME
--SELECT * FROM @table
--DROP CONSTRAINT:
SELECT
'
ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + ']
DROP CONSTRAINT ' + ForeignKeyConstraintName + '
GO'
FROM
@table
--ADD CONSTRAINT:
SELECT
'
ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + ']
ADD CONSTRAINT ' + ForeignKeyConstraintName + ' FOREIGN KEY(' + ForeignKeyConstraintColumnName + ') REFERENCES [' + PrimaryKeyConstraintTableSchema + '].[' + PrimaryKeyConstraintTableName + '](' + PrimaryKeyConstraintColumnName + ')
GO'
FROM
@table
GO
Ich bin ganz Ihrer Meinung, Hamlin. Bei der Übertragung von Daten mit SSIS oder bei der Replikation von Daten scheint es durchaus notwendig zu sein, Fremdschlüssel-Beschränkungen vorübergehend zu deaktivieren oder aufzuheben und sie dann wieder zu aktivieren oder neu zu erstellen. In diesen Fällen ist die referentielle Integrität kein Problem, da sie bereits in der Quelldatenbank gewahrt ist. Daher können Sie in dieser Angelegenheit beruhigt sein.
WITH CHECK CHECK
ist mit Sicherheit erforderlich!
Dieser Punkt wurde in einigen Antworten und Kommentaren angesprochen, aber ich halte ihn für wichtig genug, um ihn noch einmal zu erwähnen.
Das erneute Aktivieren einer Einschränkung mit dem folgenden Befehl (no WITH CHECK
) haben einige gravierende Nachteile .
ALTER TABLE MyTable CHECK CONSTRAINT MyConstraint;
MIT PRÜFUNG | MIT NICHTPRÜFUNG
Gibt an, ob die Daten in der Tabelle gegen eine neu hinzugefügte oder wieder aktivierte FOREIGN KEY- oder CHECK-Beschränkung. Wenn nicht angegeben, wird WITH CHECK für neue Beschränkungen angenommen, und WITH NOCHECK wird für wieder aktivierte Beschränkungen angenommen.
Wenn Sie keine neuen CHECK- oder FOREIGN KEY-Beschränkungen verifizieren wollen nicht gegen bestehende Daten prüfen wollen, verwenden Sie WITH NOCHECK. Wir empfehlen dies nicht dies nur in seltenen Fällen zu tun. Die neue Einschränkung wird in allen späteren Datenaktualisierungen ausgewertet. Jede Verletzung einer Bedingung, die durch durch WITH NOCHECK unterdrückt werden, wenn die Einschränkung hinzugefügt wird, können zukünftige Aktualisierungen fehlschlagen, wenn sie Zeilen mit Daten aktualisieren, die nicht mit der Beschränkung entsprechen.
Der Abfrageoptimierer berücksichtigt keine Beschränkungen, die definiert sind WITH NOCHECK. Solche Constraints werden ignoriert, bis sie wieder aktiviert werden durch ALTER TABLE table WITH CHECK CHECK CONSTRAINT ALL.
Nota: WITH NOCHECK ist die Standardeinstellung für die Wiederaktivierung von Beschränkungen. Ich muss mich fragen, warum...
- Während der Ausführung dieses Befehls werden keine vorhandenen Daten in der Tabelle ausgewertet - der erfolgreiche Abschluss ist keine Garantie dafür, dass die Daten in der Tabelle gemäß der Einschränkung gültig sind.
- Bei der nächsten Aktualisierung der ungültigen Datensätze wird die Einschränkung ausgewertet und schlägt fehl, was zu Fehlern führen kann, die nichts mit der eigentlichen Aktualisierung zu tun haben.
- Anwendungslogik, die sich auf die Einschränkung verlässt, um sicherzustellen, dass die Daten gültig sind, kann fehlschlagen.
- Der Abfrageoptimierer macht keinen Gebrauch von einer auf diese Weise aktivierten Einschränkung.
En sys.foreign_keys Die Systemansicht bietet einen gewissen Einblick in das Problem. Beachten Sie, dass es sowohl eine is_disabled
und ein is_not_trusted
Spalte. is_disabled
gibt an, ob künftige Datenmanipulationen anhand der Einschränkung validiert werden sollen. is_not_trusted
zeigt an, ob alle Daten in der Tabelle anhand der Einschränkung überprüft wurden.
ALTER TABLE MyTable WITH CHECK CHECK CONSTRAINT MyConstraint;
Kann man Ihren Zwängen trauen? Finden Sie es heraus...
SELECT * FROM sys.foreign_keys WHERE is_not_trusted = 1;
SET NOCOUNT ON
DECLARE @table TABLE(
RowId INT PRIMARY KEY IDENTITY(1, 1),
ForeignKeyConstraintName NVARCHAR(200),
ForeignKeyConstraintTableSchema NVARCHAR(200),
ForeignKeyConstraintTableName NVARCHAR(200),
ForeignKeyConstraintColumnName NVARCHAR(200),
PrimaryKeyConstraintName NVARCHAR(200),
PrimaryKeyConstraintTableSchema NVARCHAR(200),
PrimaryKeyConstraintTableName NVARCHAR(200),
PrimaryKeyConstraintColumnName NVARCHAR(200),
UpdateRule NVARCHAR(100),
DeleteRule NVARCHAR(100)
)
INSERT INTO @table(ForeignKeyConstraintName, ForeignKeyConstraintTableSchema, ForeignKeyConstraintTableName, ForeignKeyConstraintColumnName)
SELECT
U.CONSTRAINT_NAME,
U.TABLE_SCHEMA,
U.TABLE_NAME,
U.COLUMN_NAME
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE U
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
ON U.CONSTRAINT_NAME = C.CONSTRAINT_NAME
WHERE
C.CONSTRAINT_TYPE = 'FOREIGN KEY'
UPDATE @table SET
T.PrimaryKeyConstraintName = R.UNIQUE_CONSTRAINT_NAME,
T.UpdateRule = R.UPDATE_RULE,
T.DeleteRule = R.DELETE_RULE
FROM
@table T
INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R
ON T.ForeignKeyConstraintName = R.CONSTRAINT_NAME
UPDATE @table SET
PrimaryKeyConstraintTableSchema = TABLE_SCHEMA,
PrimaryKeyConstraintTableName = TABLE_NAME
FROM @table T
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
ON T.PrimaryKeyConstraintName = C.CONSTRAINT_NAME
UPDATE @table SET
PrimaryKeyConstraintColumnName = COLUMN_NAME
FROM @table T
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE U
ON T.PrimaryKeyConstraintName = U.CONSTRAINT_NAME
--SELECT * FROM @table
SELECT '
BEGIN TRANSACTION
BEGIN TRY'
--DROP CONSTRAINT:
SELECT
'
ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + ']
DROP CONSTRAINT ' + ForeignKeyConstraintName + '
'
FROM
@table
SELECT '
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
RAISERROR(''Operation failed.'', 16, 1)
END CATCH
IF(@@TRANCOUNT != 0)
BEGIN
COMMIT TRANSACTION
RAISERROR(''Operation completed successfully.'', 10, 1)
END
'
--ADD CONSTRAINT:
SELECT '
BEGIN TRANSACTION
BEGIN TRY'
SELECT
'
ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + ']
ADD CONSTRAINT ' + ForeignKeyConstraintName + ' FOREIGN KEY(' + ForeignKeyConstraintColumnName + ') REFERENCES [' + PrimaryKeyConstraintTableSchema + '].[' + PrimaryKeyConstraintTableName + '](' + PrimaryKeyConstraintColumnName + ') ON UPDATE ' + UpdateRule + ' ON DELETE ' + DeleteRule + '
'
FROM
@table
SELECT '
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
RAISERROR(''Operation failed.'', 16, 1)
END CATCH
IF(@@TRANCOUNT != 0)
BEGIN
COMMIT TRANSACTION
RAISERROR(''Operation completed successfully.'', 10, 1)
END'
GO
Erster Beitrag :)
Für den OP wird die Lösung von Kristof funktionieren, es sei denn, es gibt Probleme mit massiven Daten und Transaktionsprotokoll-Ballon-Problemen bei großen Löschungen. Außerdem kann der Vorgang bei Tabellen mit Hunderten von Millionen von Zeilen SEHR lange dauern, selbst wenn der Tlog-Speicher noch frei ist, da Löschvorgänge in den Tlog geschrieben werden.
Ich verwende eine Reihe von Cursoren, um große Kopien einer unserer großen Produktionsdatenbanken häufig zu kürzen und neu zu laden. Die Lösung wurde für mehrere Schemata und Fremdschlüsselspalten entwickelt und kann für die Verwendung in SSIS sproc'd werden.
Es umfasst die Erstellung von drei Staging-Tabellen (echte Tabellen), in denen die DROP-, CREATE- und CHECK-FK-Skripte untergebracht werden, die Erstellung und das Einfügen dieser Skripte in die Tabellen und die anschließende Schleifenbildung über die Tabellen und deren Ausführung. Das beigefügte Skript besteht aus vier Teilen: 1.) Erstellung und Speicherung der Skripte in den drei Staging-Tabellen (realen Tabellen), 2.) Ausführung der Drop-FK-Skripte über einen Cursor, und zwar eines nach dem anderen, 3.) Verwendung von sp_MSforeachtable, um alle Tabellen in der Datenbank außer den drei Staging-Tabellen abzuschneiden, und 4.) Ausführung der Create-FK- und Check-FK-Skripte am Ende Ihres ETL-SSIS-Pakets.
Führen Sie den Teil der Skripterstellung in einer Execute SQL-Aufgabe in SSIS aus. Führen Sie den Teil "Drop FK Scripts ausführen" in einer zweiten Execute SQL-Aufgabe aus. Fügen Sie das Trunkierungsskript in eine dritte Execute SQL-Aufgabe ein und führen Sie dann alle anderen ETL-Prozesse aus, die Sie vor dem Anhängen der CREATE- und CHECK-Skripte in einer letzten Execute SQL-Aufgabe (oder zwei, falls gewünscht) am Ende Ihres Kontrollflusses durchführen müssen.
Die Speicherung der Skripte in echten Tabellen hat sich als unschätzbar wertvoll erwiesen, wenn die erneute Anwendung der Fremdschlüssel fehlschlägt, da Sie * aus sync_CreateFK auswählen, in Ihr Abfragefenster kopieren/einfügen, sie einzeln ausführen und die Datenprobleme beheben können, sobald Sie diejenigen gefunden haben, die bei der erneuten Anwendung fehlgeschlagen sind bzw. immer noch nicht angewendet werden.
Führen Sie das Skript nicht erneut aus, wenn es fehlschlägt, ohne sich zu vergewissern, dass Sie vorher alle Fremdschlüssel/Prüfungen erneut anwenden, da sonst höchstwahrscheinlich einige Erstellungs- und Prüf-FK-Skripte verloren gehen, da unsere Staging-Tabellen gelöscht und neu erstellt werden, bevor die auszuführenden Skripte erstellt werden.
----------------------------------------------------------------------------
1)
/*
Author: Denmach
DateCreated: 2014-04-23
Purpose: Generates SQL statements to DROP, ADD, and CHECK existing constraints for a
database. Stores scripts in tables on target database for execution. Executes
those stored scripts via independent cursors.
DateModified:
ModifiedBy
Comments: This will eliminate deletes and the T-log ballooning associated with it.
*/
DECLARE @schema_name SYSNAME;
DECLARE @table_name SYSNAME;
DECLARE @constraint_name SYSNAME;
DECLARE @constraint_object_id INT;
DECLARE @referenced_object_name SYSNAME;
DECLARE @is_disabled BIT;
DECLARE @is_not_for_replication BIT;
DECLARE @is_not_trusted BIT;
DECLARE @delete_referential_action TINYINT;
DECLARE @update_referential_action TINYINT;
DECLARE @tsql NVARCHAR(4000);
DECLARE @tsql2 NVARCHAR(4000);
DECLARE @fkCol SYSNAME;
DECLARE @pkCol SYSNAME;
DECLARE @col1 BIT;
DECLARE @action CHAR(6);
DECLARE @referenced_schema_name SYSNAME;
--------------------------------Generate scripts to drop all foreign keys in a database --------------------------------
IF OBJECT_ID('dbo.sync_dropFK') IS NOT NULL
DROP TABLE sync_dropFK
CREATE TABLE sync_dropFK
(
ID INT IDENTITY (1,1) NOT NULL
, Script NVARCHAR(4000)
)
DECLARE FKcursor CURSOR FOR
SELECT
OBJECT_SCHEMA_NAME(parent_object_id)
, OBJECT_NAME(parent_object_id)
, name
FROM
sys.foreign_keys WITH (NOLOCK)
ORDER BY
1,2;
OPEN FKcursor;
FETCH NEXT FROM FKcursor INTO
@schema_name
, @table_name
, @constraint_name
WHILE @@FETCH_STATUS = 0
BEGIN
SET @tsql = 'ALTER TABLE '
+ QUOTENAME(@schema_name)
+ '.'
+ QUOTENAME(@table_name)
+ ' DROP CONSTRAINT '
+ QUOTENAME(@constraint_name)
+ ';';
--PRINT @tsql;
INSERT sync_dropFK (
Script
)
VALUES (
@tsql
)
FETCH NEXT FROM FKcursor INTO
@schema_name
, @table_name
, @constraint_name
;
END;
CLOSE FKcursor;
DEALLOCATE FKcursor;
---------------Generate scripts to create all existing foreign keys in a database --------------------------------
----------------------------------------------------------------------------------------------------------
IF OBJECT_ID('dbo.sync_createFK') IS NOT NULL
DROP TABLE sync_createFK
CREATE TABLE sync_createFK
(
ID INT IDENTITY (1,1) NOT NULL
, Script NVARCHAR(4000)
)
IF OBJECT_ID('dbo.sync_createCHECK') IS NOT NULL
DROP TABLE sync_createCHECK
CREATE TABLE sync_createCHECK
(
ID INT IDENTITY (1,1) NOT NULL
, Script NVARCHAR(4000)
)
DECLARE FKcursor CURSOR FOR
SELECT
OBJECT_SCHEMA_NAME(parent_object_id)
, OBJECT_NAME(parent_object_id)
, name
, OBJECT_NAME(referenced_object_id)
, OBJECT_ID
, is_disabled
, is_not_for_replication
, is_not_trusted
, delete_referential_action
, update_referential_action
, OBJECT_SCHEMA_NAME(referenced_object_id)
FROM
sys.foreign_keys WITH (NOLOCK)
ORDER BY
1,2;
OPEN FKcursor;
FETCH NEXT FROM FKcursor INTO
@schema_name
, @table_name
, @constraint_name
, @referenced_object_name
, @constraint_object_id
, @is_disabled
, @is_not_for_replication
, @is_not_trusted
, @delete_referential_action
, @update_referential_action
, @referenced_schema_name;
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN
SET @tsql = 'ALTER TABLE '
+ QUOTENAME(@schema_name)
+ '.'
+ QUOTENAME(@table_name)
+ CASE
@is_not_trusted
WHEN 0 THEN ' WITH CHECK '
ELSE ' WITH NOCHECK '
END
+ ' ADD CONSTRAINT '
+ QUOTENAME(@constraint_name)
+ ' FOREIGN KEY (';
SET @tsql2 = '';
DECLARE ColumnCursor CURSOR FOR
SELECT
COL_NAME(fk.parent_object_id
, fkc.parent_column_id)
, COL_NAME(fk.referenced_object_id
, fkc.referenced_column_id)
FROM
sys.foreign_keys fk WITH (NOLOCK)
INNER JOIN sys.foreign_key_columns fkc WITH (NOLOCK) ON fk.[object_id] = fkc.constraint_object_id
WHERE
fkc.constraint_object_id = @constraint_object_id
ORDER BY
fkc.constraint_column_id;
OPEN ColumnCursor;
SET @col1 = 1;
FETCH NEXT FROM ColumnCursor INTO @fkCol, @pkCol;
WHILE @@FETCH_STATUS = 0
BEGIN
IF (@col1 = 1)
SET @col1 = 0;
ELSE
BEGIN
SET @tsql = @tsql + ',';
SET @tsql2 = @tsql2 + ',';
END;
SET @tsql = @tsql + QUOTENAME(@fkCol);
SET @tsql2 = @tsql2 + QUOTENAME(@pkCol);
--PRINT '@tsql = ' + @tsql
--PRINT '@tsql2 = ' + @tsql2
FETCH NEXT FROM ColumnCursor INTO @fkCol, @pkCol;
--PRINT 'FK Column ' + @fkCol
--PRINT 'PK Column ' + @pkCol
END;
CLOSE ColumnCursor;
DEALLOCATE ColumnCursor;
SET @tsql = @tsql + ' ) REFERENCES '
+ QUOTENAME(@referenced_schema_name)
+ '.'
+ QUOTENAME(@referenced_object_name)
+ ' ('
+ @tsql2 + ')';
SET @tsql = @tsql
+ ' ON UPDATE '
+
CASE @update_referential_action
WHEN 0 THEN 'NO ACTION '
WHEN 1 THEN 'CASCADE '
WHEN 2 THEN 'SET NULL '
ELSE 'SET DEFAULT '
END
+ ' ON DELETE '
+
CASE @delete_referential_action
WHEN 0 THEN 'NO ACTION '
WHEN 1 THEN 'CASCADE '
WHEN 2 THEN 'SET NULL '
ELSE 'SET DEFAULT '
END
+
CASE @is_not_for_replication
WHEN 1 THEN ' NOT FOR REPLICATION '
ELSE ''
END
+ ';';
END;
-- PRINT @tsql
INSERT sync_createFK
(
Script
)
VALUES (
@tsql
)
-------------------Generate CHECK CONSTRAINT scripts for a database ------------------------------
----------------------------------------------------------------------------------------------------------
BEGIN
SET @tsql = 'ALTER TABLE '
+ QUOTENAME(@schema_name)
+ '.'
+ QUOTENAME(@table_name)
+
CASE @is_disabled
WHEN 0 THEN ' CHECK '
ELSE ' NOCHECK '
END
+ 'CONSTRAINT '
+ QUOTENAME(@constraint_name)
+ ';';
--PRINT @tsql;
INSERT sync_createCHECK
(
Script
)
VALUES (
@tsql
)
END;
FETCH NEXT FROM FKcursor INTO
@schema_name
, @table_name
, @constraint_name
, @referenced_object_name
, @constraint_object_id
, @is_disabled
, @is_not_for_replication
, @is_not_trusted
, @delete_referential_action
, @update_referential_action
, @referenced_schema_name;
END;
CLOSE FKcursor;
DEALLOCATE FKcursor;
--SELECT * FROM sync_DropFK
--SELECT * FROM sync_CreateFK
--SELECT * FROM sync_CreateCHECK
---------------------------------------------------------------------------
2.)
-----------------------------------------------------------------------------------------------------------------
----------------------------execute Drop FK Scripts --------------------------------------------------
DECLARE @scriptD NVARCHAR(4000)
DECLARE DropFKCursor CURSOR FOR
SELECT Script
FROM sync_dropFK WITH (NOLOCK)
OPEN DropFKCursor
FETCH NEXT FROM DropFKCursor
INTO @scriptD
WHILE @@FETCH_STATUS = 0
BEGIN
--PRINT @scriptD
EXEC (@scriptD)
FETCH NEXT FROM DropFKCursor
INTO @scriptD
END
CLOSE DropFKCursor
DEALLOCATE DropFKCursor
--------------------------------------------------------------------------------
3.)
------------------------------------------------------------------------------------------------------------------
----------------------------Truncate all tables in the database other than our staging tables --------------------
------------------------------------------------------------------------------------------------------------------
EXEC sp_MSforeachtable 'IF OBJECT_ID(''?'') NOT IN
(
ISNULL(OBJECT_ID(''dbo.sync_createCHECK''),0),
ISNULL(OBJECT_ID(''dbo.sync_createFK''),0),
ISNULL(OBJECT_ID(''dbo.sync_dropFK''),0)
)
BEGIN TRY
TRUNCATE TABLE ?
END TRY
BEGIN CATCH
PRINT ''Truncation failed on''+ ? +''
END CATCH;'
GO
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------
----------------------------execute Create FK Scripts and CHECK CONSTRAINT Scripts---------------
----------------------------tack me at the end of the ETL in a SQL task-------------------------
-------------------------------------------------------------------------------------------------
DECLARE @scriptC NVARCHAR(4000)
DECLARE CreateFKCursor CURSOR FOR
SELECT Script
FROM sync_createFK WITH (NOLOCK)
OPEN CreateFKCursor
FETCH NEXT FROM CreateFKCursor
INTO @scriptC
WHILE @@FETCH_STATUS = 0
BEGIN
--PRINT @scriptC
EXEC (@scriptC)
FETCH NEXT FROM CreateFKCursor
INTO @scriptC
END
CLOSE CreateFKCursor
DEALLOCATE CreateFKCursor
-------------------------------------------------------------------------------------------------
DECLARE @scriptCh NVARCHAR(4000)
DECLARE CreateCHECKCursor CURSOR FOR
SELECT Script
FROM sync_createCHECK WITH (NOLOCK)
OPEN CreateCHECKCursor
FETCH NEXT FROM CreateCHECKCursor
INTO @scriptCh
WHILE @@FETCH_STATUS = 0
BEGIN
--PRINT @scriptCh
EXEC (@scriptCh)
FETCH NEXT FROM CreateCHECKCursor
INTO @scriptCh
END
CLOSE CreateCHECKCursor
DEALLOCATE CreateCHECKCursor
Finden Sie die Einschränkung
SELECT *
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('TABLE_NAME')
Führen Sie die von diesem SQL erzeugte SQL aus
SELECT
'ALTER TABLE ' + OBJECT_SCHEMA_NAME(parent_object_id) +
'.[' + OBJECT_NAME(parent_object_id) +
'] DROP CONSTRAINT ' + name
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('TABLE_NAME')
Safeway.
Hinweis: Lösung für das Löschen der Einschränkung hinzugefügt, so dass die Tabelle ohne Einschränkungsfehler gelöscht oder geändert werden kann.
147 Stimmen
Für Leute, die sich fragen, "warum" ich dies tun möchte: Es geht um eine Testumgebung, in der ich in der Lage sein möchte, Testdaten aus mehreren Tabellen zu entfernen und zu laden, ohne dass ich die Reihenfolge, in der die Daten geladen werden, pflegen und festlegen muss. Die Datenintegrität ist in diesem Szenario nicht so wichtig.
9 Stimmen
Hinweis: Wenn Sie die Tabelle TRUNCATE (löschen) möchten, müssen Sie die Beschränkungen tatsächlich aufheben.
0 Stimmen
@OutstandingBill Offensichtlich, dies funktioniert für TRUNCATE .
8 Stimmen
Es scheint seltsam, dass jemand diese Frage in einem Produktion Umwelt. Ein sehr häufiger Anwendungsfall sind Massenbeilagen. Wenn Sie eine selbstreferenzielle Tabelle haben, ist es manchmal extrem schwierig, eine Masseneinfügung so zu sortieren, dass die übergeordnete Zeile immer vor der untergeordneten Zeile eingefügt wird, also deaktivieren Sie die Einschränkung, fügen die Masseneinfügung ein und aktivieren die Einschränkung.
0 Stimmen
Außerdem haben Sie möglicherweise ein absichtlich denormalisiertes Schema mit redundanten Spalten an einigen Stellen (sei es aus Leistungs- oder anderen Gründen). Diese können dann mit FKs verknüpft werden, so dass sich aufgrund der Redundanz keine Fehler einschleichen können. Um jedoch einen dieser redundant gespeicherten Werte zu aktualisieren (was hoffentlich selten vorkommt), müssen Sie die FKs vorübergehend deaktivieren.