具有重叠时间戳范围的排除约束

时间:2012-05-25 18:20:46

标签: postgresql postgresql-9.1

我想有一个相同的:

create table t (
    fromts timestamptz, 
    tots timestamptz,
    exclude using gist ((fromts, tots) with overlaps)
);
ERROR:  syntax error at or near ","
LINE 4:         exclude using gist ((fromts, tots) with overlaps)

我想除了语法错误之外,还存在非交换运算符的问题。

使它运作的最简单方法是什么?

2 个答案:

答案 0 :(得分:4)

这一开始看起来似乎很人为,但它开箱即用(没有双关语):

由于@Quassnoi帮助我查明,这仅适用于timestamp,而不适用于timestamptz

CREATE TABLE t (
    fromts timestamp, 
    tots   timestamp,
    exclude using GIST (box(point(EXTRACT(EPOCH FROM fromts), 0)
                          , point(EXTRACT(EPOCH FROM tots),   0)) WITH &&)
);

在您澄清类型之前,我的测试是timestampEXTRACT IMMUTABLEtimestamptimestamptztimestamp with time zone。 @Quassnoi在下面的评论中发布了一个假设,为什么会这样。

因此,对于IMMUTABLE,您必须使用@Quassnoi等辅助函数在其答案中进行转换tstzrange

在Postgres 9.2或更高版本中

...您可以针对此特定情况使用新引入的range types,{{1}} The manual provides a full code example with an exclusion constraint.

答案 1 :(得分:3)

PostgreSQL需要命名类型和运算符类才能使排除约束起作用。在9.1中,RANGE尚未实施。

您可以定义自己的权限,但这需要超级权限(即,不会对托管数据库等有效)。

您可以尝试将时间戳转换为框并使用intersects运算符(&&)定义约束:

CREATE FUNCTION ts_to_box(TIMESTAMPTZ, TIMESTAMPTZ)
RETURNS BOX
AS
$$
    SELECT  BOX(POINT(DATE_PART('epoch', $1), -1), POINT(DATE_PART('epoch', $2), 1))
$$
LANGUAGE 'sql'
IMMUTABLE;

CREATE TABLE t (
    fromts timestamptz, 
    tots timestamptz,
    EXCLUDE USING GIST (ts_to_box(fromts, tots) WITH &&)
);