仅当行数低于限制时,Postgres才会插入行

时间:2018-02-11 10:53:35

标签: sql postgresql

我希望在Postgres 10中有一个SQL语句或函数,只有在行数少于一定数量的情况下才允许我插入一行。

select count(*) from mytable where mykey = 1
--- do the following only if the above is less than 5
insert into mytable (myvalue, mykey) values ('randomvalue', 1)
--- so there are never more than 5 rows in mytable with mykey = 1

像这个伪代码这样的东西会起作用吗(对postgres服务器的多次往返调用)?

tx = app.tx("start transaction");
count = tx.query("select count(*) from mytable where mykey = 1")
if (count < 5) {
  tx.query("insert into mytable (myvalue, mykey) values ('randomvalue', 1)")
}
tx.do("commit")

如果它不起作用,我怎么能在Postgres方面这样做,所以我只从应用程序拨打一个电话,如select myinsertfunction('randomvalue', 1)

无论是上面这样做的多次往返方式,还是对postgres的单次调用,最重要的是没有办法以插入超过5行的方式并行运行。例如,事务1和2都检查计数是4(小于最大值5),并同时进行,因此它们最终将插入1行,每行总共6行而不是最多5个。

1 个答案:

答案 0 :(得分:4)

问题称为Phantom Read

  

事务重新执行一个查询,返回满足搜索条件的一组行,并发现满足条件的行集由于另一个最近提交的事务而发生了更改。

尝试

BEGIN;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
INSERT INTO mytable (myvalue, mykey) SELECT 'randomvalue', 1 WHERE
    (SELECT COUNT(*) FROM mytable WHERE mykey = 1) < 5;
END;

事务隔离级别将确保事务仅在计数小于5时插入值。