防止在开始时间,结束时间列中重叠时间

时间:2014-09-17 12:02:49

标签: postgresql database-design constraints

我们有一个用例,我们将start_week和end_week连续存储,并希望确保跨行的这些值永远不会重叠,即它们是独占的。以下示例

Ideal
code - startw - endw
T1 - 201401 - 201404
T2 - 201405 - 201408
T3 - 201409 - 201416

Not Ideal
code - startw - endw
T1 - 201401 - 201404
T2 - 201403 - 201408
T3 - 201407 - 201408
T3 - 201406 - 201410

可以在Postgres中添加这样的约束,以便在插入过程中捕获错误吗?在插入数据后,解决此类问题并避免插入而不是运行检查的最佳方法是什么。

1 个答案:

答案 0 :(得分:4)

PostgreSQL有一个专门为此设计的功能 - exclusion constraints

请参阅CREATE TABLE ... EXCLUDE ...

出于您的目的,您需要constraint on a range。您所拥有的案例将在手册中介绍。

你的日期使用了一种奇怪的格式,这有点复杂;您需要将它们转换为排除约束的tstzrange。

create table exclude(code text, startw integer, endw integer);

insert into exclude(code, startw, endw) values
('T1', 201401, 201404),
('T2', 201405, 201408),
('T3', 201409, 201416);

你不能只是:

alter table exclude 
  add constraint no_overlapping_timestamps 
  EXCLUDE USING gist( tstzrange(startw, endw) WITH && );

因为你没有使用真正的时间戳;你必须将你的周数转换为上面表达式中的时间戳。我不能为你做那件事,因为我不知道你如何定义"周"。如果它是标准方式,那么:

alter table exclude 
  add constraint no_overlapping_timestamps 
  EXCLUDE USING gist( tstzrange(to_date(startw, 'YYYYWW'), to_date(endw, 'YYYYWW')) WITH && );