PostgreSQL独特的价值acreoss多列

时间:2015-06-11 09:04:16

标签: postgresql constraints unique

我有PostgreSQL表

id    ColA    ColB
------------------
1     'a'     'b'
2     'c'     'd'

我想让ColA和ColB中的值在两列中都是唯一的,即任何这些插入都是禁止的:

INSERT INTO table (ColA,ColB) values('a','e');
INSERT INTO table (ColA,ColB) values('z','a');
INSERT INTO table (ColA,ColB) values('d','g');

并且允许任何这些插入:

INSERT INTO table (ColA,ColB) values('z','e');
INSERT INTO table (ColA,ColB) values('l','k');

所以

CONSTRAINT unique_name UNIQUE (ColA,ColB)

不合适,因为它允许以前的4个插入中的任何一个。

1 个答案:

答案 0 :(得分:3)

可悲的是,使用简单的唯一约束/索引(如果可以用它们完全解决)就无法轻易解决这个问题。

您需要的是exclusion constraint:根据 collision 之类的内容排除某些行的功能。唯一约束只是特定的排除约束(它们基于相等的碰撞)。

因此,从理论上讲,您只需排除每个row1,其中已存在row2,此表达式为真:ARRAY[row1.cola, row1.colb] && ARRAY[row2.cola, row2.colb]

此索引可以完成工作(目前只有gist索引支持排除约束):

ALTER TABLE table_name
  ADD CONSTRAINT table_name_exclusion
  EXCLUDE USING gist ((ARRAY[cola, colb]) WITH &&);
遗憾的是,

但是没有数组的默认运算符类(使用gist)。有一个intarray module,它只为integer个数组提供一个,但text数组没有。

如果你真的想要解决这个问题,你可以随时滥用range types(f.ex。我使用了相邻的-|-运算符,该运算符处理所有无法用{处理}的情况{1}})......

unique

...但我担心,通过一点点数据库重构可以更轻松地解决原始问题;这让我们想到了一个问题:你想用这个解决什么问题?