对双时态数据库的约束

时间:2013-10-03 16:16:11

标签: constraints temporal temporal-database

背景

我正在设计一个双时态数据库,我们在双时态表之间有1:N关系(我们也有M:N关系,但它们只是用连接器表和两个1:N关系建模,所以我考虑他们是1:N关系的特例。

为了说明这一点,让我们考虑一个包含两个表的简单案例:

|===============|        |==================|
|   tblOrder    |        |   tblOrderItem   |
|============== |        |==================| 
| - OrderId     |        | - OrderItemId    |
| - OrderNumber |        | - FK_OrderId     |
|===============|        | - Amount         |
                         |==================|

FK_OrderIdtblOrder的外键。

为了使这个数据库模型具有双时态性,我提出了以下设计:

|===============|        |==================|        |====================|
|   tblOrder    |        |   tblOrderItem   |        |   tblVersions      |
|============== |        |==================|        |====================|
| - Id          |        | - Id             |        | - VersionId        |
| - OrderId     |        | - OrderItemId    |        | - VersionDate      |
| - OrderNumber |        | - FK_OrderId     |        |====================|
| - VersionId   |        | - Amount         |
| - IsDeleted   |        | - VersionId      |
| - StartDate   |        | - IsDeleted      |
| - EndDate     |        | - StartDate      |
|===============|        | - EndDate        |
                         |==================|

说明:

  • VersionId列是tblVersions表的外键。对于数据库中的每个更改,都会创建tblVersions表中的条目。那么数据的当前状态就是所有版本的总和。这样就可以重建数据库的先前状态(通过 WHERE VersionDate < ... 子句)。这是双重时间的交易时间维度。
  • tblVersions table could also be avoided if we're just including the VersionDate列列入两个数据表。
  • StartDateEndDate列是双重时间的有效时间维度。是的,EndDate有点多余,我们可以使用StartTime建模表格。
  • 两个表的Id列是新的主键。由于同一实体有多行(多个版本,有效时间内的多个日期范围),因此实体的ID不能是表的主键。列OrderIdOrderItemId是实体的ID,但不再是表的主键。我们也可以将主键定义为Id,而不是创建新的主键(OrderId, VersionId, StartDate)
  • 如果删除了实体,我们只需创建一个新的版本条目,以及实体表中带有IsDeleted = 1的条目。表中的所有其他条目(插入和更新)都有IsDeleted = 0
  • FK_OrderId的{​​{1}}列引用了tblOrderitem的{​​{1}}列。这不再是真正的外键(在数据库约束的意义上),因为OrderId不再是主键。但它仍然告诉我们哪个OrderItems是某个Order的一部分。

这似乎运作良好,我们已经创建了必要的CRUD查询,并且能够读取和写入双时态数据。

问题:

我需要哪些约束才能始终如一地工作?

我对如何实现约束感兴趣(是否将它们实现为数据库约束,如tblOrderOrderId约束,或FOREIGN KEY s,或{{1}无论如何)。我只需要知道我需要的类型约束。

我想出了一些约束,我将作为答案发布。但也许还有更多?

1 个答案:

答案 0 :(得分:0)

(我使用缩写 PIVT ='有效时间点'。这表示有效时间维度上的特定时间点)

以下是我已经想到的限制:

  • FK_VersionId :显然,我们需要VersionId列的标准外键约束。
  • 双时态唯一性此外,组合(OrderId, VersionId, StartDate)必须是唯一的(tblOrderItem也是如此)。
  • 有效时间序列化:我们需要检查每个实体和每个版本,有效时间中没有重叠,即列StartDateEndDate不重叠,StartDate始终早于EndDate
  • 删除完整性:我们需要确保每个实体和每个PIVT最多有一行IsDeleted = 1,如果有这样的行,则一定不能任何版本的实体那一行之后。
  • 参照完整性:我们需要检查每个OrderItem实体,每个版本和每个PIVT,FK_OrderId的值是否设置为标识存在于的Order实体的值给定的PIVT,已插入早期版本但尚未删除(通过设置IsDeleted = 1)。