为了账号安全,请及时绑定邮箱和手机立即绑定

ER图中的超级和子类型关系如何表示为表格?

/ 猿问

ER图中的超级和子类型关系如何表示为表格?

烧仙草VB 2019-09-13 13:10:39

ER图中的超级和子类型关系如何表示为表格?

我正在学习如何将实体关系图解释为SQL DDL语句,我对符号的差异感到困惑。考虑一个不相交的关系,如下图所示:


“车辆”框连接到“IsA”三角形,标记为“不相交”,它分别连接到“2WD”框和“4WD”框。


这会表示为:


车辆,2WD和4WD表(2WD和4WD将指向车辆的PK); 要么

只有2WD和4WD表(和没有车辆表),这两个表都会复制车辆所具有的任何属性?

我认为这些是写这种关系的其他方式:


“车辆”框用粗线连接到“IsA”三角形,它与细线分别连接到“2WD”框和“4WD”框。 “车辆”盒连接到“IsA”三角形,它们分别连接到“2WD”盒和“4WD”盒,全部用细线连接。


我正在寻找一个明确的解释,说明每个图表最终会有哪些表格。


查看完整描述

3 回答

?
月关宝盒

ER表示法

有几种ER符号。我不熟悉你正在使用的那个,但很明显你试图表示一个子类型(又名继承,类别,子类,泛化层次......)。这是OOP继承的关系表亲。

在进行子类型分析时,您通常会关注以下设计决策:

  • 摘要与具体:父母可以实例化吗?在你的例子中:可以Vehicle存在不是存在2WD4WD?1

  • 包容性与排他性:可以为同一个父母实例化多个孩子吗?在你的榜样,可以Vehicle 2WD4WD?2

  • 完整与不完整:您希望将来能够添加更多儿童吗?在您的示例中,您是否希望稍后可以将a BikePlane(etc ...)添加到数据库模型中?

信息工程表示法区分包容性和排他性子类型关系。另一方面,IDEF1X表示法没有(直接)识别这种差异,但它确实区分了完整和不完整的子类型(IE没有)。

从下图ERwin的方法指南(第5章,子类型关系)示出的区别:

IE和IDEF1X都不能直接指定抽象与具体父级。

物理表征

遗憾的是,实际数据库不直接支持继承,因此您需要将此图转换为实际表。这样做通常有3种方法:

  1. 将所有类放在同一个表中,并将子字段保留为NULL。然后,您可以使用CHECK来确保非NULL中的字段的正确子集。

    • 优点:没有加入,所以一些查询可以受益。可以强制执行父级别的密钥(例如,如果您想要避免不同的2WD4WD具有相同ID的车辆)。可以轻松地强制执行包容性与独占子项以及抽象与具体父级(仅通过改变CHECK)。

    • 缺点:有些查询可能会变慢,因为它们必须过滤掉“不感兴趣”的孩子。根据您的DBMS,特定于子项的约束可能会有问题。很多NULL都会浪费存储空间。不太适合不完整的子类型 - 添加新子项需要更改现有表,这在生产环境中可能会有问题。

  2. 将所有子项放在单独的表中,但没有父表的表(而是在所有子项中重复父项的字段和约束)。具有(3)的大多数特征,同时避免JOIN,以较低的可维护性(由于所有这些字段和约束重复)和无法强制执行父级键或代表具体父级的代价。

  3. 将父项和子项放在单独的表中。

    • 优点:清洁。不需要人为地重复字段/约束。实施父级键并轻松添加特定于子级的约束。适合不完整的子类型(相对容易添加更多的子表)。某些查询只能通过查看“有趣的”子表来获益。

    • 缺点:有些查询可能很重要。可能难以强制执行包容性与独占子级以及抽象与具体父级(如果DBMS支持循环延迟外键,则可以声明性地强制执行,但在应用程序级别强制执行它们通常被认为是较小的恶意)。

正如您所看到的,情况并不理想 - 无论您选择何种方法,您都需要妥协。方法(3)应该是你的出发点,如果有令人信服的理由,只选择其中一种方案。


1我猜这是你的图表中线条的粗细。

2我猜这是你的图表中存在或不存在“不相交”的含义。



查看完整回答
反对 回复 2019-09-16
?
跃然一笑

通常,当您在数据库设计中执行超类型/子类型关系时,需要为常规实体类型(超类型)创建单独的表,并为您的专用实体版本创建单独的表(子类型)脱节与否。在您的情况下,您将需要为VEHICLE和主键创建一个表,以及一些常见或由所有子类共享的属性。然后,您将需要为2WD和4WD创建单独的表以及仅特定于这些表的属性

查看完整回答
反对 回复 2019-09-16
?
慕姐829404

其他响应者说了什么,加上下面的子类表的主键。

您的案例看起来像设计模式的一个实例,称为“泛化专业化”,或简称为Gen-Spec。如何使用数据库表对gen-spec进行建模的问题一直出现在SO中。

如果您在诸如Java之类的OOPL中对gen-spec进行建模,则可以使用子类继承工具来为您处理细节。您只需定义一个类来处理通用对象,然后定义一个子类集合,每个类型对应一种特定对象。每个子类都会扩展泛化类。它简单明了。

遗憾的是,关系数据模型没有内置子类继承,据我所知,SQL数据库系统不提供任何此类工具。但你不是运气不好。您可以设计表格以与OOP的类结构平行的方式对gen-spec进行建模。然后,在将新项添加到通用类时,必须安排实现自己的继承机制。细节如下。

类结构相当简单,一个表用于gen类,一个表用于每个spec子类。这是一个很好的例子,来自Martin Fowler的网站。 类表继承。 请注意,在此图中,Cricketer既是子类又是超类。您必须选择在哪些表中使用哪些属性。该图显示了每个表中的一个示例属性。

棘手的细节是如何为这些表定义主键。gen类表以通常的方式获取主键(除非此表是另一种泛化的特化,如Cricketers)。大多数设计师给主键一个标准名称,如“Id”。他们使用自动编号功能填充Id字段。spec类表获得一个主键,可以命名为“Id”,但不使用自动编号功能。相反,每个子类表的主键被约束为引用通用表的主键。这使得每个专用主键成为外键和主键。请注意,在Cricketers的情况下,Id字段将引用Players中的Id字段,但Bowlers中的Id字段将引用Cricketers中的Id字段。

现在,当您添加新项目时,您必须保持参照完整性,这是如何。
首先在gen表中插入一个新行,为主键提供所有属性的数据。自动编号机制生成唯一的主键。接下来,在适当的spec表中插入一个新行,包括其所有属性的数据,包括主键。您使用的主键是刚刚生成的全新主键的副本。这种主键的传播可以称为“穷人的继承”。

现在,当您希望所有通用数据与来自一个子类的所有专用数据一起使用时,您所要做的就是通过公共键将两个表连接起来。与所涉及的子类无关的所有数据都将退出连接。它光滑,简单,快速。



查看完整回答
反对 回复 2019-09-16

添加回答

回复

举报

0/150
提交
取消
意见反馈 邀请有奖 帮助中心 APP下载
官方微信