167

Ich suche nach einer Möglichkeit, alle DB-Einschränkungen vorübergehend zu deaktivieren (zB Tabellenbeziehungen).Einschränkungen temporär ausschalten (MS SQL)

Ich muss die Tabellen einer DB in eine andere DB kopieren (mit INSERTs). Ich weiß, dass ich das erreichen kann, indem ich Befehle in der richtigen Reihenfolge ausführe (um Beziehungen nicht zu unterbrechen).

Aber es wäre einfacher, wenn ich die Einschränkungen vorübergehend deaktivieren und nach dem Ende der Operation wieder einschalten könnte.

Ist das möglich?

+3

Dies ist keine vollständige Kopie Ich möchte nur aus der Zukunft ausgewählte Tabellen zwischen – Maciej

+13

Lieb Leuten kopieren: Sie deaktivieren und wieder aktivieren alle Einschränkungen in der Datenbank auf einmal; siehe http://StackOverflow.com/a/161410 – brichins

+1

Vergessen Sie nicht, die Einschränkungen zu aktivieren, wenn Sie fertig sind! –

Antwort

184

Sie können FK und CHECK-Einschränkungen nur in SQL 2005+ deaktivieren. Siehe ALTER TABLE

ALTER TABLE foo NOCHECK CONSTRAINT ALL 

oder

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column 

Primärschlüssel und eindeutige Einschränkungen nicht deaktiviert werden kann, aber das sollte in Ordnung sein, wenn ich Sie richtig verstanden habe.

+1

Aber das ist nicht vorübergehend. –

+0

@NicolasBarbulesco: es kommt darauf an. Ja ist es, in dem Sie sie mit DROP/CREATE wieder aktivieren können – gbn

+0

Diese Antwort ist nur die erste Hälfte einer Lösung. Ich war auf der Suche nach einer einfachen Möglichkeit, Constraints vorübergehend auszuschalten, und ich bin zu dem Schluss gekommen, dass es auf Oracle nicht existiert. –

55

Und, wenn Sie überprüfen möchten, dass Sie Ihre Beziehungen nicht gebrochen haben und eingeführt Waisen, sobald Sie Ihre Schecks wieder bewaffnet, dh

ALTER TABLE foo CHECK CONSTRAINT ALL 

oder

ALTER TABLE foo CHECK CONSTRAINT FK_something 

dann Sie kann zurücklaufen und eine Aktualisierung gegen irgendwelche überprüften Spalten wie folgt durchführen:

UPDATE myUpdatedTable SET someCol = someCol, fkCol = fkCol, etc = etc 

Und irgendwelche Fehler an th bei Punkt wird aufgrund der Nichterfüllung der Einschränkungen sein.

+9

Ein besserer Weg ist ALTER TABLE FOO MIT CHECK CHECK CONSTRAINT FK_something –

+1

ALTER TABLE foo CHECK CONSTRAINT ALL oder ALTER TABLE foo CHECK CONSTRAINT FK_something aktiviert Constraints, aber ohne Daten zu prüfen. Dies bedeutet, dass Constraint nicht vertrauenswürdig ist (is_no_trusted = 1, is_disabled = 0). –

16

Sie können alle Datenbankeinschränkungen in einem einzigen SQL-Befehl tatsächlich deaktivieren und sie wieder aktivieren, indem sie einen anderen einzelnen Befehl aufrufen. Siehe:

Ich arbeite derzeit mit SQL Server 2005, aber ich bin mir fast sicher, dass dieser Ansatz mit SQL 2000 und arbeitete

2

Deaktivieren und Aktivieren aller Fremdschlüssel

CREATE PROCEDURE pr_Disable_Triggers_v2 
    @disable BIT = 1 
