【问题标题】:Relations vs data constraints in database design数据库设计中的关系与数据约束
【发布时间】:2022-01-19 14:00:19
【问题描述】:

为了简化描述,假设我们有一个带有 TimeScopes(ID、start、end)的 DB 模型和带有 FK(TimeScopes.ID)的进程,这是一对多的关系,所有进程都持有一个引用到 TimeScopes.ID 在给定的时间范围内运行。

首先,您定义一个时间范围并选择在该时间范围内运行的多个进程。

TimeScopes
  |__
     Processes

应用程序中有一些额外的限制(目前数据库中没有数据库触发器),例如假设 TimeScope 不重叠 - 当时只有一个 TimeScope 可能处于活动状态。

现在我有一个新的要求,即添加一些可以在任何时候不受任何限制地启动的新进程 - 所以实际上它们不必这样做,但它们可以同时运行(并行)。

在这种情况下,有人会先定义流程,然后将其分配给这样一个新的、单一的流程多个时间范围,没有前面提到的约束。所以这将是一个进程与许多 TimeScopes 的完全相反的关系。

Processes
  |__
     TimeScopes

我正在寻求有关如何解决问题的帮助和建议?

从关系的角度来看,我可以通过添加一个表来定义两个方向的关系,将 TimeScopes 和 Processes 之间的关系调整为多对多。

TimeScopes
  |__
   __ TP-Relations
  |
Processes

让我不确定的是现有模型的额外时间限制。这促使我考虑另一种解决方案,并为 NewProcesses 和 NewTimeScopes 定义一个单独的表

NewProcesses
  |__
     NewTimeScopes

随后使用 UNION 语句在查询中合并两个模型之间的结果。

哪个更好?还有其他或更好的想法吗?

更新/改写问题

假设我们通过附加的“AB”(联结)表建立了多对多关系中的实体“A”和“B”。

对于一些以一对多关系表示 A->B 的记录,关于 A 记录还有一些额外的限制。假设我们有一些触发器来观察 A 中的每条记录不会跨越另一个 A 记录的边界。

对于以一对多关系表示 B->A 的其他记录,这些边界并不总是可接受的,因此不应强制/检查。

问题:如何处理这样的问题?

  • 修改模型/关系,如何?
  • 修改触发器?但是在数据库级别上是否甚至可以识别为 A->B 与 B->A 关系输入一些记录?

【问题讨论】:

  • 我正在阅读您的信息,我无法确定流程和时间范围之间的关系。我曾经使用过的每个作业调度系统都只处理进程。
  • @GilbertLeBlanc 我不确定在不参考时间范围的情况下如何安排任何事情? Cronjobs 怎么样?您定义时间范围(不是根据开始和结束,而是根据频率)以及要执行的脚本,对吗? Cron 不会检查是否有任何其他作业同时运行,因此即使我在更一般/抽象的上下文中使用它,这也可以说明我的 NewProcess 要求。
  • 进程一触发进程二。进程三必须等待进程一完成才能开始。进程四是独立的,可以随时启动。时间参考在哪里?我熟悉的唯一时间参考是批处理作业窗口从下午 6 点开始,那时每个人都回家休息。
  • 您能列出属于“实体”的表吗?然后注意 1:many "relationships" 需要一个表中的 id 才能链接到另一个表。 Many:many 关系之间需要一个联结表。
  • 我不确定我是否理解。以下是真的吗? - 一个时间范围可以有多个进程 - 一个进程可以属于多个时间范围 - 一个时间范围不应与另一个时间范围有重叠的开始或结束

标签: mysql database-design


【解决方案1】:

根据 cmets,以下情况似乎是正确的:

  • 一个时间范围可以有多个进程
  • 一个进程可以属于多个时间范围
  • 时间范围不应与另一个时间范围有重叠的开始或结束如果时间范围有多个进程。

我会把它分成两个问题:

我应该如何建模流程和时间范围之间的关系?

这似乎是一个简单的多对多关系,所以我会按照你的建议包含一个连接表。

我应该如何确保关于重叠时间范围的业务规则?

我认为您不能通过模型​​中的实体关系来强制执行此操作。然后,您有几个选择 - 如果您必须在数据库级别实现它,关系表上的触发器应该可以完成这项工作 - 您的规则仅适用于给定时间范围内有超过 1 个进程的情况,这将导致连接表上的插入或更新事件。

我不是触发器的忠实拥护者 - 它们难以测试、难以调试,并且可能导致性能问题。如果可能的话,我会在应用层实现这个。

是否应该将不同类型的时间范围/进程存储在不同的表中?

这部分是哲学的,部分是实用的。通常,您应该将相似类型的实体存储在同一个表中。特别是如果它们的行为不同,但属性不同;不要重复你自己和所有这些。

如果您有不同的验证规则,但属性相同,我会将它们保存在一个表中。

这都取决于“可理解性” - 如果您的系统描述哺乳动物,将“人类”和“猫”放在同一张表中并使用类型鉴别器可能没问题。如果您的系统描述了“humans”和“tables”,那么两者都具有“leg_count”属性这一事实并不是将它们保留在同一个表中的理由。

【讨论】:

  • 感谢您的回答。我也在考虑另一种解决方案,因为我们清楚地谈到了两种类型的过程,它们在时间范围方面有所不同。我正在考虑为“其他”类型的流程创建另一个表的想法(也许也是一个单独的时间范围)?我不确定关系表上的触发器是否也可以检查和过滤仅属于一种类型进程的时间范围的开始和结束 - 不是全部。我不打算编写触发器,只是想知道 RDB 是否以及如何解决此类问题?
  • P.S.我正在处理已经处理第一类进程的应用程序,我现在需要添加和处理另一种类型。所以所有的触发器和检查都会发生在应用层,但我试图弄清楚哪种方式继续前进会更好/更清洁等,因为它似乎会以某种方式变得一团糟。跨度>
猜你喜欢
  • 2016-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-30
  • 1970-01-01
相关资源
最近更新 更多