Ant*_*ton 6 postgresql constraints unique
我有PostgreSQL表
id ColA ColB
------------------
1 'a' 'b'
2 'c' 'd'
Run Code Online (Sandbox Code Playgroud)
我希望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');
Run Code Online (Sandbox Code Playgroud)
并允许任何这些插入:
INSERT INTO table (ColA,ColB) values('z','e');
INSERT INTO table (ColA,ColB) values('l','k');
Run Code Online (Sandbox Code Playgroud)
所以
CONSTRAINT unique_name UNIQUE (ColA,ColB)
Run Code Online (Sandbox Code Playgroud)
不适合,因为它将允许以前的4个插入中的任何一个.
遗憾的是,这不能通过简单的唯一约束/索引轻松解决(如果可以用它们解决的话)。
您需要的是排除 约束:基于碰撞之类的内容排除某些行的能力。唯一约束只是特定的排除约束(它们基于相等冲突)。
因此,理论上,您只需排除每个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 &&);
Run Code Online (Sandbox Code Playgroud)
但不幸的是,数组没有默认的运算符类(它使用gist
)。有一个intarray
模块,它只为integer
数组提供一个模块,但不为text
数组提供任何模块。
如果你真的想解决这个问题,你总是可以滥用类型range
(例如,我使用了相邻的-|-
运算符,它处理所有不能用 处理的情况unique
)...
-- 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
Run Code Online (Sandbox Code Playgroud)
...但恐怕,通过一些数据库重构,您原来的问题可以更容易地解决;这给我们带来了一个问题:你想用这个解决什么问题?
归档时间: |
|
查看次数: |
1199 次 |
最近记录: |