Leider kann dies nicht einfach mit einfachen eindeutigen Contraints / Indizes gelöst werden (wenn es damit überhaupt gelöst werden kann).
Was Sie brauchen, ist ein Ausschluss Einschränkung :die Fähigkeit, einige Zeilen auszuschließen, basierend auf so etwas wie Kollision . Eindeutige Beschränkungen sind nur spezifische Ausschlussbeschränkungen (sie basieren auf Gleichheits-Kollisionen ).
Theoretisch müssen Sie also nur jede row1
ausschließen , wo bereits ein row2
vorhanden ist , für die dieser Ausdruck wahr ist:ARRAY[row1.cola, row1.colb] && ARRAY[row2.cola, row2.colb]
Dieser Index könnte den Job erledigen (aktuell nur gist
Indizes unterstützen Ausschlussbeschränkungen):
ALTER TABLE table_name
ADD CONSTRAINT table_name_exclusion
EXCLUDE USING gist ((ARRAY[cola, colb]) WITH &&);
Aber Leider gibt es keine Standardoperatorklasse für Arrays (die gist
verwendet ). Es gibt einen intarray
Modul
, die nur einen für integer
bereitstellt Arrays, aber nichts für text
Arrays.
Wenn Sie das wirklich herausfinden wollen, können Sie den range
Typen
(Beispiel:Ich habe den nebenstehenden -|-
verwendet Operator, der alle Fälle behandelt, die nicht mit unique
behandelt werden können ) ...
-- there is no built-in type for text ranges neither,
-- but it can can be created fairly easily:
CREATE TYPE textrange AS RANGE (
SUBTYPE = text
);
ALTER TABLE table_name
ADD CONSTRAINT table_name_exclusion
EXCLUDE USING gist ((textrange(least(cola, colb), greatest(cola, colb))) WITH -|-);
-- the exclusion constraint above does not handle all situations:
ALTER TABLE table_name
ADD CONSTRAINT table_name_check
CHECK (cola is distinct from colb); -- without this, empty ranges could be created,
-- which are not adjacent to any other range
CREATE UNIQUE INDEX table_name_unique
ON table_name ((ARRAY[least(cola, colb), greatest(cola, colb)]));
-- without this, duplicated rows could be created,
-- because ranges are not adjacent to themselves
... aber ich fürchte, Ihr ursprüngliches Problem könnte mit ein wenig Datenbank-Refaktorisierung viel einfacher gelöst werden; was uns zu der frage bringt:welches problem willst du damit lösen?