Vincolo di colonna univoco personalizzato, applicato solo se una colonna ha un valore specifico


19

È possibile avere un vincolo di colonna univoco personalizzato come segue? Supponiamo che io abbia due colonne subsete typeentrambe le stringhe (anche se i tipi di dati probabilmente non contano).

Se typeè "vero", allora voglio che la combinazione di typee subsetsia unica. Altrimenti, non ci sono vincoli. Sto usando PostgreSQL 8.4 su Debian.


Risposte:


31

In altre parole, vuoi subsetessere unico se type = 'true'.
Un indice univoco parziale lo farà:

CREATE UNIQUE INDEX tbl_some_name_idx ON tbl (subset) WHERE type = 'true';

In questo modo è anche possibile creare combinazioni con NULLunivoco, cosa altrimenti impossibile - come spiegato in dettaglio in questa risposta correlata:
vincolo univoco multi-colonna PostgreSQL e valori NULL


Grazie Erwin. Non ho visto questa opzione quando ho guardato la documentazione. Un link più diretto è postgresql.org/docs/current/interactive/indexes-partial.html . Vedi esempio 11-3.
Faheem Mitha,

@FaheemMitha: ho collegato un livello superiore, poiché è necessario combinare un indice parziale con un indice univoco .
Erwin Brandstetter,

1
@Erwin Quella pagina (sugli indici parziali), ha un esempio con indice univoco parziale.
ypercubeᵀᴹ

@ypercube: Ah, giusto. Questo è il collegamento migliore. Ho cambiato la mia risposta per indicare l'ultimo capitolo.
Erwin Brandstetter,

6

Ciò è complementare alla risposta di Erwin sopra, ma PostgreSQL supporta una serie di tipi di indici. Questi generalmente non si escludono a vicenda. Puoi pensare a questi come a:

  • Metodo dell'indice (btree, GiST, GIN, ecc.). Scegline uno, se necessario (btree è l'impostazione predefinita)
  • Parziale o completo. Se parziale usa una clausola where
  • Diretto o funzionale. È possibile indicizzare l'output delle funzioni.
  • Unico o non unico

Questi possono essere combinati in vari modi. Tutto quello che stai facendo qui è utilizzare le funzionalità uniche e parziali, in modo che ti dia indici unici parziali (che sono estremamente utili come stai scoprendo.

Supponiamo di voler avere un indice senza distinzione tra maiuscole e minuscole nel campo del sottoinsieme in cui type è true. Quindi aggiungere una definizione funzionale:

CREATE INDEX my_index_name_idx_u ON tbl (lower(subset)) WHERE type;

Nota che crea un indice univoco sull'output della funzione lower () chiamata sull'attributo subset dove type è true.


Quindi l'indice nella risposta di Erwin è diretto, mentre quello nel tuo esempio in funzionale, corretto?
Faheem Mitha,

@FaheemMitha: Corretto.
Erwin Brandstetter,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.