在PostgreSQL中使用EXCLUDE防止相邻/重叠条目

我正在创build一个在PostgreSQL 9.2.4中存储任意date/时间范围的数据库。 我想对这个强制date/时间范围不重叠和不相邻(因为两个相邻范围可以表示为单个连续范围)的数据库施加约束。

为此,我正在使用带有GiST索引的EXCLUDE约束。 这是我目前的限制:

 ADD CONSTRAINT overlap_exclude EXCLUDE USING GIST ( box( point ( extract(EPOCH FROM "from") - 1, extract(EPOCH FROM "from") - 1 ), point ( extract(EPOCH FROM "to"), extract(EPOCH FROM "to") ) ) WITH && ); 

fromto的列都是TIMESTAMP WITHOUT TIME ZONE ,并且是以UTC格式存储的date/时间(在将数据插入到应用程序中的这些列之前,我将其转换为UTC,并且在postgresql.conf中将数据库的时区设置为“UTC” )。

但是我想我可能会遇到的问题是,这个约束使得(不正确的)假设没有时间增量小于一秒。

值得注意的是,对于我所存储的特定数据,我只需要第二个解决scheme。 不过,我觉得我可能仍然需要处理这个问题,因为SQLtypes的timestamptimestamptz的分辨率都高于一秒。

我的问题是:是否有任何问题,简单地假设第二个决议,因为这是我的应用程序的所有需求(或希望),或者,如果有,我怎么能改变这个约束来处理一秒健壮的方式?

范围types由下边界和上边界组成,可以包含或排除 。 典型的用例(和范围types的默认值)是包含下限并排除上限。

排除重叠范围似乎很清楚。 手册中有一个很好的代码示例

另外,使用相邻的运算符-|-创build另一个排除约束来排除相邻的条目。 两者都必须基于GiST索引,因为GIN目前不受支持。

我会强制所有条目的限制。 你可以用额外的CHECK约束使用范围函数来做到这一点:

 CREATE TABLE tbl ( tbl_id serial PRIMARY KEY , tsr tsrange , EXCLUDE USING gist (tsr WITH &&) -- no overlapping , EXCLUDE USING gist (tsr WITH -|-) -- no adjacent , CHECK (lower_inc(tsr) AND NOT upper_inc(tsr)) -- enforce [) bounds ); 

SQL小提琴。

您可以使用9.2中介绍的范围types重写排除。 更好的是,你可以用一个范围replace这两个字段。 请参阅这里的“范围限制”,其中的一个例子基本相当于您的用例:

http://www.postgresql.org/docs/current/static/rangetypes.html

但是我想我可能会遇到的问题是,这个约束使得(不正确的)假设没有时间增量小于一秒。

你还好吧,考虑一下:

 select extract ('epoch' from now()) , extract ('epoch' from now()::timestamp(0))