Desativar restrições temporariamente (MS SQL)

208

Estou procurando uma maneira de desativar temporariamente todas as restrições do banco de dados (por exemplo, relacionamentos de tabela).

Preciso copiar (usando INSERTs) as tabelas de um banco de dados para outro banco de dados. Eu sei que posso conseguir isso executando comandos na ordem correta (para não romper relacionamentos).

Mas seria mais fácil se eu pudesse desativar a verificação de restrições temporariamente e ligá-la novamente após o término da operação.

Isso é possível?

Maciej
fonte
3
Esta não é completa copiar Eu só quero para copiar tabelas selecionadas entre
Maciej
Minha preocupação em fazer isso é que isso desative as restrições para todos, não apenas para você. Se você deve fazer isso, coloque o banco de dados no modo de usuário único primeiro. Caso contrário, você pode acabar com problemas de integridade dos dados.
HLGEM 10/04/09
13
Caros funcionários do The Future: Você pode desativar e reativar todas as restrições no banco de dados de uma só vez; veja stackoverflow.com/a/161410
brichins
1
Não se esqueça de ativar as restrições, quando terminar!
Mike Christian
1
@NicolasBarbulesco justo o suficiente; Eu estava saindo das tags sql-servere sql-server-2005. O link que forneci é para o SQL Server, mas você pode fazer o mesmo no Oracle - veja aqui e aqui . Você também pode fazê-lo no PostgreSQL .
Brichins # 8/13

Respostas:

214

Você pode desativar as restrições FK e CHECK apenas no SQL 2005+ . Consulte ALTER TABLE

ALTER TABLE foo NOCHECK CONSTRAINT ALL

ou

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column

Chaves primárias e restrições exclusivas não podem ser desabilitadas, mas isso deve ser bom se eu entendi corretamente.

gbn
fonte
10
Mas isso não é temporário.
Nicolas Barbulesco
@NicolasBarbulesco: depende. Sim, é possível reativá-los com DROP / CREATE
gbn
Esta resposta é apenas a primeira metade de uma solução. Eu estava procurando uma maneira simples de desativar as restrições temporariamente e cheguei à conclusão de que não existe, no Oracle.
Nicolas Barbulesco 10/10
Não é verdade que PKs e restrições exclusivas não possam ser desabilitadas. Pelo menos na versão mais recente do SQL Server, ele funciona. Por exemplo, consulte: techonthenet.com/sql_server/primary_keys.php
Dejan
1
@NicolasBarbulesco no Oracle? ALTER TABLE some_table DISABLE CONSTRAINT some_table_fk1; // faz algumas coisas que violariam as restrições ALTER TABLE some_table ENABLE CONSTRAINT some_table_fk1;
22815 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
fonte
1
@kevinc no. Contanto que você seja consistente, não importa.
Po-ta-toe
2
Usar identificadores entre aspas é, acredito, a configuração padrão ANSI, o que significa que você não deve usá-los para seqüências de caracteres. Não tem nada a ver com ser consistente. veja stackoverflow.com/questions/1992314/…
kevinc 8/16
1
Obrigado pelo procedimento! E, BTW, a caixa correta é "sp_MSforeachtable" (MS maiúscula). Obrigado!
Sielu # 28/17
3
Isso deveria ter sido marcado como a resposta correta, pois responde completamente à pergunta. Não só isso, mas o @Donal incluiu uma versão curinga que foi muito útil para mim.
Matt Jackson
2
Obrigado pelo bit de reativação. Especialmente o dobro check checkque muitas pessoas esquecem !!
Alex
57

E, se você deseja verificar se você NÃO rompeu seus relacionamentos e apresentou órfãos, depois de rearmar seus cheques, ou seja,

ALTER TABLE foo CHECK CONSTRAINT ALL

ou

ALTER TABLE foo CHECK CONSTRAINT FK_something

então você pode voltar e fazer uma atualização em qualquer coluna marcada, como:

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

E quaisquer erros nesse ponto ocorrerão devido à falha em atender às restrições.

Michael K. Campbell
fonte
11
Uma maneira melhor é ALTER TABLE FOO COM CHECK CHECK CONSTRAINT FK_something
Cody Konior 27/03
1
ALTER TABLE foo CHECK CONSTRAINT ALL ou ALTER TABLE foo CHECK CONSTRAINT FK_something habilitará restrições, mas sem verificar dados, e isso significa que a restrição não será confiável (is_no_trusted = 1, is_disabled = 0).
Bogdan Sahlean
0

Desabilitando e habilitando todas as chaves estrangeiras

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

Primeiro, o cursor ForeignKeyCursor é declarado como a instrução SELECT que reúne a lista de chaves estrangeiras e seus nomes de tabela. Em seguida, o cursor é aberto e a instrução FETCH inicial é executada. Esta instrução FETCH lerá os dados da primeira linha nas variáveis ​​locais @foreignKeyName e @tableName. Ao percorrer um cursor, você pode verificar o @@ FETCH_STATUS para um valor 0, o que indica que a busca foi bem-sucedida. Isso significa que o loop continuará avançando para obter cada chave estrangeira sucessiva do conjunto de linhas. @@ FETCH_STATUS está disponível para todos os cursores na conexão. Portanto, se você estiver percorrendo vários cursores, é importante verificar o valor de @@ FETCH_STATUS na instrução imediatamente após a instrução FETCH. @@ FETCH_STATUS refletirá o status da operação FETCH mais recente na conexão. Os valores válidos para @@ FETCH_STATUS são:

0 = FETCH foi bem-sucedido
-1 = FETCH não teve sucesso
-2 = a linha que foi buscada está ausente

Dentro do loop, o código cria o comando ALTER TABLE de maneira diferente, dependendo se a intenção é desativar ou ativar a restrição de chave estrangeira (usando a palavra-chave CHECK ou NOCHECK). A instrução é impressa como uma mensagem para que seu progresso possa ser observado e, em seguida, a instrução é executada. Finalmente, quando todas as linhas foram iteradas, o procedimento armazenado fecha e desaloca o cursor.

consulte Desativando restrições e disparadores da MSDN Magazine

0x49D1
fonte