AS 
    DECLARE @sql VARCHAR(500) 
     , @tableName VARCHAR(128) 
     , @tableSchema VARCHAR(128) 

    -- List of all tables 
    DECLARE triggerCursor CURSOR FOR 
     SELECT t.TABLE_NAME AS TableName 
      , t.TABLE_SCHEMA AS TableSchema 
     FROM INFORMATION_SCHEMA.TABLES t 
     ORDER BY t.TABLE_NAME, t.TABLE_SCHEMA 

    OPEN triggerCursor 
    FETCH NEXT FROM triggerCursor INTO @tableName, @tableSchema 
    WHILE (@@FETCH_STATUS = 0) 
    BEGIN 

     SET @sql = 'ALTER TABLE ' + @tableSchema + '.[' + @tableName + '] ' 
     IF @disable = 1 
      SET @sql = @sql + ' DISABLE TRIGGER ALL' 
     ELSE 
      SET @sql = @sql + ' ENABLE TRIGGER ALL' 

     PRINT 'Executing Statement - ' + @sql 
     EXECUTE (@sql) 

     FETCH NEXT FROM triggerCursor INTO @tableName, @tableSchema 

    END 

    CLOSE triggerCursor 
    DEALLOCATE triggerCursor 

Zunächst wird der foreignKeyCursor-Cursor als SELECT-Anweisung deklariert, die die Liste der Fremdschlüssel und ihrer Tabellennamen sammelt. Als nächstes wird der Cursor geöffnet und die erste FETCH-Anweisung ausgeführt. Diese FETCH-Anweisung liest die Daten der ersten Zeile in die lokalen Variablen @foreignKeyName und @tableName. Beim Durchlaufen eines -Cursors können Sie den @@ FETCH_STATUS auf einen Wert von 0 überprüfen, wobei angibt, dass der Abruf erfolgreich war. Dies bedeutet, dass die Schleife weiterhin vorwärts bewegt wird, so dass es jeden folgenden Fremdschlüssel aus dem Rowset erhalten kann. @@ FETCH_STATUS steht allen Cursorn auf der -Verbindung zur Verfügung.Wenn Sie also mehrere Cursor durchlaufen, ist es wichtig, den Wert von @@ FETCH_STATUS in der Anweisung unmittelbar nach der FETCH-Anweisung zu überprüfen. @@ FETCH_STATUS zeigt den Status für die letzte FETCH-Operation auf der Verbindung an. Gültige Werte für @@ FETCH_STATUS sind:

0 = FETCH erfolgreich war
-1 = FETCH nicht erfolgreich war
-2 = der Zeile, die abgerufen wurde

Innerhalb der Schleife fehlt, baut sich der Code der ALTER TABLE-Befehl unterschiedlich je nachdem, ob die Absicht ist, die fremde -Schlüsseleinschränkung zu deaktivieren oder zu aktivieren (mithilfe des Schlüsselworts CHECK oder NOCHECK). Die Anweisung wird dann als eine Nachricht gedruckt, so dass der Fortschritt beobachtet werden kann und dann die Anweisung ausgeführt wird. Wenn schließlich alle Zeilen durchlaufen wurden, wird die gespeicherte Prozedur geschlossen und die Zuordnung aufgehoben.

siehe Disabling Constraints and Triggers from MSDN Magazine

137
-- Disable the constraints on a table called tableName: 
ALTER TABLE tableName NOCHECK CONSTRAINT ALL 

-- Re-enable the constraints on a table called tableName: 
ALTER TABLE tableName WITH CHECK CHECK CONSTRAINT ALL 
--------------------------------------------------------- 

-- Disable constraints for all tables: 
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all' 

-- Re-enable constraints for all tables: 
EXEC sp_msforeachtable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all' 
--------------------------------------------------------- 
+0

Ich denke, Ihre gespeicherten Prozeduraufrufe sollten einfache Anführungszeichen haben? – kevinc

+1

@kevinc nein. Solange es dir wichtig ist, ist es egal. –

+2

Die Verwendung von Bezeichnern in Anführungszeichen ist die ANSI-Standardeinstellung, was bedeutet, dass Sie sie nicht für Zeichenfolgen verwenden sollten. Hat nichts damit zu tun, konsequent zu sein. siehe http://stackoverflow.com/questions/1992314/what-is-the-difference-between-single-and-double-quotes-in-sql – kevinc