2011-03-27 11 views
17

Si tengo una tabla en PostgreSQL:Adición de una restricción no nula con un out-of-dos en PostgreSQL

create table Education ( 
    id     integer references Profiles(id), 
    finished   YearValue not null, 
    started    YearValue, 
    qualification  text, 
    schoolName   text, 
    studiedAt   integer references Organizations(id), 
    primary key (id) 
); 

Necesito hacer una restricción para que sea schoolName o studiedAt necesidades a no ser nulo (uno de ellos debe tener información en él).

¿Cómo puedo hacer esto?

Respuesta

26

Puedes usar check constraint p. Ej.

constraint chk_education check (schoolName is not null or studiedAt is not null) 

Del manual:

Una restricción de comprobación es el tipo de restricción más genérica. Le permite especificar que el valor en una determinada columna debe satisfacer una expresión booleana (valor de verdad).

Editar: Alternativa para cumplir con la interpretación Pithyless':

constraint chk_education check ((schoolName is not null and studiedAt is null) or (schoolName is null and studiedAt is not null)) 
+1

Este control no protege contra schoolName y studyAt set, que creo que el OP también tenía en mente. – pithyless

+0

La pregunta requiere un invariante que fuerce al menos una de 'schoolName' y' studiedAt' contiene alguna información. Agregué una variante de la restricción que cumple con su comentario, aunque no estoy de acuerdo con la interpretación de la pregunta. –

+2

Es un poco tarde, pero esta es una restricción XOR por lo que puede expresarlo como 'CHECK ((schoolName IS NULL) <> (estudió EN IS NULL))' – norcalli

0

También puede utilizar un disparador en la actualización e insertar para comprobar que una regla es seguida antes de permitir que los datos en la tabla. Normalmente usaría este tipo de enfoque cuando la restricción de verificación necesita una lógica más complicada.

+1

advertencia: a menudo es mejor no aplicar una restricción que recurrir a desencadenar –

+0

No llegaría tan lejos como para decir que es mejor no aplicar una restricción que utilizar un disparador, podría decir lo contrario. Cuando utilice un disparador, siempre tenga en cuenta el rendimiento y úselos con prudencia. No los uses por el gusto de hacerlo. Pruébelos para sus necesidades específicas y si le permite satisfacer sus necesidades, hágalo. No hay mal inherente con el uso de un disparador. Es otra herramienta en la caja. – Kuberchaun

+0

Supongo que esto ha sido [debatido antes] (http://stackoverflow.com/questions/460316/are-database-triggers-evil). Mi problema con ellos es que no hacen cumplir las reglas sobre los datos existentes y, a menudo, existen formas de redirigirlos para que ingresen los datos sin que se activen (por ejemplo, sql * loader for Oracle). Dado que, una API con transacciones bien definidas proporciona no menos integridad de datos sin ninguno de los efectos secundarios (y mucho más beneficios) –

Cuestiones relacionadas