在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 && );
from
和to
的列都是TIMESTAMP WITHOUT TIME ZONE
,并且是以UTC格式存储的date/时间(在将数据插入到应用程序中的这些列之前,我将其转换为UTC,并且在postgresql.conf中将数据库的时区设置为“UTC” )。
但是我想我可能会遇到的问题是,这个约束使得(不正确的)假设没有时间增量小于一秒。
值得注意的是,对于我所存储的特定数据,我只需要第二个解决scheme。 不过,我觉得我可能仍然需要处理这个问题,因为SQLtypes的timestamp
和timestamptz
的分辨率都高于一秒。
我的问题是:是否有任何问题,简单地假设第二个决议,因为这是我的应用程序的所有需求(或希望),或者,如果有,我怎么能改变这个约束来处理一秒健壮的方式?
范围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))