简体   繁体   English

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

[英]How to ensure entries with non-overlapping time ranges?

I need to ensure my database only contains entries where two or more of its columns are unique.我需要确保我的数据库只包含其中两个或更多列是唯一的条目。 This can easily be achieved with a UNIQUE constraint over those columns.这可以通过对这些列的UNIQUE约束轻松实现。

In my case, I need to forbid duplication only for overlapping time ranges.就我而言,我只需要禁止重叠时间范围的重复。 The table has valid_from and valid_to columns.该表具有valid_fromvalid_to列。 In some cases one might first need to expire the active entry to by setting valid_to = now , and then inserting a new entry adjusted to valid_from = now and valid_to = infinity .在某些情况下,可能首先需要通过设置valid_to = now来使活动条目过期,然后插入一个调整为valid_from = nowvalid_to = infinity的新条目。

I seem to be able to expire the prior entry without any problems using UPDATE , but inserting the new entry seems to be troublesome since my base columns are currently UNIQUE , and therefore can't be added again.我似乎可以使用UPDATE使先前的条目过期而没有任何问题,但是插入新条目似乎很麻烦,因为我的基列当前是UNIQUE ,因此无法再次添加。

I thought of adding valid_from and valid_to as part of the UNIQUE constraint, but that would just make the constraint more loose, and allow duplicates and overlapping time ranges to exist.我想添加valid_fromvalid_to作为UNIQUE约束的一部分,但这只会使约束更加松散,并允许存在重复重叠的时间范围。

How do I make a constraint to ensure that duplicates don't exist with overlapping valid_from and valid_to tsrange ?如何进行约束以确保不存在重叠valid_fromvalid_to tsrange的重复项?

I seem to be looking for EXCLUDE USING GIST , but it does not seem to support multiple columns?我似乎在寻找EXCLUDE USING GIST ,但它似乎不支持多列? This does not seem to work for me:这似乎对我不起作用:

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 &&);

You were on the right track.你走在正确的轨道上。 But the syntax for exclusion constraints is slightly different.但是排除约束的语法略有不同。

Depending on the undisclosed table definition, you may need to install the extension (additional module) btree_gist first.根据未公开的表定义,您可能需要先安装扩展(附加模块) btree_gist Once per db.每分贝一次。 It's needed for my example since the required operator class is not installed for type integer by default:我的示例需要它,因为默认情况下没有为类型integer安装所需的运算符 class :

CREATE EXTENSION btree_gist;

See:看:

Then:然后:

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 &&)
);

Each column needs to be listed with its respective operator.每列都需要列出其各自的运算符。

And you need a range type .你需要一个范围类型 You mention separate columns valid_from and valid_to .您提到了单独的列valid_fromvalid_to And you also mention tsrange and valid in the failed command.而且您还在失败的命令中提到tsrangevalid That's confusing.这很令人困惑。 Assuming two timestamp columns, an expression index with the expression tsrange(valid_from, valid_to) would do it.假设有两个timestamp列,一个带有表达式tsrange(valid_from, valid_to)的表达式索引可以做到这一点。

Related:有关的:

Typically, timestamptz ( tstzrange ) should be chosen over timestamp ( tsrange ).通常,应该选择timestamptz ( tstzrange ) 而不是timestamp ( tsrange )。 See:看:


Maybe , a superior design would be a one-to-many relationship between your registration table and 1-N entries in a new registration_range table.也许,一个优秀的设计将是您的registration_range registration中的1-N 个条目之间的一对多关系。 And some logic to determine the currently valid entry (for any given point in time).还有一些逻辑来确定当前有效的条目(对于任何给定的时间点)。 Depends on more undisclosed information.取决于更多未公开的信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM