C# 如何确保输入的时间范围不重叠?

C# 如何确保输入的时间范围不重叠?,c#,sql,postgresql,database-design,exclusion-constraint,C#,Sql,Postgresql,Database Design,Exclusion Constraint,我需要确保我的数据库只包含两个或更多列是唯一的条目。这可以通过对这些列使用唯一的约束轻松实现 在我的例子中,我只需要在重叠的时间范围内禁止复制。该表有valid\u from和valid\u to列。在某些情况下,可能首先需要通过设置valid\u to=now,然后插入调整为valid\u from=now和valid\u to=infinity的新条目,使活动条目过期 使用UPDATE,我似乎可以在没有任何问题的情况下使以前的条目过期,但是插入新条目似乎很麻烦,因为我的基本列当前是唯一的,因

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

在我的例子中,我只需要在重叠的时间范围内禁止复制。该表有
valid\u from
valid\u to
列。在某些情况下,可能首先需要通过设置
valid\u to=now
,然后插入调整为
valid\u from=now
valid\u to=infinity
的新条目,使活动条目过期

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

我曾想过将
valid\u从
添加到
,并将
valid\u添加到
,作为
UNIQUE
约束的一部分,但这只会使约束更加松散,并允许 存在重复和重叠的时间范围

如何进行约束以确保不存在重叠的
valid\u from
valid\u to
tsrange

我似乎在寻找使用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 &&);

你在正确的轨道上。但情况略有不同

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

CREATE EXTENSION btree_gist;
见:

然后:

创建表注册(
tbl_id默认情况下作为标识生成的整数主键
,col_是一个不为空的整数
,列b整数不为空
,从时间戳开始有效
,对时间戳有效
,约束无重叠
排除使用gist(列a与=、列b与=、tsrange(有效列from、有效列to)与&&)
);
每个列都需要列出其各自的运算符

你需要一个范围类型。您提到了从
的独立列
valid\u和
valid\u到
。您还可以在失败的命令中提到
tsrange
valid
。那太令人困惑了。假设有两列
timestamp
列,则使用表达式
tsrange(valid\u from,valid\u to)
的表达式索引即可

相关的:

通常,
timestamp
tstzrange
)应该选择在
timestamp
tsrange
)之上。见:


也许,一个更好的设计是您的
注册
表与新的
注册范围
表中的1-N个条目之间的一对多关系。和一些逻辑来确定当前有效的条目(对于任何给定的时间点)。取决于更多未披露的信息。

准确(最小)的表定义将是有用的(
CREATE table
语句)。永远是你的博士后版本。另外,为什么您的解决方案似乎不起作用?有错误消息吗?您可以免费安装扩展吗?
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 &&)
);