具有重叠子表的SQL子类型

Eri*_* W. 5 sql database database-design sql-server-2012

问题视觉

考虑上面的问题,其中'CommonChild'实体可以是子类型A或B的子类,但不是C.如何在关系[SQL]数据库中设计物理模型?

理想情况下,解决方案将允许......

  1. 用于CommonChild与其相关子类型之间的识别关系.
  2. 1:N的关系.

可能的解决方案

  1. 向超类型添加其他子类型,并在新子类型下移动子类型A和B. 然后,CommonChild可以对新创建的子类型具有FK约束.适用于上述情况,但如果添加的附加实体可能与子类型A和C有关,但不是B.

  2. 在CommonChild和SuperType之间添加FK约束.在允许新元组进入CommonChild之前,对超类型的鉴别器使用触发器或检查约束(w/UDF).看起来很直接,但现在CommonChild几乎看起来像新的子类型(它不是).

  3. 我的模型存在根本缺陷.重塑和问题应该消失.

我正在寻找其他可能的解决方案或确认我已经提出的上述解决方案之一.

谢谢!


编辑

我将实施Branko Dimitrijevic提供的独家外键解决方案(见接受的答案).

我将在这种情况下稍作修改:

  1. 超类型,子类型和"CommonChild"都具有相同的PK和;
  2. PKs是3列复合材料.

修改是创建一个中间表,其唯一的作用是强制子类型和"CommonChild"之间的独占FK约束(Dimitrijevic提供的精确模型减去"CommonChild"属性).CommonChild的PK将对中间表具有正常的FK约束.

这将阻止"CommonChild"具有2组3列复合FK.另外,由于识别关系从超类型维护到"CommonChild",[读取]查询可以完全有效地忽略中间表.

Bra*_*vic 3

看起来您需要一种专有外键的变体:

CREATE TABLE CommonChild (
    Id AS COALESCE(SubTypeAId, SubTypeBId) PERSISTED PRIMARY KEY,
    SubTypeAId int REFERENCES SubTypeA (SuperId),
    SubTypeBId int REFERENCES SubTypeB (SuperId),
    Attr6 varchar,
    CHECK (
        (SubTypeAId IS NOT NULL AND SubTypeBId IS NULL)
        OR (SubTypeAId IS NULL AND SubTypeBId IS NOT NULL)
    )
);
Run Code Online (Sandbox Code Playgroud)

这里有几点需要注意:

  • 有两个可以为 NULL 的外键。
  • 有一个 CHECK 允许这些 FK 中的一个恰好为非 NULL。
  • 有一个计算列Id等于 FK 之一(以当前非 NULL 为准),它也是主键。这可以确保:
    • 一位父母不能有多个孩子。
    • “孙”表可以CommonChild.Id直接从其 FK 引用。有效地SuperType.Id一直向下传播。
    • 我们不必搞乱可以 NULL 的 UNIQUE 约束,这在 MS SQL Server 中是有问题的(见下文)。

执行类似操作的与 DBMS 无关的方法是......

CREATE TABLE CommonChild (
    Id int PRIMARY KEY,
    SubTypeAId int UNIQUE REFERENCES SubTypeA (SuperId),
    SubTypeBId int UNIQUE REFERENCES SubTypeB (SuperId),
    Attr6 varchar,
    CHECK (
        (SubTypeAId IS NOT NULL AND SubTypeAId = Id AND SubTypeBId IS NULL)
        OR (SubTypeAId IS NULL AND SubTypeBId IS NOT NULL AND SubTypeBId = Id)
    )
)
Run Code Online (Sandbox Code Playgroud)

不幸的是,MS SQL Server 不允许包含多个 NULL 的 UNIQUE 列,而大多数 DBMS 中并非如此。但是,如果您不想引用SubTypeAIdSubTypeBId不想直接引用,则可以省略 UNIQUE 约束。