2011-03-27 10 views
17

Se Ho una tabella in PostgreSQL:Aggiunta di un vincolo non nullo one-out-of-due in 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) 
); 

Ho bisogno di fare un vincolo in modo che sia schoolName o studiedAt necessità di non essere NULL (uno di loro deve avere informazioni in esso).

Come posso fare?

risposta

26

È possibile utilizzare un check constraint ad es.

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

Dal manuale:

Un vincolo di controllo è il tipo di vincolo più generico. Ti consente di specificare che il valore in una determinata colonna deve soddisfare un'espressione booleana (valore-verità).

Edit: Alternativa a rispettare con l'interpretazione Pithyless':

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

Questo assegno non protegge da entrambi i schoolName e studiato in fase di impostazione, il che penso che l'OP avesse anche in mente. – pithyless

+0

La domanda richiede un invariante che forza almeno su 'schoolName' e' studyAt' contiene alcune informazioni. Ho aggiunto una variante del vincolo che è conforme al tuo commento sebbene non sia d'accordo con l'interpretazione della domanda. –

+2

È un po 'tardi, ma questo è un vincolo XOR in modo che tu possa esprimerlo come "CHECK ((schoolName IS NULL) <> (studyAt IS NULL))" – norcalli

0

È inoltre possibile utilizzare un trigger aggiornata e inserire per controllare che una regola è seguita prima di consentire i dati nella tabella. Normalmente utilizzerai questo tipo di approccio quando il vincolo del controllo richiede una logica più complicata.

+1

avvertimento: è spesso meglio non applicare un vincolo che ricorrere ad un trigger –

+0

Non andrei tanto lontano da dire che è meglio non applicare un vincolo piuttosto che usare un trigger, potrei dire l'oposite. Quando si utilizza un trigger, tenere sempre a mente le prestazioni e usarle con saggezza. Non usarli per il gusto di farlo. Provali per le tue esigenze specifiche e se ti permette di soddisfare i tuoi bisogni, fallo. Non c'è il male inerente con l'uso di un grilletto. È un altro strumento nella scatola. – Kuberchaun

+0

Immagino che questo sia stato [discusso prima] (http://stackoverflow.com/questions/460316/are-database-triggers-evil). La mia lamentela con loro è che non applicano regole sui dati esistenti e ci sono spesso modi per aggirare i dati senza farli sparare (es. Sql * loader per Oracle). Dato che, una API con transazioni ben definite fornisce un'integrità di dati non inferiore senza nessuno degli effetti collaterali (e molti altri vantaggi) –

Problemi correlati