PostgreSQL 不允许超过一行满足条件

问题描述 投票:0回答:3

我有一张桌子

orders
,其中包含以下列:
id
user_id
status
status
列是枚举值:pending, in_process, completed, declined.

我需要禁止用户使用

status in (pending, in_process)
拥有多个订单。

例如,有桌子:

id 状态 user_id
1 完成 1
2 进程中 1
3 待定 2

对于

pending
,我们不应该再插入一个状态为
in_process
或状态为
user_id=1
的订单。

我觉得我应该在这里使用排除约束,但不知道如何禁止两个集合的交集。

postgresql
3个回答
1
投票

您正在寻找的是部分唯一索引。由于

status
是一个枚举,您很可能必须对数组进行类型转换。

create unique index on orders (user_id, status)
where status = any ( array['pending', 'in_process']::status_enum[] );

1
投票

你不是在这里寻找排除约束(因为你想允许任意数量的

completed
行,这些行都具有相同的
user_id
status
值)而是一个 conditionally unique constraint - which postgres 不支持
CONSTRAINT
,但你可以使用 partial
UNIQUE
index
:

CREATE UNIQUE INDEX unique_active_order
ON orders (user_id)
WHERE (status IN ('pending', 'in_process'));

CREATE UNIQUE INDEX unique_active_order
ON orders (user_id)
WHERE (status <> 'completed');

0
投票

BelayerBergi 比我先发布部分独特的方法,所以对于运动:你 can 做一个 exclusion constraint 工作。 演示

create table orders (
   id smallserial,
   user_id int,
   status text check (status in ('pending','in_process','completed','declined') ),
   exclude (user_id with =) where (status in ('pending','in_process'))
);

但它没有任何好处:

虽然允许,但使用具有排除约束的 B 树或哈希索引没有什么意义,因为这没有做普通唯一约束不能做得更好的事情。所以在实践中,访问方法将始终是 GiST 或 SP-GiST。

© www.soinside.com 2019 - 2024. All rights reserved.