2009-02-23 12 views
5

Me gustaría una solución para imponer una restricción solo si una columna no es nula. Parece que no puedo encontrar la forma de hacerlo en la documentación.¿Cómo puedo aplicar una restricción solo si una columna no es nula en Postgresql?

create table mytable(
    table_identifier_a INTEGER, 
    table_identifier_b INTEGER, 
    table_value1,...) 

En cuanto a la naturaleza de los datos, tendré el identificador by un valor cuando se cree la tabla. Después de recibir datos adicionales, podré llenar el identificador a. En este punto, me gustaría asegurar un unique key of (identifier_a, value1), pero solo si existe identifier_a.

Espero que tenga sentido, ¿alguien tiene alguna idea?

Respuesta

6

Ummm. Las restricciones únicas no impiden valores NULL múltiples.

CREATE TABLE mytable (
    table_identifier_a INTEGER NULL, 
    table_identifier_b INTEGER NOT NULL, 
    table_value1   INTEGER NOT NULL, 

    UNIQUE(table_identifier_a, table_identifier_b) 
); 

Tenga en cuenta que podemos insertar valores NULL Muliple en él, incluso cuando identifier_b partidos:

test=# INSERT INTO mytable values(NULL, 1, 2); 
INSERT 0 1 
test=# INSERT INTO mytable values(NULL, 1, 2); 
INSERT 0 1 
test=# select * from mytable; 
table_identifier_a | table_identifier_b | table_value1 
--------------------+--------------------+-------------- 
        |     1 |   2 
        |     1 |   2 
(2 rows) 

Pero no podemos crear duplicado (a, b) pares:

test=# update mytable set table_identifier_a = 3; 
ERROR: duplicate key value violates unique constraint "mytable_table_identifier_a_key" 

Por supuesto, usted tiene un problema: su tabla no tiene clave principal. Usted probablemente tenga un problema con el modelo de datos. Pero no proporcionó suficientes detalles de para solucionarlo.

+0

¡El problema del modelo de datos no es mío, son los clientes :)! Gracias. –

0

Puede manejar esto usando un disparador en lugar de una restricción.

0

Si yo fuera usted, dividiría la mesa en dos tablas, y posiblemente crearía una vista que las combine según sea necesario.

1

Si es factible para completar toda la operación dentro de una transacción, es posible cambiar el tiempo que postgres evalúa la restricción, es decir .:

START; 
SET CONSTRAINTS <...> DEFERRED; 
<SOME INSERT/UPDATE/DELETE> 
COMMIT; 

En este caso, la restricción se evalúa en comprometerse. Ver: Postgres 7.4 Doc - Set constraints o Postgres 8.3 Doc

1

En realidad, probablemente dividiría esto en Dos tablas. Estás modelando dos tipos diferentes de cosas. El primero es la versión inicial, que es solo parcial, y el segundo es todo. Una vez que se necesita la información para llevar el primer tipo de cosas al segundo, mueva la fila de una tabla a la otra.

Cuestiones relacionadas