PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Unikalna wartość PostgreSQL w wielu kolumnach

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ć?




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tablica wierszy PL/pgSQL

  2. Relacja nie istnieje

  3. Jak mogę wysłać e-mail z wyzwalacza PostgreSQL?

  4. PostgreSQL - dynamiczna wartość jako nazwa tabeli

  5. Wskazówki dotyczące zdalnego zarządzania PostgreSQL