Einschränkungen vorübergehend deaktivieren (MS SQL)

208

Ich suche nach einer Möglichkeit, alle DB-Einschränkungen (z. B. Tabellenbeziehungen) vorübergehend zu deaktivieren.

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

Es wäre jedoch einfacher, wenn ich die Überprüfungsbeschränkungen vorübergehend deaktivieren und nach Abschluss der Operation wieder einschalten könnte.

Ist das möglich?

Maciej
quelle
3
Dies ist keine vollständige Kopie Ich möchte nur ausgewählte Tabellen zwischen
Maciej
Meine Sorge dabei ist, dass dies die Einschränkungen für alle außer Ihnen ausschaltet. Wenn Sie dies tun müssen, versetzen Sie die Datenbank zuerst in den Einzelbenutzermodus. Andernfalls können Probleme mit der Datenintegrität auftreten.
HLGEM
13
Liebe Leute aus der Zukunft: Sie können alle Einschränkungen in der Datenbank gleichzeitig deaktivieren und wieder aktivieren. siehe stackoverflow.com/a/161410
brichins
1
Vergessen Sie nicht, die Einschränkungen zu aktivieren, wenn Sie fertig sind!
Mike Christian
1
@NicolasBarbulesco fair genug; Ich ging aus sql-serverund sql-server-2005Tags. Der Link, den ich gegeben habe, ist für SQL Server, aber Sie können dasselbe in Oracle tun - siehe hier und hier . Sie können dies auch in PostgreSQL tun .
Brichins

Antworten:

214

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 können nicht deaktiviert werden. Dies sollte jedoch in Ordnung sein, wenn ich Sie richtig verstanden habe.

gbn
quelle
10
Dies ist jedoch nicht vorübergehend.
Nicolas Barbulesco
@NicolasBarbulesco: es kommt darauf an. Ja,
insofern
Diese Antwort ist nur die erste Hälfte einer Lösung. Ich habe nach einer einfachen Möglichkeit gesucht, Einschränkungen vorübergehend zu deaktivieren, und bin zu dem Schluss gekommen, dass sie unter Oracle nicht vorhanden sind.
Nicolas Barbulesco
Es ist nicht wahr, dass PKs und eindeutige Einschränkungen nicht deaktiviert werden können. Zumindest in einer neueren Version von SQL Server funktioniert es. Zum Beispiel: techonthenet.com/sql_server/primary_keys.php
Dejan
1
@NicolasBarbulesco auf Oracle? ALTER TABLE some_table DISABLE CONSTRAINT some_table_fk1; // mache einige Dinge, die die Einschränkungen verletzen würden ALTER TABLE some_table ENABLE CONSTRAINT some_table_fk1;
Steve Swinsburg
237
-- 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'
---------------------------------------------------------
Donal
quelle
1
@ kevinc nein. Solange Sie einverstanden sind, spielt es keine Rolle.
Po-ta-toe
2
Die Verwendung von Bezeichnern in Anführungszeichen ist meiner Meinung nach die ANSI-Standardeinstellung, was bedeutet, dass Sie sie nicht für Zeichenfolgen verwenden sollten. Hat nichts damit zu tun, konsequent zu sein. siehe stackoverflow.com/questions/1992314/…
kevinc
1
Danke für das Verfahren! Übrigens ist das korrekte Gehäuse "sp_MSforeachtable" (MS-Großbuchstaben). Vielen Dank!
Sielu
3
Dies sollte als die richtige Antwort markiert worden sein, da es die Frage vollständig beantwortet. Darüber hinaus enthielt @Donal eine Wildcard-Version, die für mich sehr hilfreich war.
Matt Jackson
2
Vielen Dank für die erneute Aktivierung. Besonders das Doppel, check checkdas viele Leute vergessen !!
Alex
57

Und wenn Sie überprüfen möchten, ob Sie Ihre Beziehungen NICHT unterbrochen und Waisenkinder eingeführt haben, nachdem Sie Ihre Schecks erneut aktiviert haben, d. H.

ALTER TABLE foo CHECK CONSTRAINT ALL

oder

ALTER TABLE foo CHECK CONSTRAINT FK_something

Dann können Sie zurücklaufen und ein Update für alle aktivierten Spalten durchführen, z. B.:

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

Und alle Fehler an diesem Punkt sind darauf zurückzuführen, dass die Einschränkungen nicht eingehalten werden.

Michael K. Campbell
quelle
11
Ein besserer Weg ist ALTER TABLE FOO MIT CHECK CHECK CONSTRAINT FK_something
Cody Konior
1
ALTER TABLE foo CHECK CONSTRAINT ALL oder ALTER TABLE foo CHECK CONSTRAINT FK_something aktiviert Einschränkungen, jedoch ohne Überprüfung der Daten. Dies bedeutet, dass die Einschränkung nicht vertrauenswürdig ist (is_no_trusted = 1, is_disabled = 0).
Bogdan Sahlean
0

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 ihre Tabellennamen sammelt. Als nächstes wird der Cursor geöffnet und die anfängliche FETCH-Anweisung ausgeführt. Diese FETCH-Anweisung liest die Daten der ersten Zeile in die lokalen Variablen @foreignKeyName und @tableName. Wenn Sie einen Cursor durchlaufen, können Sie @@ FETCH_STATUS auf den Wert 0 überprüfen, was darauf hinweist, dass der Abruf erfolgreich war. Dies bedeutet, dass sich die Schleife weiter vorwärts bewegt, sodass jeder aufeinanderfolgende Fremdschlüssel aus dem Rowset abgerufen werden kann. @@ FETCH_STATUS steht allen Cursorn 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 gibt den Status der letzten FETCH-Operation für die Verbindung wieder. Gültige Werte für @@ FETCH_STATUS sind:

0 = FETCH war erfolgreich
-1 = FETCH war nicht erfolgreich
-2 = Die abgerufene Zeile fehlt

Innerhalb der Schleife erstellt der Code den Befehl ALTER TABLE unterschiedlich, je nachdem, ob die Fremdschlüsseleinschränkung deaktiviert oder aktiviert werden soll (mithilfe des Schlüsselworts CHECK oder NOCHECK). Die Anweisung wird dann als Nachricht gedruckt, damit ihr Fortschritt beobachtet werden kann, und dann wird die Anweisung ausgeführt. Wenn alle Zeilen durchlaufen wurden, schließt die gespeicherte Prozedur den Cursor und gibt die Zuordnung frei.

Siehe Deaktivieren von Einschränkungen und Triggern im MSDN Magazine

0x49D1
quelle