2

我需要确保我的数据库只包含其中两个或更多列是唯一的条目。UNIQUE这可以通过对这些列的约束轻松实现。

就我而言,我只需要禁止重叠时间范围的重复。该表有valid_fromvalid_to列。在某些情况下,可能首先需要通过设置使活动条目过期valid_to = now,然后插入一个调整为valid_from = nowand的新条目valid_to = infinity

我似乎可以在没有任何问题的情况下使先前的条目过期UPDATE,但是插入新条目似乎很麻烦,因为我的基列当前是UNIQUE,因此无法再次添加。

我想添加valid_fromandvalid_to作为UNIQUE约束的一部分,但这只会使约束更加松散,并允许存在重复重叠的时间范围。

如何进行约束以确保不存在重叠的重复项valid_fromvalid_to tsrange

我似乎在寻找EXCLUDE USING GIST,但它似乎不支持多列?这似乎对我不起作用:

ALTER TABLE registration 
DROP Constraint IF EXISTS registration_{string.Join('_', listOfAttributes)}_key, 
ADD Constraint registration_{string.Join('_', listOfAttributes)}_key EXCLUDE USING GIST({string.Join(',', listOfAttributes)} WITH =, valid WITH &&);
4

1 回答 1

2

你走在正确的轨道上。但是排除约束的语法略有不同。

根据未公开的表定义,您可能需要先安装扩展(附加模块)btree_gist。每分贝一次。我的示例需要它,因为integer默认情况下没有为 type 安装所需的运算符类:

CREATE EXTENSION btree_gist;

看:

然后:

CREATE TABLE registration  (
  tbl_id integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY
, col_a  integer NOT NULL
, col_b  integer NOT NULL
, valid_from timestamp
, valid_to   timestamp
, CONSTRAINT no_overlap
    EXCLUDE USING gist (col_a with =, col_b with =, tsrange(valid_from, valid_to) WITH &&)
);

每列都需要列出其各自的运算符。

你需要一个范围类型。您提到单独的列valid_fromvalid_to. 您还在失败的命令中提到tsrangeand valid。这很令人困惑。假设有两timestamp列,带有表达式的表达式索引tsrange(valid_from, valid_to)就可以了。

有关的:

通常,应选择 ( ) 而非timestamptz( ) 。看:tstzrangetimestamptsrange


也许registration,一个优秀的设计将是您的表和新表中的 1-N 个条目之间的一对多关系registration_range。还有一些逻辑来确定当前有效的条目(对于任何给定的时间点)。取决于更多未公开的信息。

于 2020-05-13T16:31:16.763 回答