Leider kann dies nicht einfach mit einfachen eindeutigen Einschränkungen/Indizes (wenn es überhaupt mit ihnen gelöst werden kann) gelöst werden.
Was Sie brauchen, ist ein exclusionconstraint: die Fähigkeit, einige Zeilen auszuschließen, basierend auf so etwas wie Kollision. Eindeutige Einschränkungen sind nur spezifische Ausschlussbedingungen (sie basieren auf der Gleichheit Kollisionen).
Also in der Theorie, man muss nur jeden row1
auszuschließen, in denen es bereits ein row2
, für die dieser Ausdruck wahr ist: ARRAY[row1.cola, row1.colb] && ARRAY[row2.cola, row2.colb]
Dieser Index die Arbeit machen könnte (derzeit nur gist
Indizes Unterstützung Ausschlussbedingungen):
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
module, der einen für nur integer
Arrays bereitstellt, aber nichts für text
Arrays.
Wenn Sie wirklich daran arbeiten wollen, können Sie immer die range
types (zb ich den benachbarten -|-
Operator verwendet, der alle Fälle behandelt, die nicht mit unique
gehandhabt werden kann) missbrauchen ...
-- 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-Refactoring viel einfacher gelöst werden; Das bringt uns zu der Frage: Welches Problem, willst du damit lösen?