跨多个列的排列的唯一postgres约束

Kev*_*Dog 9 sql postgresql database-design constraints unique-constraint

给出Postgres数据库中的以下三列:第一,第二,第三; 如何创建约束以使排列是唯一的?

例如,如果('foo', 'bar', 'shiz')存在于db中,('bar', 'shiz', 'foo')则将其排除为非唯一.

Jak*_*nia 6

您可以使用hstore创建唯一索引:

CREATE UNIQUE INDEX hidx ON test USING BTREE (hstore(ARRAY[a,b,c], ARRAY[a,b,c]));
Run Code Online (Sandbox Code Playgroud)

小提琴

UPDATE

其实

CREATE UNIQUE INDEX hidx ON test USING BTREE (hstore(ARRAY[a,b,c], ARRAY[null,null,null]));
Run Code Online (Sandbox Code Playgroud)

可能是一个更好的主意,因为它会工作相同,但应占用更少的空间(小提琴).


Erw*_*ter 5

对于仅有三列,仅使用基本表达式的唯一索引应该可以很好地执行.无需其他模块,如hstore或自定义函数:

CREATE UNIQUE INDEX t_abc_uni_idx ON t (
  LEAST(a,b,c)
, GREATEST(LEAST(a,b), LEAST(b,c), LEAST(a,c))
, GREATEST(a,b,c)
);
Run Code Online (Sandbox Code Playgroud)

- > SQLfiddle

还需要最少的磁盘空间:

SELECT pg_column_size(row(hstore(t))) AS hst_row
      ,pg_column_size(row(hstore(ARRAY[a,b,c], ARRAY[a,b,c]))) AS hst1
      ,pg_column_size(row(hstore(ARRAY[a,b,c], ARRAY[null,null,null]))) AS hst2
      ,pg_column_size(row(ARRAY[a,b,c])) AS arr
      ,pg_column_size(row(LEAST(a,b,c)
                        , GREATEST(LEAST(a,b), LEAST(b,c), LEAST(a,c))
                        , GREATEST(a,b,c))) AS columns
FROM t;

 hst_row | hst1 | hst2 | arr | columns
---------+------+------+-----+---------
      59 |   59 |   56 |  69 |      30
Run Code Online (Sandbox Code Playgroud)

数字是小提琴示例中索引行的字节数,用pg_column_size().我的例子只使用单个字符,大小差异是不变的.