Désactiver temporairement les contraintes (MS SQL)

208

Je cherche un moyen de désactiver temporairement toutes les contraintes de la base de données (par exemple, les relations de table).

J'ai besoin de copier (à l'aide des INSERT) les tables d'une base de données vers une autre base de données. Je sais que je peux y parvenir en exécutant les commandes dans le bon ordre (pour ne pas rompre les relations).

Mais ce serait plus facile si je pouvais désactiver temporairement la vérification des contraintes et la réactiver après la fin de l'opération.

Est-ce possible?

Maciej
la source
3
Ce n'est pas une copie complète Je veux juste copier les tables sélectionnées entre
Maciej
Ce qui m'inquiète, c'est que cela désactive les contraintes pour tout le monde, pas seulement pour vous. Si vous devez le faire, mettez d'abord la base de données en mode mono-utilisateur. Sinon, vous pouvez vous retrouver avec des problèmes d'intégrité des données.
HLGEM
13
Chers gens de The Future: Vous pouvez désactiver et réactiver toutes les contraintes de la base de données en même temps; voir stackoverflow.com/a/161410
brichins
1
N'oubliez pas d'activer les contraintes, une fois terminé!
Mike Christian
1
@NicolasBarbulesco assez juste; Je sortais des balises sql-serveret sql-server-2005. Le lien que j'ai donné est pour SQL Server, mais vous pouvez faire la même chose dans Oracle - voir ici et ici . Vous pouvez également le faire dans PostgreSQL .
brichins

Réponses:

214

Vous ne pouvez désactiver les contraintes FK et CHECK que dans SQL 2005+ . Voir ALTER TABLE

ALTER TABLE foo NOCHECK CONSTRAINT ALL

ou

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column

Les clés primaires et les contraintes uniques ne peuvent pas être désactivées, mais cela devrait être OK si je vous ai bien compris.

gbn
la source
10
Mais ce n'est pas temporaire.
Nicolas Barbulesco du
@NicolasBarbulesco: cela dépend. Oui, car vous pouvez les réactiver avec DROP / CREATE
gbn
Cette réponse n'est que la première moitié d'une solution. Je cherchais un moyen simple de désactiver temporairement les contraintes, et je suis arrivé à la conclusion qu'il n'existe pas, sur Oracle.
Nicolas Barbulesco
Il n'est pas vrai que les PK et la contrainte unique ne peuvent pas être désactivés. Au moins dans une version plus récente de SQL Server, cela fonctionne. Par exemple, voir: techonthenet.com/sql_server/primary_keys.php
Dejan
1
@NicolasBarbulesco sur Oracle? ALTER TABLE some_table DISABLE CONSTRAINT some_table_fk1; // fait des choses qui violeraient les contraintes 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
la source
1
@kevinc no. Tant que vous êtes constant, cela n'a pas d'importance.
Po-ta-toe
2
L'utilisation d'identificateurs entre guillemets est, je crois, le paramètre standard ANSI, ce qui signifie que vous ne devriez pas les utiliser pour les chaînes. N'a rien à voir avec la cohérence. voir stackoverflow.com/questions/1992314/…
kevinc
1
Merci pour la procédure! Et BTW, son boîtier correct est "sp_MSforeachtable" (MS en majuscules). Merci!
Sielu
3
Cela aurait dû être marqué comme la bonne réponse car il répond complètement à la question. Non seulement cela, mais @Donal comprenait une version générique qui m'a été très utile.
Matt Jackson
2
Merci pour le bit de réactivation. Surtout le double check checkque beaucoup oublient !!
Alex
57

Et, si vous voulez vérifier que vous N'AVEZ PAS brisé vos relations et introduit des orphelins, une fois que vous avez réarmé vos chèques, c'est-à-dire

ALTER TABLE foo CHECK CONSTRAINT ALL

ou

ALTER TABLE foo CHECK CONSTRAINT FK_something

alors vous pouvez revenir en arrière et faire une mise à jour sur toutes les colonnes cochées comme ceci:

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

Et toute erreur à ce stade sera due au non-respect des contraintes.

Michael K. Campbell
la source
11
Une meilleure façon est ALTER TABLE FOO AVEC CHECK CHECK CONSTRAINT FK_something
Cody Konior
1
ALTER TABLE foo CHECK CONSTRAINT ALL ou ALTER TABLE foo CHECK CONSTRAINT FK_something activera les contraintes mais sans vérifier les données et cela signifie que la contrainte ne sera pas approuvée (is_no_trusted = 1, is_disabled = 0).
Bogdan Sahlean
0

Désactivation et activation de toutes les clés étrangères

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

Tout d'abord, le curseur foreignKeyCursor est déclaré comme l'instruction SELECT qui rassemble la liste des clés étrangères et leurs noms de table. Ensuite, le curseur est ouvert et l'instruction FETCH initiale est exécutée. Cette instruction FETCH lira les données de la première ligne dans les variables locales @foreignKeyName et @tableName. Lorsque vous parcourez un curseur, vous pouvez vérifier @@ FETCH_STATUS pour une valeur de 0, ce qui indique que l'extraction a réussi. Cela signifie que la boucle continuera d'avancer afin qu'elle puisse obtenir chaque clé étrangère successive de l'ensemble de lignes. @@ FETCH_STATUS est disponible pour tous les curseurs de la connexion. Donc, si vous parcourez plusieurs curseurs, il est important de vérifier la valeur de @@ FETCH_STATUS dans l'instruction immédiatement après l'instruction FETCH. @@ FETCH_STATUS reflétera l'état de la dernière opération FETCH sur la connexion. Les valeurs valides pour @@ FETCH_STATUS sont:

0 = FETCH a réussi
-1 = FETCH a échoué
-2 = la ligne qui a été récupérée est manquante

À l'intérieur de la boucle, le code crée la commande ALTER TABLE différemment selon que l'intention est de désactiver ou d'activer la contrainte de clé étrangère (à l'aide du mot clé CHECK ou NOCHECK). L'instruction est ensuite imprimée sous forme de message afin que sa progression puisse être observée, puis l'instruction est exécutée. Enfin, lorsque toutes les lignes ont été itérées, la procédure stockée ferme et désalloue le curseur.

voir Désactivation des contraintes et des déclencheurs dans MSDN Magazine

0x49D1
la source