【发布时间】: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