[英]how to handle updates on a table with exclusion constraint?
我有一個表格來跟蹤酒店預訂情況,如下所示。
目前,我允許客人更新他們的預訂。 因此,如果 guest_id 1 從 2010-01-03、2010-01-03 將他的預訂從 3 天預訂更改為一天,如果我運行此更新語句,postgres 將由於重疊約束而阻止更新:
update reservation set from_ts = '2021-01-03 00:00:00', to_ts='2021-01-10 23:59:00', during = '[2021-01-03 00:00:00, 2021-01-10 23:59:00]' where id = 1
你怎么go關於允許這個更新呢? 您是否必須保持預訂 ID 不變,並刪除其他的?
** 注意:我實際上每行存儲一天,因為我還有其他屬性可以每天跟蹤 **
Table: reservation
id | room | from_ts | to_ts | guest_id
----+------+---------------------+---------------------+------------
1 | 101 | 2010-01-01 00:00:00 | 2010-01-01 23:59:00 | 1
2 | 101 | 2010-01-02 00:00:00 | 2010-01-02 23:59:00 | 1
3 | 101 | 2010-01-03 00:00:00 | 2010-01-03 23:59:00 | 1
CREATE TABLE reservation (
id int,
guest_id int,
room int,
from_ts timestamp without time zone,
to_ts timestamp without time zone,
during tsrange,
EXCLUDE USING GIST (room WITH =, during WITH &&)
);
-- bootstrap to test the problem
INSERT INTO reservation ( id, guest_id, room, from_ts, to_ts, during ) VALUES ( 1, 1, 101, '2021-01-01 00:00:00', '2021-01-01 23:59:00', '[2021-01-01 00:00:00, 2021-01-01 23:59:00]');
INSERT INTO reservation ( id, guest_id, room, from_ts, to_ts, during ) VALUES ( 2, 1, 101, '2021-01-02 00:00:00', '2021-01-02 23:59:00', '[2021-01-02 00:00:00, 2021-01-02 23:59:00]' );
INSERT INTO reservation ( id, guest_id, room, from_ts, to_ts, during ) VALUES ( 3, 1, 101, '2021-01-03 00:00:00', '2021-01-03 23:59:00', '[2021-01-03 00:00:00, 2021-01-03 23:59:00]' );
-- update statement will fail after you run the insert statements
update reservation set from_ts = '2021-01-03 00:00:00', to_ts='2021-01-10 23:59:00', during = '[2021-01-03 00:00:00, 2021-01-10 23:59:00]' where id = 1
您可以通過使用不同的排除約束而不是您創建的排除約束來解決該問題:
ALTER TABLE reservation ADD EXCLUDE USING gist (
room WITH =,
guest_id WITH <>,
tsrange(from_ts, to_ts, '[]') WITH &&
);
這將排除兩個條目,其中房間相同且時間戳范圍重疊並且預訂是針對不同客人的。
請注意,我使用了一個表達式而不是during
。 在數據庫設計中避免冗余是個好主意。 您當然也可以保留duration
並取消from_ts
和to_ts
。
還要注意to_ts
在 23:59:00 結束時有多尷尬。 您可以改為選擇在上端開放的間隔:
SELECT tsrange('2021-01-02 00:00:00', '2021-01-03 00:00:00');
tsrange
═══════════════════════════════════════════════
["2021-01-02 00:00:00","2021-01-03 00:00:00")
(1 row)
這不會與以 2021-01-03 00:00:00 開頭的范圍重疊。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.