PostgreSQL INSERT语句

时间:2016-10-05 11:50:27

标签: sql postgresql insert

我正在使用一个postgres数据库,我的问题包括两个表,下面是它们的简化版本。

CREATE TABLE events(
    id SERIAL PRIMARY KEY NOT NULL,
    max_persons INTEGER NOT NULL
);

CREATE TABLE requests(
    id SERIAL PRIMARY KEY NOT NULL,
    confirmed BOOLEAN NOT NULL,
    creation_time TIMESTAMP DEFAULT NOW(),
    event_id INTEGER NOT NULL /*foreign key*/
);

n个事件,每个事件最多可包含events.max_persons个参与者。新请求需要确认,有效期最长为30分钟。在此期间之后,如果未确认,请求将被忽略。

现在我想要做的事情只会插入新的request,此时所有已确认的请求和所有仍然有效但未确认的请求的总和小于{ {1}}。

我已经有了一个选择单个事件的查询。这是它的简化版本,只是为了给你一个想法,它应该如何工作

events.max_persons

是否可以使用单个INSERT命令实现此目的?

1 个答案:

答案 0 :(得分:2)

你可以这样做:

INSERT INTO requests
   SELECT * FROM (VALUES (...)) row
      WHERE ...

并编写一个WHERE子句,只有在满足条件的情况下才会生效。

但这种方法存在一个根本问题,即它会受到竞争条件的影响。

如果两个这样的语句同时运行,则两者都可以找到条件满足,但是当每个语句都添加了它的行并提交时,可以违反条件。这是因为在提交之前,没有一个语句可以看到另一个语句的效果。

有两种解决方案:

  • 在测试和插入之前锁定表格。这很简单,但对并发性非常不利。

  • 始终使用SERIALIZABLE个交易。然后,这应该导致序列化错误,并且必须重试其中一个语句,并且会在发生时违反条件。