PostgreSQL独特的价值acreoss多列

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个插入中的任何一个.

poz*_*ozs 5

遗憾的是,这不能通过简单的唯一约束/索引轻松解决(如果可以用它们解决的话)。

您需要的是排除 约束:基于碰撞之类的内容排除某些行的能力。唯一约束只是特定的排除约束(它们基于相等冲突)。

因此,理论上,您只需排除每个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)

...但恐怕,通过一些数据库重构,您原来的问题可以更容易地解决;这给我们带来了一个问题:你想用这个解决什么问题?