2009-02-23 15 views
5

Vorrei una soluzione per applicare un vincolo solo se una colonna non è nulla. Non riesco a trovare un modo per farlo nella documentazione.Come posso applicare un vincolo solo se una colonna non è nullo in Postgresql?

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

Fare alla natura dei dati, avrò l'identificatore b e un valore quando viene creata la tabella. Dopo aver ricevuto dati aggiuntivi, sarò in grado di popolare l'identificativo a. A questo punto mi piacerebbe assicurare un unique key of (identifier_a, value1) ma solo se identifier_a esiste.

Speriamo che abbia senso, Qualcuno ha qualche idea?

risposta

6

Ummm. I vincoli univoci non impediscono più valori NULL.

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) 
); 

Si noti che possiamo inserire NULL muliple in esso, anche quando identifier_b partite:

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) 

Ma non possiamo creare duplicati (a, b) le coppie:

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

Certo, hai un problema: la tua tabella non ha una chiave primaria. È probabile che tu abbia un problema di modello di dati. Ma non hai fornito abbastanza dettagli per risolvere il problema.

+0

Il problema del modello di dati non è mio, è il cliente :)! Grazie. –

0

È possibile gestirlo utilizzando un trigger anziché un vincolo.

0

Se fossi in te, dividerei il tavolo in due tabelle, e possibilmente creare una vista che le combini se necessario.

1

Se è fattibile per completare l'intera operazione entro una transazione, è possibile modificare il tempo che postgres valuta il vincolo, cioè .:

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

In questo caso, il vincolo viene valutato commit. Vedi: Postgres 7.4 Doc - Set constraints o Postgres 8.3 Doc

1

In realtà, probabilmente lo spiegheremo in due tabelle. Stai modellando due diversi tipi di cose. Il primo è la versione iniziale, che è solo parziale, e il secondo è il tutto. Una volta che le informazioni necessarie per portare il primo tipo di cosa al secondo, spostare la riga da un tavolo all'altro.

Problemi correlati