SQL 2012计算列外键独占或与其他十个表

本文关键字:其他 十个 计算 2012 SQL | 更新日期: 2023-09-27 17:54:44

我有11张表

称其中一个为Parent表,其他十个为Child表,可能是childda、childdb等,通过ChildJ

假设Parent表抽象了一个电子元件。每一件电子产品都有一些共同的列,比如名称,但每种不同类型的电子设备都有截然不同的特性。表示电视所需的列与表示手机所需的列有很大的不同。

父表可以有且只有一个存在于child表中的子表,但不能与多个子表相关联。

因此,如果Parent有一个childda,它不会通过ChildJ有一个childdb。

我目前实现的方式是通过一个"ChildType"列,一个"ChildId"字段和十个持久化计算列。

例如,我(任意地)为childda的ChildType赋值1,为childdb赋值2,等等(对ChildType有一个CHECK约束)

然后,我使用CASE创建持久化列,通过使用Type列为Parent表提供ChildAId、ChildBId等。

ChildAId AS CASE WHEN ChildType=1 THEN ItemId END PERSISTED,
ChildBId AS CASE WHEN ChildType=2 THEN ItemId END PERSISTED,

…等

这些计算列是持久化的,因为我需要在FOREIGN KEY约束中使用它们。

各个子表的内容如此不同,以至于彼此之间完全无关。

通过这种方式,我有效地在SQL 中表示了一种变体类型。

我考虑过的其他想法,以及我拒绝它们的原因:

  1. 使用ChildX表中父表的Id。

  2. xref表之间的父和各种ChildX表。拒绝,因为它也会允许每个父母有多个孩子(更重要的是,每个孩子有多个父母)

  3. 创建一堆列,这些列代表所有子类型所需的所有数据的超集。拒绝,因为它是愚蠢的(而且,这是我正在更换的系统所做的,也是我试图避免的事情之一)

现在进入实际问题:

当只有两种类型的孩子时,这是一个好主意,当它突然跳到10时,我开始担心。虽然这可能不会达到50,但在我们完成之前可能会有多达25种不同的儿童类型。

同样,这在通过实体框架引入c#时也能很好地工作:

与child行相关联的Parent行有效地成为Parent对象。这真的是一件美好的事情,也是我选择我所选择的主要原因之一。

是否有一种更标准化的方式,这种类型的数据(基本上是一种变体)以一种通过约束控制的方式在SQL中表示,并允许我查询它并使用实体框架等东西来消费它?添加许多字段(除了一个字段之外,所有字段都将始终为NULL)是我这样做的权衡成本吗?难道我没有看到应该看到的危险信号吗?

SQL 2012计算列外键独占或与其他十个表

我认为处理这种情况的常见方法是
1)使用ChildX表中父表的Id,稍作修改

尽管它引入了冗余,但拥有由引擎强制执行的清晰模型是可以接受的成本。例如,

ParentTable(parentTableId, childType, UNIQUE(parentTableId,childType) , 
 PK(parentTableId), CHECK(childType IN (1,2,3,4,5,...)) );
ChildTable1(parentTableId, childType, other attributes, 
    FK(parentTableId, childType), PK(parentTableId, childType), CHECK(childType=1));
ChildTable2(parentTableId, childType, other attributes, 
   FK(parentTableId, childType), PK(parentTableId, childType), CHECK(childType=2));

如果子类型的数量非常少,比如2-3个,在父表中设置检查约束是可以的,就像上面的例子;如果您有或期望更多,我宁愿创建一个小查找表,ChildType并使用外键(这样添加新的子类型将不需要更改ParentTable中的检查约束)…

你所描述的在我看来像是继承。有三种常见的建模方法,你所描述的特别类似于每类型表(TPT)

TPT通常使用选项1建模,即与父表共享派生表上的PK:

Base(PK id, [type], attr1, attr2)
Derived1(PK/FK id, attr10, attr11)
Derived2(PF/FK id, attr20, attr21)

基表上的type属性并不是必需的,但是它可能会有很大的帮助,因为它使您能够知道一行实际上是什么,而无需尝试连接所有派生表。

是的,使用这个模型,您可以在多个派生表中插入行。人们通常不会为此烦恼。您将注意到,您不能在DB模型中强制所有内容。a1ex07的答案是告诉你,在复合PK的代价下,如果你真的想的话,你可以强制执行这个。

既然您提到了EF,那么您会很高兴地知道它内置了对TPT继承的支持。