¿Qué es una RESTRICCIÓN CON CHECK CHECK?

18

Tengo algunos T-SQL autogenerados, que probablemente sean válidos, pero realmente no entiendo.

ALTER TABLE [dbo].[MyTable]
WITH CHECK
CHECK CONSTRAINT [My_FORIEGN_KEY];

Sé lo que es una restricción de clave externa, pero ¿cuál es el CHECK CHECK?

BanksySan
fuente

Respuestas:

27

La página de documentación de MSDN ALTER TABLEexplica esto:

  • ALTER TABLE: modifica la estructura de la tabla
    (y algunas de las posibles acciones / modificaciones son):
    • CHECK CONSTRAINT ..: habilitar la restricción
    • NOCHECK CONSTRAINT ..: deshabilitar la restricción
      También hay pasos opcionales adicionales que se deben realizar al crear / habilitar / deshabilitar una restricción:
      • WITH CHECK: compruebe la restricción también
      • WITH NOCHECK: no verifique la restricción

En sus palabras:

| [ WITH { CHECK | NOCHECK } ] { CHECK | NOCHECK } CONSTRAINT   
    { ALL | constraint_name [ ,...n ] }

...

WITH CHECK | WITH NOCHECK Especifica si los datos de la tabla se validan o no contra una restricción FOREIGN KEYo CHECKrestricción recientemente agregada o reactivada . Si no se especifica, WITH CHECKse supone para nuevas restricciones, yWITH NOCHECK se asume para restricciones reactivadas.

Si no desea verificar nuevas restricciones CHECKo FOREIGN KEYrestricciones contra los datos existentes, use WITH NOCHECK. No recomendamos hacer esto, excepto en casos excepcionales. La nueva restricción se evaluará en todas las actualizaciones de datos posteriores. Cualquier violación de restricciones que se suprima WITH NOCHECKcuando se agrega la restricción puede provocar que las actualizaciones futuras fallen si actualizan filas con datos que no cumplen con la restricción.

El optimizador de consultas no considera las restricciones que se definen WITH NOCHECK. Dichas restricciones se ignoran hasta que se vuelven a habilitar mediante la ALTER TABLEtabla WITH CHECK CHECK CONSTRAINT ALL.

...

{ CHECK | NOCHECK } CONSTRAINT
Especifica que restricint_name está habilitado o deshabilitado. Esta opción solo se puede usar con FOREIGN KEYy CHECKrestricciones. Cuando NOCHECKse especifica, la restricción se deshabilita y las futuras inserciones o actualizaciones de la columna no se validan en función de las condiciones de restricción. DEFAULT, PRIMARY KEYY UNIQUElas limitaciones no se puede desactivar.

Prueba en dbfiddle :

CREATE TABLE a (aid INT PRIMARY KEY);

VAMOS

INSERT INTO a (aid)
VALUES (1), (2), (3) ;

VAMOS

3 filas afectadas
CREATE TABLE b 
( aid INT,
  bid INT PRIMARY KEY,
  CONSTRAINT [My_FORIEGN_KEY]
    FOREIGN KEY (aid) REFERENCES a (aid)
) ;

VAMOS

INSERT INTO b (aid, bid)
VALUES
  (1, 11),
  (1, 12),
  (2, 21), 
  (3, 31) ;

VAMOS

4 filas afectadas
INSERT INTO b (aid, bid)
VALUES
  (6, 61),
  (6, 62) ;

VAMOS

Msg 547 Nivel 16 Estado 0 Línea 1
La instrucción INSERT entró en conflicto con la restricción FOREIGN KEY "My_FORIEGN_KEY". El conflicto se produjo en la base de datos "fiddle_792fce5de09f42908c3a0f91421f3522", tabla "dbo.a", columna 'ayuda'.
Msg 3621 Nivel 0 Estado 0 Línea 1
La instrucción se ha terminado.
SELECT * FROM b ;

VAMOS

ayuda | oferta
-: | -:
  1 | 11
  1 | 12
  2 | 21
  3 | 31
ALTER TABLE b NOCHECK CONSTRAINT [My_FORIEGN_KEY];   --disable

VAMOS

INSERT INTO b (aid, bid)
VALUES
  (4, 41),
  (4, 42) ;

VAMOS

2 filas afectadas
SELECT * FROM b ;

VAMOS

ayuda | oferta
-: | -:
  1 | 11
  1 | 12
  2 | 21
  3 | 31
  4 | 41
  4 | 42
ALTER TABLE b WITH NOCHECK CHECK CONSTRAINT [My_FORIEGN_KEY];  
-- enable constraint without checking existing data

VAMOS

SELECT * FROM b ;

VAMOS

ayuda | oferta
-: | -:
  1 | 11
  1 | 12
  2 | 21
  3 | 31
  4 | 41
  4 | 42
INSERT INTO b (aid, bid)
VALUES
  (6, 61),
  (6, 62) ;

VAMOS

Msg 547 Nivel 16 Estado 0 Línea 1
La instrucción INSERT entró en conflicto con la restricción FOREIGN KEY "My_FORIEGN_KEY". El conflicto se produjo en la base de datos "fiddle_792fce5de09f42908c3a0f91421f3522", tabla "dbo.a", columna 'ayuda'.
Msg 3621 Nivel 0 Estado 0 Línea 1
La instrucción se ha terminado.
SELECT * FROM b ;

VAMOS

ayuda | oferta
-: | -:
  1 | 11
  1 | 12
  2 | 21
  3 | 31
  4 | 41
  4 | 42
ALTER TABLE b WITH CHECK CHECK CONSTRAINT [My_FORIEGN_KEY];  
-- check existing data and enable constraint 

VAMOS

Msg 547 Nivel 16 Estado 0 Línea 1
La instrucción ALTER TABLE entró en conflicto con la restricción FOREIGN KEY "My_FORIEGN_KEY". El conflicto se produjo en la base de datos "fiddle_792fce5de09f42908c3a0f91421f3522", tabla "dbo.a", columna 'ayuda'.
ypercubeᵀᴹ
fuente
1
Gracias. Wrt ALTER TABLE b WITH NOCHECK CHECK CONSTRAINT [My_FORIEGN_KEY]; -- enable constraint without checking, ¿significará esto que la restricción no verificará los datos existentes, solo los nuevos datos entrantes?
BanksySan
1
Exactamente. Vea cómo la siguiente inserción (aid = 6) no está permitida pero las filas existentes (con aid = 4) todavía están allí.
ypercubeᵀᴹ
Eso lo demuestra perfectamente.
BanksySan