I have a table orders
with the columns: id
, user_id
and status
. The status
column is enum with values: pending, in_process, completed, declined.
I need to disallow a user to have more than one order with status in (pending, in_process)
.
For example, having the table:
id | status | user_id |
---|---|---|
1 | completed | 1 |
2 | in_process | 1 |
3 | pending | 2 |
We shouldn’t be able to insert neither one more order with status pending
nor with status in_process
for the user_id=1
.
I feel like I should use an exclusion constraint here, but don’t know how to disallow intersection of two sets.
3
Answers
What you are looking for is a partial unique index. Since
status
is an enum you will, most likely, have to type cast the array.You’re not looking for an exclusion constraint here (as you want to allow any number of
completed
rows which all have the same values foruser_id
andstatus
) but rather for a conditionally unique constraint – which postgres does not support as aCONSTRAINT
, but you can use a partialUNIQUE
index:or
Belayer and Bergi beat me to posting the partial unique approach, so for sports: you can make an exclusion constraint work for this. demo
Among those
where status in ('pending','in_process')
, no twouser_id
‘s can be the same.I said this is for sports because it can work, but offers no benefits over the partial unique: