PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Уникална стойност на PostgreSQL в множество колони

За съжаление, това не може да бъде решено лесно с прости уникални ограничения / индекси (ако изобщо може да бъде решено с тях).

Това, от което се нуждаете, е изключване ограничение :възможността за изключване на някои редове въз основа на нещо като сблъсък . Уникалните ограничения са просто специфични ограничения за изключване (те се основават на сблъсъци на равенство ).

Така че на теория просто трябва да изключите всеки row1 , където вече има row2 , за които този израз е верен:ARRAY[row1.cola, row1.colb] && ARRAY[row2.cola, row2.colb]

Този индекс може свърши работата (в момента само gist индексите поддържат ограничения за изключване):

ALTER TABLE table_name
  ADD CONSTRAINT table_name_exclusion
  EXCLUDE USING gist ((ARRAY[cola, colb]) WITH &&);

Но за съжаление няма операторен клас по подразбиране за масиви (който използва gist ). Има intarray модул , което предоставя едно само за integer масиви, но нищо за text масиви.

Ако наистина искате да разрешите това, винаги можете да злоупотребите с range типове (напр. използвах съседния -|- оператор, който обработва всички случаи, които не могат да бъдат обработени с 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

... но се опасявам, че вашият първоначален проблем може да бъде решен много по-лесно с малко рефакторинг на базата данни; което ни води до въпроса:какъв проблем искате да решите с това?




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. postgresql с функция wrap sql толкова бавен?

  2. Върнете само числовите стойности от колона на PostgreSQL база данни

  3. Как да изброя информация за всички файлове на Alfresco (Postgres SQL)?

  4. ГРЕШКА:редът е твърде голям:размер 8168, максимален размер 8164

  5. Postgresql 11:Грешка при извикване на съхранена процедура - За да извикате процедура, използвайте CALL, Java