我有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('l','k');
所以
CONSTRAINT unique_name UNIQUE (ColA,ColB)
不适合,因为它将允许以前的4个插入中的任何一个.
遗憾的是,使用简单独特的约束/索引(如果可以用它们解决它)就无法轻易解决这个问题.
你需要的是exclusion constraint:基于碰撞之类的东西排除某些行的能力.唯一约束只是特定的排除约束(它们基于相等冲突).
所以,从理论上讲,你只需要排除每个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,它只提供一个整数数组,但没有提供文本数组.
如果你真的想要解决这个问题,你总是可以滥用range
types(f.ex.我使用了相邻的| – – 运算符,它处理所有情况,无法用唯一处理)…
-- 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)])); -- without this,duplicated rows Could be created,-- because ranges are not adjacent to themselves
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。