繁体   English   中英

如何处理具有排除约束的表的更新?

[英]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_tsto_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM