SQL - 两个相互依赖的外键

Bri*_*ian 2 sql sql-server foreign-keys foreign-key-relationship sql-server-2008

目前的结构如下:

Table RowType:    RowTypeID

Table RowSubType: RowSubTypeID
                  FK_RowTypeID

Table ColumnDef:  FK_RowTypeID
                  FK_RowSubTypeID (nullable)
Run Code Online (Sandbox Code Playgroud)

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

现在的设计是对SQL的亵渎吗?

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

Bil*_*win 5

您遇到的麻烦是第四范式

这是解决方案:

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
Run Code Online (Sandbox Code Playgroud)

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

但就其价值而言,我同意@Seth 关于可能存在过度设计的评论。我不确定我是否理解您如何使用这些列定义和行类型,但它闻起来像内部平台效应反模式。在SQL中,只需使用元数据来定义元数据。不要尝试使用数据来创建动态模式。

另请参阅这个精彩的故事:Bad CaRMa


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

另请参阅我对产品表的回答,多种产品,每种产品都有许多参数或我的演示幻灯片SQL 中的实用面向对象模型