【问题标题】:Constraints on bitemporal database双时态数据库的约束
【发布时间】:2013-10-03 16:16:10
【问题描述】:

背景:

我正在设计一个双时态数据库,我们在双时态表之间有 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 theVersionDate` 列放入两个数据表中。
  • StartDateEndDate 列是双时态的有效时间 维度。是的,EndDate 有点多余,我们可以只用StartTime 对表格进行建模。
  • 两个表的Id 列是新的主键。因为我们对同一个实体有多个行(多个版本,有效时间中的多个日期范围),实体的ID不能是表的主键。 OrderIdOrderItemId 列是实体的 ID,但不再是表的主键。除了创建新的主键 Id,我们还可以将主键定义为 (OrderId, VersionId, StartDate)
  • 如果删除了一个实体,我们只需创建一个新的版本条目,以及在实体表中使用IsDeleted = 1 的条目。表中的所有其他条目(插入和更新)都有IsDeleted = 0
  • tblOrderitem 的列 FK_OrderId 引用了 tblOrder 的列 OrderId。这不再是真正的外键(在数据库约束的意义上),因为 OrderId 不再是主键。但它仍然告诉我们哪些 OrderItems 是某个 Order 的一部分。

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

问题:

我需要什么样的约束才能使其始终如一地工作?

我对如何实现约束不感兴趣(是否将它们实现为数据库约束,如FOREIGN KEYs 或UNIQUE 约束,或TRIGGERs,或CHECKs,等等)。我只需要知道我需要哪些类型约束。

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

【问题讨论】:

    标签: constraints temporal temporal-database


    【解决方案1】:

    (我使用缩写 PIVT = 'point in valid time'。这表示 valid time 维度上的某个时间点)

    这是我已经想到的约束:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-03
      • 1970-01-01
      相关资源
      最近更新 更多