3

I am currently working with a bitemporal application, which stores data entries using 4 timestamps:

Valid_from, Valid_to
Registration_from, Registration_to

The first two state when the given entry is valid_from and valid_to, and the other two are when the entry has been registered_from, and assumed as true until registration_to.

In this time setting I need to make sure that each row has unique column within the same valid_from and valid_to known within the same registration_from and registration_to across multiple entries.

So I need to check every row before insertion (pseudo-code):

If registration period is overlapping
    If Valid period is overlapping 
        Check if properties are the same 
            Throw error if they are

I have tried with an exclusion like this:

ADD Constraint exclusion_reg_{entity.InternalName}_registration_{string.Join('_', listOfAttributes)}_key Exclude using gist({string.Join(',', listOfAttributes.Select(x => x + " with =").ToList())} , registration WITH &&);

But I am not sure whether I am using it correctly. I am currently always getting an error, since the check is done in opposite order, and among the incorrect ones. Is there a way to make this exclusion check nested, such that it only check validation overlap if the registration is overlapping, and throws an error if this is true?

How do I go about that in PostreSQL?

4

1 回答 1

2

只需在排除约束中列出两个范围。

ALTER TABLE tbl ADD CONSTRAINT foo
EXCLUDE USING gist (attribute_1 WITH =, attribute_2 WITH =  -- more?
                  , tsrange(valid_from, valid_to) WITH &&
                  , tsrange(registration_from, registration_to) WITH &&);

几周前我用更多解释回答了您的相关(更简单)问题后,可以肯定地假设基本的基础知识已经很清楚了。其他人可能想先阅读以下内容:

为了强制执行您的约束,表达式的顺序甚至无关紧要。考虑排除约束如何操作的手册中的基本定义:

排除约束确保如果使用指定的运算符在指定的列或表达式上比较任意两行,这些运算符比较中的至少一个将返回 false 或 null

这有效地执行了您的约束:只有当所有表达式的计算结果true, in other words, 重叠并且所有属性都完全匹配时,约束才会引发异常。

但是,由于约束是通过使用相应的多列 GiST 索引来实现的,所以表达式的顺序毕竟对性能很重要。手册:

多列 GiST 索引可以与涉及索引列的任何子集的查询条件一起使用。附加列上的条件限制了索引返回的条目,但第一列上的条件是确定需要扫描多少索引的最重要条件。如果 GiST 索引的第一列只有几个不同的值,即使附加列中有许多不同的值,它也会相对无效。

因此,重新排列表达式以首先将具有最不同值的表达式放在列中。

于 2020-07-06T22:28:35.177 回答