在单个列中使用来自多个表的 ID

DCN*_*YAM 6 normalization foreign-key database-design

我的一位同事创建了一个类似于以下的架构。这是一个简化的模式,仅包括解决此问题所需的部分。

系统规则如下:

  1. 部门可以有 0 到多个部门。
  2. 一个部门必须只属于一个部门。
  3. 一篇文章可以分配给一个部门,也可以分配给该部门的一个部门。

架构是:

Department
---------- 
DepartmentID (PK) int NOT NULL
DepartmentName varchar(50) NOT NULL

Division
--------
DivisionID (PK) int NOT NULL
DepartmentID (FK) int NOT NULL
DivisonName varchar(50) NOT NULL

Article
-------
ArticleID (PK) int NOT NULL
UniqueID int NOT NULL
ArticleName varchar(50) NOT NULL
Run Code Online (Sandbox Code Playgroud)

他使用一个虚构的规则(因为没有更好的术语)定义了模式,即所有 DepartmentID 都在 1 到 100 之间,所有 DivisionID 都在 101 到 200 之间。他指出,在查询文章表时,您将知道是否UniqueID 来自 Department 表或 Division 表,具体取决于它所属的范围。

我认为这是一个糟糕的设计,并提出了以下替代方案:

Department
----------
DepartmentID (PK) int NOT NULL
ParentDepartmentID (FK) int NULL /* Self-referencing foreign key.  Divisions have parent departments. */
DepartmentName varchar(50) NOT NULL

Article
-------
ArticleID (PK) int NOT NULL
DepartmentID (FK) int NOT NULL
ArticleName varchar(50) NOT NULL
Run Code Online (Sandbox Code Playgroud)

我相信这是一个正确规范化的模式,并正确地强制执行关系和数据完整性,同时遵守上面概述的业务规则。

我的具体问题是:

我知道使用一列来包含来自两个域的值是糟糕的设计,我可以论证文章表中外键的好处。但是,有人可以提供我可以用来支持我的立场的特定数据库设计文章/论文的参考。如果我能指出一些具体的东西,它会让事情变得容易得多。

gbn*_*gbn 5

您的自我参考可能会在部门内引入部门的层次结构。您需要代码(通常是触发器)来确保没有分区允许这样做。

使用编码的原始模式也被破坏了。你没有可执行的 FK

就个人而言,我会考虑使用检查约束来确保每行只填充 DepartmentID 和 DivisionID 之一

Article
-------
ArticleID (PK) int NOT NULL
DepartmentID (FK) int NULL
DivisionID (FK) int NULL
ArticleName varchar(50) NOT NULL
Run Code Online (Sandbox Code Playgroud)

为什么?

  • 不需要代码
  • 没有嵌套的分区
  • 通过 FK 到父表的完整 DRI
  • 强制执行“多个父级,一次只有一个”

您还可以使用计算列添加一个列,表示“部门”或“部门”

另一种方式:要求每个部门至少有一个部门......