【问题标题】:To Fully Enforce Your Data Model or To Not Fully Enforce Your Data Model完全执行您的数据模型或不完全执行您的数据模型
【发布时间】:2009-07-17 19:12:46
【问题描述】:

http://weblogs.sqlteam.com/jeffs/archive/2008/08/13.aspx:

考虑以下逻辑数据模型:
* 有多家公司
* 每个公司都有很多项目
* 每个项目都有很多任务
* 每个任务都有一个状态,从预定义状态的全局列表中选择。

假设我们决定公司、项目、任务和状态的主键都是身份(自动编号)列,因为我们想为这些表自动生成主键。

所以基本上,我们有 4 个表:
Status (PK: StatusID)
公司(PK:CompanyID)
项目(PK:ProjectID,FK:[Companies].CompanyID)
任务(PK:TaskID,FK:[Projects].ProjectID,[Status].StatusID)。

现在,请允许我添加一点皱纹。假设每个任务的可用状态不是全局定义的,而是在公司级别定义的。也就是说,每个公司都有自己的状态列表,可以分配任务。

这意味着状态表现在需要对公司表的外键引用(以指示每个状态属于哪个公司):

公司(PK:CompanyID)
状态(PK:StatusID,FK:[Companies].CompanyID)
项目(PK:ProjectID,FK:[Companies].CompanyID)
任务(PK:TaskID,FK:[Projects].ProjectID,[Status].StatusID)。

我们还需要对此数据模型进行任何其他更改吗?或者只是将 CompanyID 列添加到 Status 表就足以促进这种变化?请记住,我们的目标始终是尽可能使用主键和外键约束的完全参照完整性。

嗯,有一个问题:

此数据模型中的任何内容都不会阻止我们将状态分配给未为该任务的母公司定义的任务。在我们目前的限制条件下,我们现在无法执行此操作。我们的物理数据模型存在缺陷。

这很容易解决,但只能通过违反“所有表只需要一个身份主键”的规则来解决。

首先,记住这一点:仅仅因为标识列是唯一的并不意味着该列不能是主键的部分

他接着指出如何使用复合键来完全强制和约束您的数据模型,如下所示:

公司(PK:CompanyID)
状态(PK:CompanyID、StatusID,FK:[Companies].CompanyID)
项目(PK:CompanyID、ProjectID、FK:[Companies].CompanyID)
任务(PK:TaskID,FK:[Projects]。(CompanyID,ProjectID),[Status]。(CompanyID,StatusID))。

长期以来,我一直热衷于完全强制/约束我的数据模型,但是,我经常发现自己处于与上述类似的情况,并且我走到了一个十字路口:

完全执行或不完全执行。

这样做的明显缺点是看似过于复杂的设计。

现在,我知道不一定有“正确”的设计,但对于这样的情况.. 我正在寻找最佳实践方面的反馈。

关于此设计或完全执行您的数据模型设计的优点、缺点和一般想法?

**请注意,这个问题可能会引发关于在执行数据模型(数据库或应用程序或两者)方面责任在哪里的争论。为了便于讨论,我认为您的数据模型应该自行执行——请在此假设下回答。 **

【问题讨论】:

  • 应用程序和数据库层应该执行数据模型的规则。由于规则应该由另一个加强。
  • 原文有一个归一化错误(正如OrbMan指出的);会给作者留下评论,但没有看到 cmets 选项

标签: database sql-server-2005 database-design


【解决方案1】:

我将创建一个CompanyStatus 表,它是CompanyStatus 之间的多对多表,并描述了哪些状态适用于给定公司。然后,任务被分配一个CompanyStatusID 而不是StatusID

这还可以防止您在 Status 表中出现重复的状态 - 例如,许多公司可以共享相同的已关闭状态,这是更好的规范化。

因此,您无需使用复合键来正确执行约束。我更喜欢使用没有意义的单个自动增量主键(代理键)。这比假设密钥是唯一的(例如 SSN)更可靠,因为总是有机会证明并非如此,但无论如何您都必须存储数据,因为应用程序需要它(所以唯一的约束在这里没有帮助)。

【讨论】:

  • 这是正确/规范化的设计,不是问题中列出的设计,尽管在 Task 表中使用 StatusId 如果不是更好的话也可以(CompanyStatus 仅用于过滤初始分配)
  • 我不会对项目做同样的事情,除非多个公司可以与同一个项目相关联,而我没有从需求中得到这一点。我确实理解基本前提,即您可以使用复合键来获得比使用代理更好的完整性。这是设计模型时要考虑的事情;就个人而言,我还没有找到一个决定走这条路的场合——我怀疑我更有可能因为在查询中错误输入冗长的复合键而出错,而不是因为代理键可能给你的约束丢失。
  • 添加 CompanyStatus 表将允许您拥有来自一家公司的项目和来自另一家公司的状态的任务。不过,除此之外,我真的在考虑完全执行数据模型方面的最佳实践。
猜你喜欢
  • 1970-01-01
  • 2013-06-02
  • 2010-10-25
  • 2011-04-11
  • 1970-01-01
  • 2015-12-30
  • 1970-01-01
  • 2022-08-02
  • 1970-01-01
相关资源
最近更新 更多