La respuesta de @ypercube logra esto parcialmente como un cambio de metadatos solamente.
Agregar la restricción con NOCHECK
significa que no será necesario leer filas para verificarlo, y si está comenzando desde una posición donde la columna no contiene NULL
valores (y si sabe que no se agregará ninguno entre la verificación y la adición de la restricción), entonces, como los previene de restricción NULL
valores que se crean a partir de futuro INSERT
o de UPDATE
operaciones, esto va a funcionar.
Sin embargo, agregar la restricción aún puede tener un impacto en las transacciones concurrentes. El ALTER TABLE
tendrá que adquirir un Sch-M
bloqueo en primer lugar. Mientras espera esto, todos los demás accesos a la tabla serán bloqueados como se describe aquí .
Sch-M
Sin embargo, una vez que se obtiene el bloqueo, la operación debería ser bastante rápida.
Un problema con esto es que, incluso si sabe que la columna de hecho no tiene NULL
seguridad, el optimizador de consultas no confía en la restricción, lo que significa que los planes pueden ser subóptimos.
CREATE TABLE T (X INT NULL)
INSERT INTO T
SELECT ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM master..spt_values
ALTER TABLE T WITH NOCHECK
ADD CONSTRAINT X_NOT_NULL
CHECK (X IS NOT NULL) ;
SELECT *
FROM T
WHERE X NOT IN (SELECT X FROM T)
Compare esto con el más simple
ALTER TABLE T ALTER COLUMN X INT NOT NULL
SELECT *
FROM T
WHERE X NOT IN (SELECT X FROM T)
Un posible problema que puede encontrar al alterar la definición de columna de esta manera es que no solo necesita leer todas las filas para verificar que cumplan con la condición, sino que también puede terminar realizando actualizaciones registradas en las filas .
Una posible casa a mitad de camino podría ser agregar la restricción de verificación WITH CHECK
. Esto será más lento de WITH NOCHECK
lo que necesita para leer todas las filas, pero permite que el optimizador de consultas proporcione el plan más simple en la consulta anterior y debería evitar el posible problema de actualizaciones registradas.