Desactivar restricciones temporalmente (MS SQL)

208

Estoy buscando una manera de desactivar temporalmente todas las restricciones de DB (por ejemplo, relaciones de tabla).

Necesito copiar (usando INSERTs) las tablas de un DB a otro DB. Sé que puedo lograrlo ejecutando comandos en el orden correcto (para no romper relaciones).

Pero sería más fácil si pudiera desactivar las restricciones de verificación temporalmente y volver a activarlo después de que finalice la operación.

es posible?

Maciej
fuente
3
Esta no es una copia completa, solo quiero copiar las tablas seleccionadas entre
Maciej
Mi preocupación por hacer esto es que esto apaga las restricciones para todos, no solo para ti. Si debe hacer esto, coloque primero la base de datos en modo de usuario único. De lo contrario, puede terminar con problemas de integridad de datos.
HLGEM
13
Queridas personas de The Future: puede deshabilitar y volver a habilitar todas las restricciones en la base de datos a la vez; ver stackoverflow.com/a/161410
brichins
1
¡No olvides habilitar las restricciones cuando hayas terminado!
Mike Christian
1
@NicolasBarbulesco bastante justo; Iba de los sql-servery sql-server-2005las etiquetas. El enlace que proporcioné es para SQL Server, pero puede hacer lo mismo en Oracle: consulte aquí y aquí . También puedes hacerlo en PostgreSQL .
brichins

Respuestas:

214

Puede deshabilitar las restricciones FK y CHECK solo en SQL 2005+ . Ver ALTER TABLE

ALTER TABLE foo NOCHECK CONSTRAINT ALL

o

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column

Las claves primarias y las restricciones únicas no se pueden deshabilitar, pero esto debería estar bien si te he entendido correctamente.

gbn
fuente
10
Pero esto no es temporal.
Nicolas Barbulesco
@NicolasBarbulesco: depende. Sí lo es, ya que puedes volver a habilitarlos con DROP / CREATE
gbn
Esta respuesta es solo la primera mitad de una solución. Estaba buscando una manera simple de desactivar temporalmente las restricciones, y he llegado a la conclusión de que no existe, en Oracle.
Nicolas Barbulesco
No es cierto que las PK y la restricción única no se puedan deshabilitar. Al menos en la versión más reciente de SQL Server funciona. Por ejemplo, consulte: techonthenet.com/sql_server/primary_keys.php
Dejan,
1
@NicolasBarbulesco en Oracle? ALTER TABLE some_table DISABLE CONSTRAINT some_table_fk1; // hacer algunas cosas que violarían las restricciones 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
fuente
1
@kevinc no. Mientras seas constante no importa.
Po-ta-toe
2
El uso de identificadores entre comillas es la configuración estándar ANSI, lo que significa que no debe usarlos para cadenas. No tiene nada que ver con ser consistente. ver stackoverflow.com/questions/1992314/…
kevinc
1
Gracias por el procedimiento! Y, por cierto, su carcasa correcta es "sp_MSforeachtable" (MS en mayúscula). ¡Gracias!
Sielu
3
Esto debería haber sido marcado como la respuesta correcta, ya que responde la pregunta por completo. No solo eso, sino que @Donal incluyó una versión comodín que fue muy útil para mí.
Matt Jackson
2
Gracias por el bit de reactivación. ¡Especialmente el doble check checkque mucha gente olvida!
Alex
57

Y, si desea verificar que NO HA roto sus relaciones y presentado huérfanos, una vez que haya armado sus cheques, es decir

ALTER TABLE foo CHECK CONSTRAINT ALL

o

ALTER TABLE foo CHECK CONSTRAINT FK_something

entonces puede volver a ejecutar y hacer una actualización en cualquier columna marcada de esta manera:

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

Y cualquier error en ese punto se deberá al incumplimiento de las restricciones.

Michael K. Campbell
fuente
11
Una mejor manera es ALTERAR MESA FOO CON CHECK CHECK CONSTRAINT FK_something
Cody Konior
1
ALTER TABLE foo CHECK CONSTRAINT ALL o ALTER TABLE foo CHECK CONSTRAINT FK_something habilitará restricciones pero sin verificar los datos y esto significa que la restricción no será confiable (is_no_trusted = 1, is_disabled = 0).
Bogdan Sahlean
0

Deshabilitar y habilitar todas las claves foráneas

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

Primero, el cursor foreignKeyCursor se declara como la instrucción SELECT que recopila la lista de claves foráneas y sus nombres de tabla. A continuación, se abre el cursor y se ejecuta la instrucción FETCH inicial. Esta instrucción FETCH leerá los datos de la primera fila en las variables locales @foreignKeyName y @tableName. Al recorrer un cursor, puede verificar @@ FETCH_STATUS para un valor de 0, lo que indica que la recuperación fue exitosa. Esto significa que el bucle continuará avanzando para que pueda obtener cada clave externa sucesiva del conjunto de filas. @@ FETCH_STATUS está disponible para todos los cursores en la conexión. Entonces, si está recorriendo varios cursores, es importante verificar el valor de @@ FETCH_STATUS en la declaración que sigue inmediatamente a la declaración FETCH. @@ FETCH_STATUS reflejará el estado de la operación FETCH más reciente en la conexión. Los valores válidos para @@ FETCH_STATUS son:

0 = FETCH fue exitoso
-1 = FETCH no fue exitoso
-2 = falta la fila que fue recuperada

Dentro del bucle, el código crea el comando ALTER TABLE de manera diferente dependiendo de si la intención es deshabilitar o habilitar la restricción de clave externa (usando la palabra clave CHECK o NOCHECK). La declaración se imprime como un mensaje para que se pueda observar su progreso y luego se ejecuta la declaración. Finalmente, cuando se han iterado todas las filas, el procedimiento almacenado cierra y desasigna el cursor.

ver Deshabilitar restricciones y disparadores de la revista MSDN

0x49D1
fuente