2013-06-03 15 views
12

Ist es in PostgreSQL möglich, eine aufschiebbare eindeutige Einschränkung für eine Zeichenspalte zu erstellen, aber ohne Berücksichtigung der Groß- und Kleinschreibung?Verschiebbare, case-insensitive unique constraint

Lassen Sie uns die folgende einfache Tabelle übernehmen:

CREATE TABLE sample_table ( 
    my_column VARCHAR(100) 
); 

Wenn aufschiebbare Einschränkung nicht erforderlich ist, ist es so einfach wie mit der Funktion eindeutigen Index erstellen, zB:

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

Latente Bedingungsprüfung erfordert die Schaffung die Bedingung explizit, zB:

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

Und leider y Es ist nicht möglich, beliebige Funktionen in der eindeutigen Einschränkung zu verwenden.

Eine mögliche Problemumgehung wäre, zusätzliche Spalte mit dem gleichen Inhalt wie my_column zu erstellen, aber in Großbuchstaben, nach jedem Update/Einfügung über einen Trigger aktualisiert, und dann eine aufschiebbare eindeutige Einschränkung für diese künstliche Spalte erstellen. Dies klingt jedoch nach einem wirklich hässlichen Hack.

Alternativ sollte es möglich sein, CREATE CONSTRAINT TRIGGER zu verwenden und manuell auf Groß-/Kleinschreibung zu überprüfen (natürlich wäre ein regulärer Index immer noch notwendig). Dies klingt ein wenig zu kompliziert für solch eine einfache (und beliebte, nehme ich an) Anforderung.

Gibt es einen einfacheren und/oder eleganteren Weg um diese Einschränkung?

+0

Ihre Postgres Version? –

+0

Es ist 9.1 im Moment. Aber wenn es eine nette Lösung für neuere Versionen gibt, würde ich mich freuen, darüber zu lesen :) –

+1

Überprüfen Sie die 'EXCLUDE' Einschränkungen. Sie können so eingerichtet werden, dass sie wie die Groß-/Kleinschreibung "EINMALIG" wirkt. –

Antwort

11

Sie können die Einschränkung umgehen, indem Sie den speziellen Typ citext verwenden, der vom gleichnamigen Zusatzmodul bereitgestellt wird. Zitiert das Handbuch:

Das citext Modul bietet einen Groß- und Kleinschreibung Zeichenfolge Typen, CITEXT. Im Wesentlichen ruft es intern niedrigere Werte auf, wenn Werte verglichen werden. Ansonsten verhält es sich fast genau wie text.

Es adressiert Ihren Fall genau. Führen Sie einmal pro Datenbank:

CREATE EXTENSION citext; 

Dann können Sie:

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

Großartig, genau das, was ich in diesem Fall will (hoffe immer noch auf eine Lösung, die Funktion in Einschränkungen ermöglicht;)). Für Ubuntu-Benutzer - 'citext' ist im' postgresql-contrib' Paket. –

+1

Ich hätte keine Erweiterung hinzufügen müssen, um einen String-Typ nicht Groß-und Kleinschreibung zu beachten ... Postgress sollte eine bessere Lösung bieten – Leonel

+6

@Leonel: Ihre Meinung wird ordnungsgemäß zur Kenntnis genommen. Nicht sicher, wie es auf meine Antwort zu einem Downvote übersetzt wird. Wenn Sie ein bestimmtes Problem lösen müssen, können Sie eine Frage stellen. Es gibt verschiedene Fälle, die gelöst werden können, ohne die Erweiterung 'citext' zu installieren.Aber es ist nichts falsch daran, es zu installieren und es ist wirklich nur eine Frage von 'CREATE EXTENSION citext;'. Das Modul ist Teil der Distribution, wird von demselben Team gepflegt und freigegeben und ebenso gründlich getestet. Der einzige Grund, warum es nicht in der Kernversion ist, ist, weil die meisten Leute es nicht brauchen. Es ist "Postgres", übrigens, kurz für PostgreSQL. –

Verwandte Themen