2013-06-03 16 views
12

È possibile in PostgreSQL creare un vincolo univoco deferrabile su una colonna di caratteri, ma senza distinzione tra maiuscole e minuscole?Vincolo unico non sensibile alla distinzione tra maiuscole e minuscole

Supponiamo la seguente tabella di base:

CREATE TABLE sample_table ( 
    my_column VARCHAR(100) 
); 

Se senza vincolo differibile, è semplice come creare indice univoco con funzione, ad esempio:

CREATE UNIQUE INDEX my_unique_index ON sample_table(UPPER(my_column)); 

differite controllo vincolo richiede la creazione il vincolo in modo esplicito, ad esempio:

ALTER TABLE sample_table 
ADD CONSTRAINT my_unique_constraint UNIQUE(my_column) 
DEFERRABLE INITIALLY IMMEDIATE; 

E unfortunatel y non è possibile utilizzare funzioni arbitrarie nel vincolo univoco.

Una soluzione possibile sarebbe creare una colonna aggiuntiva con lo stesso contenuto di my_column, ma in maiuscolo, aggiornata tramite un trigger dopo ogni aggiornamento/inserimento, quindi creare un vincolo unico deferrabile su questa colonna artificiale. Questo, tuttavia, sembra un brutto scherzo.

In alternativa, dovrebbe essere possibile utilizzare CREATE CONSTRAINT TRIGGER e verificare manualmente l'univocità insensibile alle maiuscole/minuscole (ovviamente sarebbe comunque necessario un indice regolare). Questo suona un po 'complicato per un requisito così semplice (e popolare, suppongo).

C'è qualche modo più semplice e/o più elegante attorno a questa limitazione?

+0

vostri Postgres? –

+0

Al momento è 9.1. Eppure, se c'è una bella soluzione disponibile sulle versioni più recenti, sarei perfettamente felice di leggerlo :) –

+1

Controlla i vincoli di 'EXCLUDE'. Possono essere impostati, per agire come maiuscole/minuscole "UNIQUE". –

risposta

11

È possibile aggirare la restrizione utilizzando il tipo speciale citext fornito dal modulo aggiuntivo con lo stesso nome. Citando il manuale:

Il modulo citext fornisce un tipo stringa di caratteri case-insensitive, citext. Essenzialmente, internamente chiama più basso quando si confrontano i valori. Altrimenti, si comporta quasi esattamente come text.

affronta esattamente il vostro caso. Esegui una volta per database:

CREATE EXTENSION citext; 

Quindi è possibile:

versione
CREATE TABLE sample_table ( 
    my_column citext 
    ,CONSTRAINT my_unique_constraint UNIQUE(my_column) 
    DEFERRABLE INITIALLY IMMEDIATE 
); 
+0

Grande, esattamente quello che voglio in questo caso (speravo ancora in una soluzione che consentisse una funzione in termini di vincoli;)). Per gli utenti di Ubuntu - 'citext' è nel pacchetto' postgresql-contrib'. –

+1

Non avrei dovuto aggiungere un'estensione per avere un tipo di stringa senza distinzione tra maiuscole e minuscole ... il postgress dovrebbe fornire una soluzione migliore – Leonel

+6

@Leonel: la tua opinione è debitamente indicata. Non sono sicuro di come si traduca in un downvote sulla mia risposta, però. Se hai un problema specifico da risolvere, considera di pubblicare una domanda, ci sono vari casi che possono essere risolti senza installare l'estensione 'citext'.Ma non c'è niente di sbagliato nell'installarlo ed è davvero solo questione di 'CREATE EXTENSION citext;'. Il modulo è parte della distribuzione, mantenuto e rilasciato dallo stesso team e testato altrettanto accuratamente. L'unica ragione per cui non è nella versione principale è perché la maggior parte delle persone non ne ha bisogno. È "Postgres", btw, abbreviazione di PostgreSQL. –

Problemi correlati