考虑上面的问题,其中'CommonChild'实体可以是子类型A或B的子类,但不是C.如何在关系[SQL]数据库中设计物理模型?
理想情况下,解决方案允许......
向超类型添加其他子类型,并在新子类型下移动子类型A和B.然后,CommonChild可以对新创建的子类型具有FK约束。适用于上述情况,但如果添加的附加实体可能与子类型A和C有关系但不是B,则不起作用。
在CommonChild和SuperType之间添加FK约束。在允许新元组进入CommonChild之前,对超类型的鉴别器使用触发器或检查约束(w / UDF)。看起来很直接,但现在CommonChild几乎看起来像是新的子类型(它不是)。
我的模型存在根本缺陷。改造和问题应该消失。
我正在寻找其他可能的解决方案或确认我已提出的上述解决方案之一。
谢谢!
修改
我将实施Branko Dimitrijevic提供的独家外键解决方案(见接受的答案)。
我将在这种情况下稍作修改:
修改是创建一个中间表,其唯一的作用是强制子类型和“CommonChild”之间的独占FK约束(Dimitrijevic提供的精确模型减去“CommonChild”的属性)。 CommonChild的PK将对中间表具有正常的FK约束。
这将阻止“CommonChild”具有2组3列复合FK。另外,由于识别关系从超类型维护到“CommonChild”,[读取]查询可以完全有效地忽略中间表。
答案 0 :(得分:3)
您似乎需要exclusive foreign keys的变体:
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)
)
);
这里有几点需要注意:
Id
,它等于其中一个FK(以当前非NULL为准),它也是一个主键。这可以确保:
CommonChild.Id
。 SuperType.Id
有效地一直向下延伸。与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)
)
)
不幸的是,MS SQL Server不允许包含多个NULL的UNIQUE列,大多数DBMS都不是这种情况。但是,如果您不想直接引用SubTypeAId
或SubTypeBId
,则可以省略UNIQUE约束。
答案 1 :(得分:3)
想知道我在这里失踪了什么?
不可否认,没有特定问题的措辞就很难,但事情确实有点颠倒。