对日期范围设置唯一性约束

sri*_*rip 2 postgresql database-design exclusion-constraint postgresql-9.3 range-types

我有一个表reservation的列roomno(INTEGER)startdate(DATE)enddate(DATE)与主键(roomno, startdate)。

我如何在表上设置约束,以便不允许预订重叠?

我试图在SQLFIDDLE postgreSQL9.3 中实现这个

例如:

101  2016-01-01   2016-01-05
101  2016-01-03   2016-01-06 [This row should not be possible to insert]
Run Code Online (Sandbox Code Playgroud)

startdate并且enddate是数据类型date

Erw*_*ter 5

使用排除约束并注意类型的边界是如何daterange工作的。date是离散类型,因此范围具有默认[)范围。根据文档:

内置范围类型int4rangeint8rangedaterange都使用规范形式,包括下限和排除上限;也就是说,[)

因此,如果您要预订 2016-01-01 至 2016-01-05 的房间,包括第一天和最后一天,则必须明确指定界限:

daterange(start_date, end_date, '[]')
Run Code Online (Sandbox Code Playgroud)

或者您输入具有排他上限的日期;包括2016年1月5日,进入2016-01- 06。然后你可以使用更简单的表达式:

daterange(start_date, end_date)
Run Code Online (Sandbox Code Playgroud)

在排除约束中使用上述表达式使其成为功能索引,如@ypercube 所示:

通过这种方式,您可以像现在一样保留列。

或者您可以用一列替换startdate和并在排除约束中使用普通列。就像在这个相关的答案中一样:enddatedaterange

无论哪种方式,假设roomno是一个integer列,您需要先安装附加模块btree_gist,每个数据库一次。

有关的: