Sayangnya, ini tidak dapat diselesaikan dengan mudah dengan batasan/indeks unik yang sederhana (jika dapat diselesaikan dengan mereka sama sekali).
Yang Anda butuhkan adalah pengecualian batasan :kemampuan untuk mengecualikan beberapa baris, berdasarkan sesuatu seperti tabrakan . Batasan unik hanyalah batasan pengecualian khusus (berdasarkan persamaan tabrakan ).
Jadi, secara teori, Anda hanya perlu mengecualikan setiap row1
, di mana sudah ada row2
, yang ekspresinya benar:ARRAY[row1.cola, row1.colb] && ARRAY[row2.cola, row2.colb]
Indeks ini bisa melakukan pekerjaan (saat ini hanya gist
indeks mendukung batasan pengecualian):
ALTER TABLE table_name
ADD CONSTRAINT table_name_exclusion
EXCLUDE USING gist ((ARRAY[cola, colb]) WITH &&);
Tapi sayangnya, tidak ada kelas operator default untuk array (yang menggunakan gist
). Ada intarray
modul
, yang menyediakan satu hanya untuk integer
array, tetapi tidak ada untuk text
array.
Jika Anda benar-benar ingin menyelesaikannya, Anda selalu dapat menyalahgunakan range
jenis
(mis. Saya menggunakan -|-
. yang berdekatan operator, yang menangani semua kasus, yang tidak dapat ditangani dengan 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
... tapi saya khawatir, masalah awal Anda dapat diselesaikan dengan lebih mudah dengan sedikit refactoring basis data; yang membawa kita ke pertanyaan:masalah apa, yang ingin Anda selesaikan dengan ini?