使用 Postgres 排除约束限制匹配特定条件的表行数?
Posted
技术标签:
【中文标题】使用 Postgres 排除约束限制匹配特定条件的表行数?【英文标题】:Cap on number of table rows matching a certain condition using Postgres exclusion constraint? 【发布时间】:2020-03-05 22:03:07 【问题描述】:如果我有一个类似这样的轮胎表的 Postgresql 数据库模式(用户有很多轮胎):
user_id integer
description text
size integer
color text
created_at timestamp
我想强制执行“用户只能有 4 个轮胎”的约束。
实现这一点的一种天真的方法是:
SELECT COUNT(*) FROM tires WHERE user_id='123'
,将结果与 4 进行比较,如果它低于 4,则插入。这可能是竞争条件,因此是一种幼稚的方法。
我不想添加计数列。我怎样才能使用排除约束来做到这一点(或者我可以做到这一点)?如果排除约束不可能,那么规范的方法是什么?
【问题讨论】:
【参考方案1】:“正确”的方式是在这里使用锁。 首先,您需要锁定相关行。其次,如果用户的轮胎少于 4 个,则插入新记录。这是 SQL:
begin;
-- lock rows
select count(*)
from tires
where user_id = 123
for update;
-- throw an error of there are more than 3
-- insert new row
insert into tires (user_id, description)
values (123, 'tire123');
commit;
您可以在这里阅读更多内容How to perform conditional insert based on row count?
【讨论】:
你写的东西里潜伏着一个正确的答案。SELECT ... FOR UPDATE
应该在user_id
上,并且INSERT
中的重新检查是不必要的。以上是关于使用 Postgres 排除约束限制匹配特定条件的表行数?的主要内容,如果未能解决你的问题,请参考以下文章
冲突部分索引的 Postgres 唯一或排除约束无法更新票证
Postgres 忽略表约束,即使约束不匹配也会扫描所有继承的表