Compruebe la restricción, solo una de las tres columnas no es nula


61

Tengo una tabla (SQL Server) que contiene 3 tipos de resultados: FLOAT, NVARCHAR (30) o DATETIME (3 columnas separadas). Quiero asegurarme de que para cualquier fila dada, solo una columna tenga un resultado y las otras columnas sean NULL. ¿Cuál es la restricción de verificación más simple para lograr esto?

El contexto para esto es tratar de adaptar la capacidad de capturar resultados no numéricos en un sistema existente. Agregar dos nuevas columnas a la tabla con una restricción para evitar más de un resultado por fila fue el enfoque más económico, no necesariamente el correcto.

Actualización: Lo siento, tipo de datos snafu. Lamentablemente, no tenía la intención de que los tipos de resultados indicados fueran interpretados como tipos de datos de SQL Server, solo términos genéricos, corregidos ahora.

Respuestas:


72

Lo siguiente debería hacer el truco:

CREATE TABLE MyTable (col1 FLOAT NULL, col2 NVARCHAR(30) NULL, col3 DATETIME NULL);
GO

ALTER TABLE MyTable
ADD CONSTRAINT CheckOnlyOneColumnIsNull
CHECK 
(
    ( CASE WHEN col1 IS NULL THEN 0 ELSE 1 END
    + CASE WHEN col2 IS NULL THEN 0 ELSE 1 END
    + CASE WHEN col3 IS NULL THEN 0 ELSE 1 END
    ) = 1
)
GO

24

Probablemente necesite hacer tres pruebas dentro de la restricción, una prueba para cada par que desee que sea nulo y otra para la columna que no debería ser nula:

ALTER TABLE table
ADD CONSTRAINT CK_one_is_null
CHECK (
     (col1 IS NOT NULL AND col2 IS NULL AND col3 IS NULL)
  OR (col2 IS NOT NULL AND col1 IS NULL AND col3 IS NULL) 
  OR (col3 IS NOT NULL AND col1 IS NULL AND col2 IS NULL)
);

Esto no es tan escalable, tengo una tabla con 9 claves externas y solo una no debería ser nula, prefiero la solución de
@MarkStoreySmith

5

Aquí hay una solución PostgreSQL que utiliza las funciones de matriz integradas :

ALTER TABLE your_table
ADD chk_only_one_is_not_null CHECK (array_length(array_remove(ARRAY[col1::text, col2::text, col3::text], NULL), 1) = 1);

¿Será una implementación más rápida en postgreSQL que las soluciones CASE o AND / OR mencionadas anteriormente publicadas por Mark Storey y mrdenny respectivamente?
Chris Britt
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.