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

Cmd*_*ozy 8 sql postgresql datetime range-types exclusion-constraint

我正在创建一个在PostgreSQL 9.2.4中存储任意日期/时间范围的数据库.我想在这个数据库上设置一个约束,它强制日期/时间范围不重叠,不相邻(因为两个相邻的范围可以表示为单个连续范围).

为此,我使用EXCLUDE带有GiST索引的约束.这是我目前的约束:

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 &&
);
Run Code Online (Sandbox Code Playgroud)

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

但是,我想我可能遇到的问题是,这个约束正在做出(错误的)假设,即没有小于一秒的时间增量.

值得注意的是,对于我存储的特定数据,我只需要第二个分辨率.不过,我觉得我可能还是需要处理这个,因为SQL类型timestamptimestamptz都超过一秒更高的分辨率.

我的问题是:是否有任何问题,只是假设第二个解决方案,因为这是我的所有应用程序需要(或想要),或者,如果有,我怎么能改变这个约束来处理一个秒的分数健壮的方式?

Erw*_*ter 18

范围类型包括下边框和上边框,可以包含或排除.典型用例(范围类型的默认值)是包含下限并排除上限.

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

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

为了保持清洁,我将使用范围函数[)对所有具有CHECK约束的条目强制执行边界(包括下限和排除上限):

CREATE TABLE tbl (
   tbl_id serial PRIMARY KEY
 , tsr tsrange
 , CONSTRAINT tsr_no_overlap  EXCLUDE USING gist (tsr WITH &&)
 , CONSTRAINT tsr_no_adjacent EXCLUDE USING gist (tsr WITH -|-)
 , CONSTRAINT tsr_enforce_bounds CHECK (lower_inc(tsr) AND NOT upper_inc(tsr))
);
Run Code Online (Sandbox Code Playgroud)

SQL小提琴.

  • 这个解决方案将非常有效.虽然我可以使用单独的列伪装它,但切换到`tsrange`会使这个变得微不足道,**和**会给我所有其他范围操作符,这些操作符对于使用/管理这些数据非常方便.谢谢!:) (3认同)