如何确保条目具有不重叠的时间范围?
How to ensure entries with non-overlapping time ranges?
我需要确保我的数据库只包含其中两个或更多列是唯一的条目。这可以很容易地通过对这些列的 UNIQUE
约束来实现。
就我而言,我需要仅针对重叠的时间范围禁止重复。 table 有 valid_from
和 valid_to
列。在某些情况下,可能首先需要通过设置 valid_to = now
使活动条目过期,然后插入调整为 valid_from = now
和 valid_to = infinity
的新条目。
我似乎能够使用 UPDATE
毫无问题地使先前的条目过期,但插入新条目似乎很麻烦,因为我的基本列目前是 UNIQUE
,因此不能'不再添加。
我想添加 valid_from
和 valid_to
作为 UNIQUE
约束的一部分,但这只会使约束更加宽松,并允许
复制 和 重叠的时间范围。
如何进行约束以确保不存在重叠 valid_from
和 valid_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;
参见:
- PostgreSQL EXCLUDE USING error: Data type integer has no default operator class
- How to use (install) dblink in PostgreSQL?
然后:
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_from
和 valid_to
。并且您还在失败的命令中提到了 tsrange
和 valid
。这令人困惑。假设有两个 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
)。参见:
- Ignoring time zones altogether in Rails and PostgreSQL
- Don't use timestamp (without time zone)
也许,更好的设计是你的registration
table和新[中的1-N条目之间的一对多关系=24=] table。以及确定当前有效条目的一些逻辑(对于任何给定的时间点)。取决于更多未公开的信息。
我需要确保我的数据库只包含其中两个或更多列是唯一的条目。这可以很容易地通过对这些列的 UNIQUE
约束来实现。
就我而言,我需要仅针对重叠的时间范围禁止重复。 table 有 valid_from
和 valid_to
列。在某些情况下,可能首先需要通过设置 valid_to = now
使活动条目过期,然后插入调整为 valid_from = now
和 valid_to = infinity
的新条目。
我似乎能够使用 UPDATE
毫无问题地使先前的条目过期,但插入新条目似乎很麻烦,因为我的基本列目前是 UNIQUE
,因此不能'不再添加。
我想添加 valid_from
和 valid_to
作为 UNIQUE
约束的一部分,但这只会使约束更加宽松,并允许
复制 和 重叠的时间范围。
如何进行约束以确保不存在重叠 valid_from
和 valid_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
:
CREATE EXTENSION btree_gist;
参见:
- PostgreSQL EXCLUDE USING error: Data type integer has no default operator class
- How to use (install) dblink in PostgreSQL?
然后:
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_from
和 valid_to
。并且您还在失败的命令中提到了 tsrange
和 valid
。这令人困惑。假设有两个 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
)。参见:
- Ignoring time zones altogether in Rails and PostgreSQL
- Don't use timestamp (without time zone)
也许,更好的设计是你的registration
table和新[中的1-N条目之间的一对多关系=24=] table。以及确定当前有效条目的一些逻辑(对于任何给定的时间点)。取决于更多未公开的信息。