在Postgresql中,强制两列的组合唯一。

368

我希望在PostgreSQL中设置一个表,使得两列组合起来必须是唯一的。每个值都可以有多个副本,只要没有两个值共享这两列。

例如:

CREATE TABLE someTable (
    id int PRIMARY KEY AUTOINCREMENT,
    col1 int NOT NULL,
    col2 int NOT NULL
)
所以,col1col2可以重复使用,但不能同时重复。所以,这是允许的(不包括id)。
1 1
1 2
2 1
2 2

但不包括这个:

1 1
1 2
1 1 -- would reject this insert for violating constraints

6
由于这是谷歌搜索结果中排名靠前的内容,或许最好也提供修改现有表格的选项。 - Mamrezo
4个回答

455
CREATE TABLE someTable (
    id serial PRIMARY KEY,
    col1 int NOT NULL,
    col2 int NOT NULL,
    UNIQUE (col1, col2)
)

自增不适用于PostgreSQL。您可以使用 integer primary key generated always as identity(或者如果您使用PG 9或更低版本,则使用serial。在 PG 10中, serial 已被软弃用)。

如果col1col2唯一且不为空,则它们可以成为一个很好的主键:

CREATE TABLE someTable (
    col1 int NOT NULL,
    col2 int NOT NULL,
    PRIMARY KEY (col1, col2)
)

9
我喜欢在这里使用主键而不是唯一键的建议,因为在这种情况下我们不允许空值。根据PostgreSQL文档:“请注意,唯一约束本身并不能提供唯一标识符,因为它不能排除空值。” https://www.postgresql.org/docs/8.1/static/ddl-constraints.html#AEN2038 - ndequeker
7
在某些情况下,您可能希望使用代理键作为主键,而不是一组列的组合。特别是在处理大量数据时进行连接以提高性能。我个人选择了以下的UNIQUE CONSTRAINT解决方案。 - Alexis.Rolland
1
是否可以对一个排列强制执行唯一约束条件,例如unique(col1, col2 = '1')? - Vikram Khemlani
1
但是,就性能而言,顺序整数作为主键在索引中是否比组合主键更优? - Константин Ван
1
不确定我理解@awm的问题。如果col1是唯一的,col2也是唯一的,那么col1+col2也是唯一的,所以不需要复合键或约束。 - undefined
显示剩余4条评论

281
创建唯一约束条件,使得两个数字在一起时不能重复出现:
ALTER TABLE someTable
ADD UNIQUE (col1, col2)

41

如果像我一样,你有一个预先存在的表格,需要添加新列,并且还需要在新列和旧列上添加新的唯一约束条件,并且要能够撤销所有更改(即编写一个向下迁移),那么以下方法适用于我:

  • 使用上面的答案之一并扩展它:

这是对我有用的方法:

-- up

ALTER TABLE myoldtable ADD COLUMN newcolumn TEXT;
ALTER TABLE myoldtable ADD CONSTRAINT myoldtable_oldcolumn_newcolumn_key UNIQUE (oldcolumn, newcolumn);

---

ALTER TABLE myoldtable DROP CONSTRAINT myoldtable_oldcolumn_newcolumn_key;
ALTER TABLE myoldtable DROP COLUMN newcolumn;

-- down

36

看起来像是普通的唯一约束 :)

CREATE TABLE example (
a integer,
b integer,
c integer,
UNIQUE (a, c));

更多这里


1
这是否独立地为 ac 添加索引?因为有时我需要根据 a 快速查找,有时我需要根据 c 快速查找。 - CMCDragonkai
@CMCDragonkai 这个在a、c上的索引内部为两种类型的查询提供服务。一个以'a'作为where子句的查询和一个在where子句中包含列a和c的查询将从上述索引中受益。在这两种情况下,列'a'都应该存在,因为它是查找列。 - Akhil Mathew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接