具有重叠子表的SQL子类型
考虑上面的问题,“CommonChild”实体可以是子类型a或B的子类型,但不能是C的子类型。我如何在关系[SQL]数据库中设计物理模型 理想情况下,解决方案将允许具有重叠子表的SQL子类型,sql,database,database-design,sql-server-2012,Sql,Database,Database Design,Sql Server 2012,考虑上面的问题,“CommonChild”实体可以是子类型a或B的子类型,但不能是C的子类型。我如何在关系[SQL]数据库中设计物理模型 理想情况下,解决方案将允许 用于识别CommonChild及其相关子类型之间的关系 一对一的关系。 可能的解决方案 将附加子类型添加到超级类型,并将子类型A和B移动到新子类型下。然后,CommonChild可以对新创建的子类型具有FK约束。适用于上述情况,但如果添加了与子类型a和C(而非B)有关系的附加实体,则不适用 在CommonChild和超类型之间添加
编辑 我将实现Branko Dimitrijevic提供的专用外键解决方案(请参阅接受的答案) 在这种情况下,我将做一些轻微的修改,如下所示:
这将防止“CommonChild”具有2组3列复合FK。另外,由于标识关系是从超级类型到“CommonChild”进行维护的,[read]查询可以有效地完全忽略中间表 看起来您需要以下变量: 这里有几点需要注意:
- 有两个NULL able外键
- 有一个检查允许这些FK中只有一个不为空
- 有一个计算列
,它等于一个FK(当前为非空的),这也是一个主键。这可确保:Id
- 一个父项不能有多个子项
- “孙子”表可以直接从其FK引用
。CommonChild.Id
被有效地向下移动SuperType.Id
- 我们不必处理可空的唯一约束,这在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)
)
)
不幸的是,MS SQL Server不允许包含多个NULL的唯一列,这在大多数DBMS中是不允许的。但是,如果您不想直接引用
subsubsipaid
或subsibid
,您可以省略唯一约束。想知道我在这里遗漏了什么吗
诚然,没有具体问题的措辞是很难的,但事情确实有点颠倒了
在SQL Server中可以使用筛选索引来强制执行忽略
null
s@MartinSmith是的,但这将是一个索引,而不是唯一的约束,因此它不能(例如)被外键引用,它的违规行为将以不同的方式报告给客户端(如果这很重要的话)。此外,有一种哲学观点反对混合物理和逻辑概念。SQL Server允许FKs引用唯一的索引。但它不允许唯一的筛选索引。对于使用COALESCE的计算主键语法,+1…我已经遇到过几次相同的场景,虽然我找到了两个可为null的FK和CHECK约束,但我从未找到如何以这种方式实现主键。现在看起来很明显!优雅的我曾考虑过添加一个额外的层次结构,但在这种特殊情况下,再加上限制A&B和A&C有一个共同的孩子,这是没有意义的。实际上,我的“CommonChild”实体应该是它自己的独立实体。各种子类型应通过FK引用或关联表引用CommonChild。这是一个70年代后期大型机中非常不规范(且较差)的数据模型的中间规范化模型。
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)
)
)