PostgreSQL唯一值ACREOS多列
我有一个PostgreSQL表PostgreSQL唯一值ACREOS多列,postgresql,constraints,unique,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) v
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');
所以
不适合,因为它将允许前面4个插入中的任何一个。遗憾的是,这不能用简单的唯一约束/索引轻松解决(如果可以用它们解决的话) 您需要的是:基于诸如碰撞之类的内容排除某些行的能力。唯一约束只是特定的排除约束(它们基于相等冲突) 因此,从理论上讲,您只需要排除每个
row1
,其中已经有一个row2
,对于这个表达式:ARRAY[row1.cola,row1.colb]&&ARRAY[row2.cola,row2.colb]
此索引可以执行此任务(目前只有gist
索引支持排除约束):
但是不幸的是,数组没有默认的操作符类(使用gist
)。有一个,它只为整数
数组提供一个,而不为文本
数组提供一个
如果你真的想解决这个问题,你总是可以滥用(例如,我使用了相邻的-|-
操作符,它处理所有的情况,而unique
无法处理这些情况)
。。。但我担心,通过一点数据库重构,您原来的问题可能会更容易解决;这就引出了一个问题:您想用它解决什么问题?我有一个类似的问题:用户表有两列电子邮件地址。一封用于普通电子邮件,另一封用于未经验证的新电子邮件。现在我希望它们是唯一的,不管它们是否已经被验证过。
CONSTRAINT unique_name UNIQUE (ColA,ColB)
ALTER TABLE table_name
ADD CONSTRAINT table_name_exclusion
EXCLUDE USING gist ((ARRAY[cola, colb]) WITH &&);
-- there is no built-in type for text ranges neither,
-- but it can can be created fairly easily:
CREATE TYPE textrange AS RANGE (
SUBTYPE = text
);
ALTER TABLE table_name
ADD CONSTRAINT table_name_exclusion
EXCLUDE USING gist ((textrange(least(cola, colb), greatest(cola, colb))) WITH -|-);
-- the exclusion constraint above does not handle all situations:
ALTER TABLE table_name
ADD CONSTRAINT table_name_check
CHECK (cola is distinct from colb); -- without this, empty ranges could be created,
-- which are not adjacent to any other range
CREATE UNIQUE INDEX table_name_unique
ON table_name ((ARRAY[least(cola, colb), greatest(cola, colb)]));
-- without this, duplicated rows could be created,
-- because ranges are not adjacent to themselves