167

Sto cercando un modo per disattivare temporaneamente tutti i vincoli di DB (ad es. Le relazioni tra tabelle).Disattiva temporaneamente i vincoli (MS SQL)

Ho bisogno di copiare (utilizzando INSERT) le tabelle di un DB in 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 riaccenderlo dopo l'operazione.

È possibile?

+3

Questo non è completa copia voglio solo copiare tabelle selezionate tra – Maciej

+13

Cari persone dal futuro: è possibile disattivare e riattivare tutti i vincoli presenti nel database in una sola volta; vedi http://stackoverflow.com/a/161410 – brichins

+1

Non dimenticare di abilitare i vincoli, una volta terminato! –

risposta

184

È 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 

chiavi primarie e vincoli univoci non può essere disattivata, ma questo dovrebbe essere OK se ti ho capito bene.

+1

Ma questo non è temporaneo. –

+0

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

+0

Questa risposta è solo la prima metà di una soluzione. Stavo cercando un modo semplice per disattivare temporaneamente i vincoli e ho raggiunto la conclusione che non esiste, su Oracle. –

55

E, se si desidera verificare che non si è rotto le relazioni e ha introdotto gli orfani, una volta che avete ri-armati vostri controlli, vale a dire

ALTER TABLE foo CHECK CONSTRAINT ALL 

o

ALTER TABLE foo CHECK CONSTRAINT FK_something 

allora si può eseguire di nuovo e fare un aggiornamento su qualsiasi colonne verificate in questo modo:

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

E eventuali errori a al punto sarà dovuto al mancato rispetto dei vincoli.

+9

Un modo migliore è ALTER TABLE FOO WITH CHECK CHECK CONSTRAINT FK_qualcosa –

+1

ALTER TABLE foo CONTROLLA CONSTRAINT ALL o ALTER TABLE foo CONSEGNA CONTROLLO FK_qualcosa abilita i vincoli ma senza verificare i dati e questo significa che il vincolo non sarà attendibile (is_no_trusted = 1, is_disabled = 0). –

2

Disattivazione e attivazione 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 istruzione SELECT che raccoglie l'elenco di chiavi esterne e i relativi nomi di tabelle. 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 esegue il ciclo attraverso un cursore , è possibile controllare il @@ FETCH_STATUS per un valore pari a 0, che indica che il recupero ha avuto esito positivo. Ciò significa che il ciclo sarà continuare ad avanzare in modo da poter ottenere ogni chiave esterna successiva dal set di righe. @@ FETCH_STATUS è disponibile per tutti i cursori sulla connessione .Quindi, se siete loop attraverso molteplici cursori, è importante controllare il valore di @@ FETCH_STATUS nella dichiarazione subito dopo la dichiarazione FETCH. @@ FETCH_STATUS riflette lo lo stato dell'operazione FETCH più recente sulla connessione. valori validi per @@ FETCH_STATUS sono:

0 = FETCH avuto successo
-1 = FETCH non ha avuto successo
-2 = riga che è stato recuperato manca

All'interno del ciclo, il codice costruisce il comando TABLE diverso ALTER a seconda che l'intenzione è quella di disabilitare o abilitare l'estero vincolo di chiave (utilizzando il CHECK o NOCHECK parola chiave). L'affermazione è quindi stampato come un messaggio in modo il suo progresso può essere osservato e quindi viene eseguita l'istruzione . Infine, quando tutte le righe sono state ripetute da a, la stored procedure si chiude e rilascia il cursore.

vedere 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

Penso che le chiamate alle stored procedure debbano avere virgolette singole? – kevinc

+1

@kevinc no. Finché sei un consitatore non importa. –

+2

L'uso degli identificatori tra virgolette è 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 http://stackoverflow.com/questions/1992314/che-è-differenza-differente-e-double-quotes-in-sql – kevinc