Gav*_*nis 0 postgresql database-design unique-constraint
我试图找出一个特殊的UNIQUE约束:表中有很多列Users,但只有这两列与问题相关:
id bigint,
active boolean,
...
Run Code Online (Sandbox Code Playgroud)
我想允许多行具有相同的id-但其中只有一行可能具有active = true.
例如,可以有很多行包含id = 1和active = false,但只有一行可以包含id = 1和active = true。
为此,您可以利用一个非常有用的 PostgreSQL 功能 - partial index.
你有你的桌子:
CREATE TABLE foo
(
id BIGINT NOT NULL,
--
-- other fields
--
active BOOLEAN NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
然后,你这样做:
CREATE UNIQUE INDEX ON foo (id)
WHERE active; -- if you prefer more clarity, could have "WHERE active = TRUE;"
Run Code Online (Sandbox Code Playgroud)
所以,我们尝试一下(请参阅此处的小提琴):
--
-- `active` - all false for a given id - works
--
INSERT INTO foo
VALUES (1, FALSE), (1, FALSE), (1, FALSE);
Run Code Online (Sandbox Code Playgroud)
查看:
SELECT * FROM foo;
Run Code Online (Sandbox Code Playgroud)
结果:
id active
1 f
1 f
1 f
Run Code Online (Sandbox Code Playgroud)
另一种可能性 - 与问题相关的具体可能性:
--
-- one and only one `active` = true for a given id - works
--
INSERT INTO foo
VALUES (2, FALSE), (2, FALSE), (2, TRUE);
Run Code Online (Sandbox Code Playgroud)
查看:
SELECT * FROM foo;
Run Code Online (Sandbox Code Playgroud)
结果:
id active
1 f
1 f
1 f
2 f
2 f
2 t
Run Code Online (Sandbox Code Playgroud)
最后一个考试:
--
-- attempt to INSERT two true `active` values for a given id - fails!
--
INSERT INTO foo
VALUES (3, FALSE), (3, FALSE), (3, TRUE), (3, TRUE);
Run Code Online (Sandbox Code Playgroud)
结果:
ERROR: duplicate key value violates unique constraint "foo_id_idx"
DETAIL: Key (id)=(3) already exists.
Run Code Online (Sandbox Code Playgroud)
表foo不变,这就是我们想要的!