Disattiva temporaneamente i vincoli (MS SQL)


213

Sto cercando un modo per disattivare temporaneamente tutti i vincoli del DB (ad esempio le relazioni tra tabelle).

Ho bisogno di copiare (utilizzando INSERT) le tabelle di un DB su un altro DB. So che posso ottenerlo eseguendo i comandi nell'ordine corretto (per non interrompere le relazioni).

Ma sarebbe più facile se potessi disattivare temporaneamente il controllo dei vincoli e riattivarlo al termine dell'operazione.

È possibile?


3
Questa non è una copia completa, voglio solo copiare le tabelle selezionate tra
Maciej

La mia preoccupazione nel fare questo è che questo disattivi i vincoli per tutti, non solo per te. Se è necessario eseguire questa operazione, mettere prima il database in modalità utente singolo. Altrimenti puoi finire per problemi di integrità dei dati.
HLGEM

13
Care persone del futuro: potete disattivare e riattivare contemporaneamente tutti i vincoli nel database; vedi stackoverflow.com/a/161410
brichins

1
Non dimenticare di abilitare i vincoli, quando hai finito!
Mike Christian

1
@NicolasBarbulesco abbastanza giusto; Stavo disattivando i tag sql-servere sql-server-2005. Il collegamento che ho fornito è per SQL Server, ma puoi fare la stessa cosa in Oracle: guarda qui e qui . Puoi farlo anche in PostgreSQL .
brichins

Risposte:


218

È possibile disabilitare i vincoli FK e CHECK solo in SQL 2005+ . Vedi ALTER TABLE

ALTER TABLE foo NOCHECK CONSTRAINT ALL

o

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column

Le chiavi primarie e i vincoli univoci non possono essere disabilitati, ma dovrebbe andare bene se ti ho capito correttamente.


10
Ma questo non è temporaneo.
Nicolas Barbulesco

@NicolasBarbulesco: dipende. Sì, è possibile riattivarli con DROP / CREATE
gbn

Questa risposta è solo la prima metà di una soluzione. Stavo cercando un modo semplice per disattivare temporaneamente i vincoli e sono giunto alla conclusione che non esiste su Oracle.
Nicolas Barbulesco

Non è vero che le PK e il vincolo univoco non possono essere disabilitati. Almeno nella versione più recente di SQL Server funziona. Ad esempio, vedere: techonthenet.com/sql_server/primary_keys.php
Dejan

1
@NicolasBarbulesco su Oracle? ALTER TABLE some_table DISABLE CONSTRAINT some_table_fk1; // fa alcune cose che violerebbero i vincoli ALTER TABLE some_table ENABLE CONSTRAINT some_table_fk1;
Steve Swinsburg

247
-- 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'
---------------------------------------------------------

1
@kevinc no. Finché sei coerente, non importa.
Po-ta-toe

2
L'uso di identificatori tra virgolette è, credo, l'impostazione standard ANSI, il che significa che non dovresti usarli per le stringhe. Non ha nulla a che fare con l'essere coerenti. vedi stackoverflow.com/questions/1992314/…
kevinc

1
Grazie per la procedura! E, a proposito, il case corretto è "sp_MSforeachtable" (MS maiuscolo). Grazie!
Sielu

3
Dovrebbe essere stata contrassegnata come risposta corretta poiché risponde completamente alla domanda. Non solo, ma @Donal ha incluso una versione con caratteri jolly che è stata molto utile per me.
Matt Jackson

2
Grazie per il bit di riattivazione. Soprattutto il doppio check checkche molte persone dimenticano !!
Alex

57

E, se vuoi verificare che NON HAI interrotto le tue relazioni e introdotto orfani, una volta che hai riarmato i tuoi assegni, ovvero

ALTER TABLE foo CHECK CONSTRAINT ALL

o

ALTER TABLE foo CHECK CONSTRAINT FK_something

quindi puoi tornare indietro e fare un aggiornamento su qualsiasi colonna selezionata in questo modo:

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

E qualsiasi errore a quel punto sarà dovuto al mancato rispetto dei vincoli.


11
Un modo migliore è ALTER TABLE FOO WITH CHECK CHECK CONSTRAINT FK_something
Cody Konior

1
ALTER TABLE foo CHECK CONSTRAINT ALL o ALTER TABLE foo CHECK CONSTRAINT FK_something abiliterà i vincoli ma senza controllare i dati e questo significa che il vincolo non sarà attendibile (is_no_trusted = 1, is_disabled = 0).
Bogdan Sahlean


0

Disattivazione e attivazione di tutte le chiavi esterne

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

Innanzitutto, il cursore foreignKeyCursor viene dichiarato come l'istruzione SELECT che raccoglie l'elenco delle chiavi esterne e dei relativi nomi di tabella. Successivamente, il cursore viene aperto e viene eseguita l'istruzione FETCH iniziale. Questa istruzione FETCH leggerà i dati della prima riga nelle variabili locali @foreignKeyName e @tableName. Quando si scorre un cursore, è possibile controllare @@ FETCH_STATUS per un valore di 0, che indica che il recupero è riuscito. Ciò significa che il ciclo continuerà ad andare avanti in modo che possa ottenere ogni chiave esterna successiva dal set di righe. @@ FETCH_STATUS è disponibile per tutti i cursori sulla connessione. Quindi, se stai scorrendo più cursori, è importante controllare il valore di @@ FETCH_STATUS nell'istruzione immediatamente successiva all'istruzione FETCH. @@ FETCH_STATUS rifletterà lo stato dell'operazione FETCH più recente sulla connessione. I valori validi per @@ FETCH_STATUS sono:

0 = FETCH ha avuto successo
-1 = FETCH non ha avuto successo
-2 = la riga che è stata recuperata è mancante

All'interno del ciclo, il codice crea il comando ALTER TABLE in modo diverso a seconda che si intenda disabilitare o abilitare il vincolo di chiave esterna (utilizzando la parola chiave CHECK o NOCHECK). L'istruzione viene quindi stampata come messaggio in modo che sia possibile osservarne il progresso e quindi viene eseguita l'istruzione. Infine, quando tutte le righe sono state iterate, la stored procedure si chiude e rilascia il cursore.

vedere Disattivazione di vincoli e trigger da MSDN Magazine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.