我有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个插入中的任何一个。
答案 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
...但我担心,通过一点点数据库重构可以更轻松地解决原始问题;这让我们想到了一个问题:你想用这个解决什么问题?