2009-07-17 17 views
1

http://weblogs.sqlteam.com/jeffs/archive/2008/08/13.aspx充分执行你的数据模型或不充分执行你的数据模型

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

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

因此,基本上,我们有4个表:
状态(PK:StatusID)
公司(PK:CompanyID)
项目(PK:专案编号,FK:[公司] .CompanyID)
任务(PK:TaskID,FK:[Projects] .ProjectID,[Status] .StatusID)。

现在,让我补充一点点皱纹。假设每个任务的可用状态不是全局定义的,而是公司层面的。也就是说,每个公司都有自己的状态列表,任务可以分配到该状态列表。

这意味着,状态表现在需要一个外键参照公司表(指示哪些公司每一个状态属于):

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

我们需要对此数据模型做出其他更改吗?或者只是简单地将一个CompanyID列添加到状态表中足以促进此更改?请记住,我们的目标始终是尽可能使用主键和外键约束的完整参照完整性。

那么,有一个问题:在这个数据模型

没有阻止我们分配状态到未针对该任务的母公司定义的任务。现在我们无法通过我们目前的限制来执行这项权利。我们的物理数据模型存在缺陷。

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

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

他接着指出键怎么复合材料可以用来完全执行和像这样的东西限制你的数据模型:

公司(PK:CompanyID)
状态(PK:CompanyID,StatusID (PK:公司ID,项目ID),[项目ID] [公司ID,项目ID],[项目ID] [公司ID] [项目ID]
项目(PK:CompanyID,ProjectID,FK:[公司]] Company
任务(CompanyID,StatusID))。

我长久以来一直是充分执行/限制我的数据模型迷,但是,我常常发现自己在类似上述情况,我来到一个十字路口:

充分强制执行或不完全执行。

明显的缺点是看起来过于复杂的设计。

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

这个设计的优点,缺点和一般想法或完全实施您的数据模型设计?

**请注意,这个问题可能引发关于责任在执行数据模型(数据库或应用程序或两者)方面的争论。为了讨论起见,我相信您的数据模型应该自行实施 - 请根据这种推定来回答。 **

+0

应用程序和数据库层应该强制执行数据模型的规则。这样可以更容易地发现错误,因为规则*应该由另一方来加强。 – 2009-07-17 19:29:36

+0

原文有规范化错误(OrbMan指出);会给作者留下评论,但看不到任何评论选项 – 2009-07-17 19:35:00

回答

2

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

这也防止你在你的Status表中重复状态 - 很多企业可以共享例如同一关闭状态,这是更好的正常化。

因此,您不需要使用复合键来正确执行约束。我更喜欢使用无意义的单自动增量主键(代理键)。比起假定密钥是唯一的(比如SSN)更加可靠,当总是有可能变成不是这样的情况时,你仍然必须存储数据,因为应用程序需要它(所以一个独特的约束在这里没有帮助)。