SQL - 两个在它们之间具有依赖关系的外键

时间:2010-06-02 17:20:37

标签: sql sql-server sql-server-2008 foreign-keys foreign-key-relationship

目前的结构如下:

Table RowType:    RowTypeID

Table RowSubType: RowSubTypeID
                  FK_RowTypeID

Table ColumnDef:  FK_RowTypeID
                  FK_RowSubTypeID (nullable)

简而言之,我将列定义映射到行。在某些情况下,这些行具有子类型,这些子类型具有特定于它们的列定义。或者,我可以将特定于子类型的列定义挂起自己的表,或者我可以将RowType和RowSubType中的数据合并到一个表中并使用单个ID,但我不确定是否是更好的解决方案(如果有的话,我会倾向于后者,因为我们最终会为给定的RowType / RowSubType拉取ColumnDef)。

当前的设计SQL亵渎吗?

如果我保留当前结构,如果在ColumnDef中指定了RowSubTypeID,它如何保持它必须对应于RowTypeID指定的RowType?我应该尝试用触发器强制执行此操作,还是我错过了一个可以解决问题的简单重新设计?

1 个答案:

答案 0 :(得分:4)

您遇到的问题是Fourth Normal Form

以下是解决方案:

Table RowSubType:       RowSubTypeID
                        FK_RowTypeID
                        UNIQUE(FK_RowTypeID, RowSubTypeID) 

Table ColumnDef:        ColumnDefID
                        FK_RowTypeID
                        UNIQUE(ColumnDefID, FK_RowTypeID) 

Table ColumnDefSubType: FK_ColumnDefID   } compound foreign key to ColumnDef
                        FK_RowTypeID     }   } 
                        FK_RowSubTypeID      } compound foreign key to RowSubType

您只需要在ColumnDefSubType表中为具有行子类型的列创建一行。但是所有引用都受到约束,因此您无法创建异常。

但是对于它的价值,我同意@ Seth关于可能过度工程的评论。我不确定我是否理解你如何使用这些列defs和行类型,但它闻起来像Inner-Platform Effect反模式。在SQL中,只需使用元数据来定义元数据。不要尝试使用数据来创建动态模式。

另见这篇精彩的故事:Bad CaRMa


重新评论:在您的情况下,我建议使用类表继承或具体表继承。这意味着为每个子类型定义一个单独的表。但是,原始文本记录的每一列都将进入子类型表的相应列。这样您就不需要拥有rowtype或rowsubtype表,通过为每个子类型定义表来隐含它。并且您不需要您的columndefs表,这是由表中定义的列隐含的。

另请参阅我对Product table, many kinds of product, each product has many parameters或演示幻灯片Practical Object-Oriented Models in SQL的回答。