SQL NOT EXISTS(BETWEEN(...)AND(...))

时间:2016-10-16 23:26:19

标签: sql postgresql

我正在创建一个用于预订酒店房间的数据库。我停留在一个约束上,该约束检查guest虚拟机的'dateFrom'变量是否在该特定guest虚拟机的任何'dateFrom'和'dateTo'变量之间。即)客人不能一次预订超过1个房间。

我收到错误:“无法在检查约束中使用子查询”:

CREATE TABLE tomsBooking 
(
    hotelNo HotelNo NOT NULL,
    guestNo INT NOT NULL,
    dateFrom DATE NOT NULL,
    dateTo DATE NOT NULL, 
    roomNo RoomNumber 

    CONSTRAINT GuestOverlap
    CHECK ( NOT EXISTS 
                (SELECT * FROM tomsBooking b 
                                WHERE b.guestNo = b.guestNo
                                AND b.dateTo >= dateFrom 
                                AND b.dateFrom <= dateTo
                            )
             )
);

2 个答案:

答案 0 :(得分:4)

不幸的是,Postgres不支持检查约束的子查询。

但是这种情况正是exclusion constraints创建的地方:

CREATE TABLE tomsBooking 
(
    hotelNo HotelNo NOT NULL,
    guestNo INT NOT NULL,
    dateFrom DATE NOT NULL,
    dateTo DATE NOT NULL, 
    roomNo RoomNumber 
);

alter table tomsbooking
   add constraint guestoverlap 
   exclude using gist (guestno with =, daterange(datefrom, dateto) with &&);

有关详细信息和示例,请参阅手册:https://www.postgresql.org/docs/current/static/rangetypes.html#RANGETYPES-CONSTRAINT

为了使GIST索引能够使用=运算符,您需要使用以下命令安装btree_gist模块:

create extension btree_gist;

(每个数据库只需要执行一次)

答案 1 :(得分:0)

请记住,我不知道Postgres SQL ......在我看来,您需要在BETWEEN语句附近使用术语VALUE,以便比较知道它在哪个值之间进行检查。

作为替代方案,并且基于Postgresql query between date ranges,我会将其构造为:

CREATE DOMAIN DateFrom AS DATE
    CHECK (VALUE > '2016-10-16' AND NOT EXISTS (SELECT * FROM tomsBooking b 
                            WHERE b.guestNo = g.guestNo
                                AND VALUE >= dateFrom 
                                AND VALUE <= dateTo
                            )
    );

正如我所说,我不了解Postgres,所以你可能需要调整我的建议。