Đáng buồn thay, điều này không thể được giải quyết dễ dàng với các đối chiếu / chỉ mục duy nhất đơn giản (nếu nó có thể được giải quyết bằng chúng).
Điều bạn cần là loại trừ ràng buộc :khả năng loại trừ một số hàng, dựa trên một số hàng như va chạm . Các ràng buộc duy nhất chỉ là các ràng buộc loại trừ cụ thể (chúng dựa trên sự bình đẳng va chạm ).
Vì vậy, về lý thuyết, bạn chỉ cần loại trừ mọi row1
, nơi đã có row2
, mà biểu thức này là true:ARRAY[row1.cola, row1.colb] && ARRAY[row2.cola, row2.colb]
Chỉ mục này có thể thực hiện công việc (hiện chỉ gist
chỉ mục hỗ trợ các ràng buộc loại trừ):
ALTER TABLE table_name
ADD CONSTRAINT table_name_exclusion
EXCLUDE USING gist ((ARRAY[cola, colb]) WITH &&);
Nhưng rất tiếc, không có lớp toán tử mặc định cho mảng (sử dụng gist
). Có một intarray
mô-đun
, chỉ cung cấp một số cho integer
mảng, nhưng không có gì cho text
mảng.
Nếu bạn thực sự muốn giải quyết vấn đề này, bạn luôn có thể lạm dụng range
các loại
(f.ex. Tôi đã sử dụng -|-
liền kề toán tử, xử lý tất cả các trường hợp, không thể xử lý bằng 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
... nhưng tôi e rằng, vấn đề ban đầu của bạn có thể được giải quyết dễ dàng hơn nhiều với một chút cấu trúc lại cơ sở dữ liệu; đưa chúng ta đến câu hỏi:bạn muốn giải quyết vấn đề gì?