目前的结构如下:
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?我应该尝试用触发器强制执行此操作,还是我错过了一个可以解决问题的简单重新设计?
答案 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的回答。