在Postgres数据库中给出以下三列:第一,第二,第三;如何创建约束以使排列是唯一的?
E.g。如果数据库中存在('foo', 'bar', 'shiz')
,则('bar', 'shiz', 'foo')
将被排除为非唯一。
答案 0 :(得分:6)
您可以使用hstore创建唯一索引:
CREATE UNIQUE INDEX hidx ON test USING BTREE (hstore(ARRAY[a,b,c], ARRAY[a,b,c]));
实际上
CREATE UNIQUE INDEX hidx ON test USING BTREE (hstore(ARRAY[a,b,c], ARRAY[null,null,null]));
可能是一个更好的主意,因为它的工作方式相同但应占用更少的空间(fiddle)。
答案 1 :(得分: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)
);
还需要最少的磁盘空间:
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
数字是小提琴示例中索引行的字节,用pg_column_size()
衡量。我的例子只使用单个字符,大小差异是不变的。
答案 2 :(得分:3)
您可以通过在函数上创建唯一索引来执行此操作,该函数返回列中值的排序数组:
CREATE OR REPLACE FUNCTION sorted_array(anyarray)
RETURNS anyarray
AS $BODY$
SELECT array_agg(x) FROM (SELECT unnest($1) AS x FROM test ORDER BY x) AS y;
$BODY$
LANGUAGE sql IMMUTABLE;
CREATE UNIQUE index ON test (sorted_array(array[first,second,third]));
答案 3 :(得分:0)
来自同事的建议,@ julien的想法的变化:
按字母顺序对术语进行排序,并在每个术语的任一侧放置分隔符。连接它们并将它们放在一个单独的字段中,成为主键。
为什么分隔符?这样,“a”,“aa”,“aaa”和“aa”,“aa”,“aa”都可以插入。