Niestety nie można tego łatwo rozwiązać za pomocą prostych unikalnych ograniczeń / indeksów (jeśli w ogóle można to za ich pomocą rozwiązać).
Potrzebujesz wykluczenia ograniczenie :możliwość wykluczenia niektórych wierszy na podstawie czegoś takiego jak kolizja . Unikalne ograniczenia to tylko określone ograniczenia wykluczenia (opierają się na równości kolizje ).
Tak więc teoretycznie wystarczy wykluczyć każdy row1
, gdzie istnieje już row2
, dla którego to wyrażenie jest prawdziwe:ARRAY[row1.cola, row1.colb] && ARRAY[row2.cola, row2.colb]
Ten indeks może wykonać pracę (obecnie tylko gist
indeksy obsługują ograniczenia wykluczenia):
ALTER TABLE table_name
ADD CONSTRAINT table_name_exclusion
EXCLUDE USING gist ((ARRAY[cola, colb]) WITH &&);
Ale niestety nie ma domyślnej klasy operatora dla tablic (która używa gist
). Istnieje intarray
moduł
, który zapewnia jeden tylko dla integer
tablice, ale nic dla text
tablice.
Jeśli naprawdę chcesz to rozwiązać, zawsze możesz nadużyć range
typy
(np. użyłem sąsiedniego -|-
operator, który obsługuje wszystkie przypadki, których nie można obsłużyć za pomocą 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
... ale obawiam się, że Twój pierwotny problem można rozwiązać znacznie łatwiej dzięki niewielkiej refaktoryzacji bazy danych; co prowadzi nas do pytania:jaki problem chcesz z tym rozwiązać?