Malheureusement, cela ne peut pas être résolu facilement avec de simples contraintes / index uniques (si cela peut être résolu avec eux).
Ce dont vous avez besoin, c'est d'une exclusion contrainte :la possibilité d'exclure certaines lignes, en fonction de quelque chose comme la collision . Les contraintes uniques ne sont que des contraintes d'exclusion spécifiques (elles sont basées sur des collisions d'égalité ).
Donc, en théorie, il suffit d'exclure chaque row1
, où il y a déjà un row2
, pour laquelle cette expression est vraie :ARRAY[row1.cola, row1.colb] && ARRAY[row2.cola, row2.colb]
Cet index pourrait faire le travail (actuellement seulement gist
les index prennent en charge les contraintes d'exclusion) :
ALTER TABLE table_name
ADD CONSTRAINT table_name_exclusion
EXCLUDE USING gist ((ARRAY[cola, colb]) WITH &&);
Mais malheureusement, il n'y a pas de classe d'opérateur par défaut pour les tableaux (qui utilise gist
). Il existe un intarray
modules
, qui en fournit un pour seulement integer
tableaux, mais rien pour text
tableaux.
Si vous voulez vraiment résoudre ce problème, vous pouvez toujours abuser du range
type
(par exemple, j'ai utilisé le -|-
adjacent opérateur, qui gère tous les cas, qui ne peuvent pas être traités avec 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
... mais j'ai bien peur que votre problème d'origine puisse être résolu beaucoup plus facilement avec une petite refactorisation de la base de données ; ce qui nous amène à la question :quel problème voulez-vous résoudre avec cela ?