残念ながら、これは単純な一意の制約/インデックスでは簡単に解決できません(それらで解決できる場合)。
必要なのは、除外 制約 :衝突などに基づいて一部の行を除外する機能 。一意の制約は、特定の除外制約にすぎません(これらは、等式衝突に基づいています。 。
したがって、理論的には、すべての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
のみに1つ提供します 配列ですが、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
...しかし、恐れ入りますが、データベースを少しリファクタリングするだけで、元の問題をはるかに簡単に解決できる可能性があります。それは私たちに質問をもたらします:どのような問題、これで解決したいですか?