Postgresql

不同列的唯一約束

  • October 6, 2017

我正在嘗試製作一個表格來儲存有向圖的邊緣,但希望避免兩個方向上的重複邊緣。我當然可以把它變成一個方向:

CREATE TABLE edge (parent integer, child integer, UNIQUE(parent, child));

但是我如何確保我也不允許新的 (parent, child) 已經作為 (child, parent) 存在?

任何想法將不勝感激!

使用GREATESTLEAST

本質上,如果我們可以對索引中的列進行排序,我們可以確保重複條目會導致衝突和違反約束,這是因為sort(5,2) = sort(2,5). 因為沒有sort,所以我們使用greatestand least

CREATE TABLE edge (
 parent int,
 child  int
);

CREATE UNIQUE INDEX
 ON edge ( greatest(parent,child), least(parent,child) );

INSERT INTO edge(parent,child)
VALUES (42,7), (42,9), (5,7);

INSERT INTO edge(parent,child)
VALUES (7,42);
ERROR:  duplicate key value violates unique constraint "edge_greatest_least_idx"
DETAIL:  Key ((GREATEST(parent, child)), (LEAST(parent, child)))=(42, 7) already exists.

引用自:https://dba.stackexchange.com/questions/187675