Desværre kan dette ikke løses let med simple unikke begrænsninger / indekser (hvis det overhovedet kan løses med dem).
Det, du har brug for, er en udelukkelse begrænsning :evnen til at ekskludere nogle rækker, baseret på noget som kollision . Unikke begrænsninger er blot specifikke ekskluderingsbegrænsninger (de er baseret på ligestillings-kollisioner ).
Så i teorien skal du bare udelukke hver row1
, hvor der allerede er en row2
, for hvilket dette udtryk er sandt:ARRAY[row1.cola, row1.colb] && ARRAY[row2.cola, row2.colb]
Dette indeks kunne udføre jobbet (i øjeblikket kun gist
). indekser understøtter ekskluderingsbegrænsninger):
ALTER TABLE table_name
ADD CONSTRAINT table_name_exclusion
EXCLUDE USING gist ((ARRAY[cola, colb]) WITH &&);
Men Desværre er der ingen standardoperatørklasse for arrays (som bruger gist
). Der er en intarray
modul
, som kun giver en for integer
arrays, men intet for text
arrays.
Hvis du virkelig ønsker at finde ud af dette, kan du altid misbruge range
typer
(f.eks. brugte jeg den tilstødende -|-
operatør, som håndterer alle de sager, som ikke kan håndteres med unique
) ...
-- 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
... men jeg er bange for, at dit oprindelige problem kunne løses meget lettere med lidt databaserefaktorering; hvilket bringer os til spørgsmålet:hvilket problem, vil du løse med dette?