私はpostgresデータベースを使用していますが、私の問題には2つのテーブルが含まれています。PostgreSQL INSERT with statements
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分まで有効です。その期間が過ぎると、確認されなかった場合、リクエストは無視されます。すべての合計が要求とまだ有効であるすべての要求を確認したが、確認されていない、events.max_persons
未満のとき
今私はを何をしたいのかは、唯一の新しいrequest
を挿入しています。
すでに1つのイベントを選択するためのクエリがあります。コマンドを - ここでの簡易版はそれはそれは、単一のINSERTでこれを達成するためにpossibileです
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 INTO requests
SELECT * FROM (VALUES (...)) row
WHERE ...
をし、あなたの条件が満たされた場合にのみ、真であるWHERE
句を書く:
こんにちは、遅い答えを申し訳ありません。現時点では、max_personsとnumber_booked/number_reservedの違いを取得し、0より大きい場合にのみinsert文を実行するクエリを実行することで、私の問題を解決しました。もう1つの質問ですが、SERIALIZABLEトランザクションを使用している場合、2人で同時に同じイベントにサインアップしようとすると問題は起こりますが、残っているのは1つだけです。 – PrototypeX7
あなたの現在のテクニックは、私が答えで示した問題に対して脆弱です.2つのトランザクションが並行して実行され、1つの場所だけが空いている場合、両方とも新しい要求を追加します。起こり得ないSERIALIZABLEによって。トランザクションの1つは、シリアル化エラーで終了し、再試行する必要があります。再試行中にイベントが既に予約されていることが示されます。 –
ありがとう、それを試してみよう! – PrototypeX7