我正在使用postgres数据库,我的问题包括两个表格,它们的简化版本如下。PostgreSQL插入语句
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
,当所有的确认请求,以及目前仍然有效的所有请求,但没有证实的总和,小于events.max_persons
。
我已经有查询来选择单个事件。这里是它的一个简化版本,只是给你一个想法,它应该如何工作
SELECT
e.id,
SUM(CASE WHEN r.confirmed = 1 THEN 1 ELSE 0 END) AS number_confirmed
SUM(CASE WHEN r.creation_time > (CURRENT_TIMESTAMP - INTERVAL '30 MINUTE') AND r.confirmed = 0 THEN 1 ELSE 0 END) AS number_reserved,
e.max_persons
FROM events e, requests r
WHERE l.id = ?
AND r.event_id = e.id
AND (r.confirmed = 1 OR r.creation_time > (CURRENT_TIMESTAMP - INTERVAL '30 MINUTE'))
GROUP BY e.id, e.max_persons
HAVING SUM(CASE WHEN r.confirmed = 1 OR (r.creation_time > (CURRENT_TIMESTAMP - INTERVAL '30 MINUTE')) THEN 1 ELSE 0 END) < e.max_persons";
难道不可能性与一个单一的INSERT实现这一目标 - 命令?
你好,对于最近的答案抱歉。目前我通过运行查询来解决我的问题,该查询得到max_persons和number_booked/number_reserved之间的差异,并只执行插入语句,如果它大于0。这是一种可行的做法吗?还有一个问题,如果我使用SERIALIZABLE交易,我可以解决两个人同时报名参加同一个活动的问题,但只剩下一个地方吗? – PrototypeX7
您目前的技术很容易受到我在答复中指出的问题的影响 - 如果两个此类事务并行运行,并且只有一个地方是免费的,则它们都会添加新的请求。 SERIALIZABLE无法实现。其中一个事务会因序列化错误而终止,并且必须重试。在重试期间,它会显示该事件已经预订完毕。 –
谢谢,试试看! – PrototypeX7