如何确保条目具有不重叠的时间范围?

How to ensure entries with non-overlapping time ranges?

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

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

我似乎能够使用 UPDATE 毫无问题地使先前的条目过期,但插入新条目似乎很麻烦,因为我的基本列目前是 UNIQUE,因此不能'不再添加。

我想添加 valid_fromvalid_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 &&);

你走在正确的轨道上。但是 syntax for exclusion constraints 略有不同。

根据未公开的 table 定义,您可能需要先 install the extension (additional module) btree_gist。每个数据库一次。此解决方案需要为类型 integer:

提供所需的运算符 class
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 (<b>col_a with =, col_b with =, tsrange(valid_from, valid_to) WITH &&</b>)
);

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

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

相关:

  • Perform this hours of operation query in PostgreSQL
  • Non-overlap, continuous timestamp ranges (tstzrange) for opening hours
  • Store the day of the week and time?

通常,应选择 timestamptz (tstzrange) 而不是 timestamp (tsrange)。参见:


也许,更好的设计是你的registrationtable和新[中的1-N条目之间的一对多关系=24=] table。以及确定当前有效条目的一些逻辑(对于任何给定的时间点)。取决于更多未公开的信息。