Skip to content

ER 模型

约 2307 个字 预计阅读时间 8 分钟

实体集 E

真实的世界可以被建模为一系列实体的集合和这些实体之间的联系。所谓的实体是一个具有属性的对象,可以理解为关系型数据库中的一行;一个实体集是多个同类实体的集合,可以理解为关系型数据库中的一张表。属性是可以被实体集成员拥有的可描述性质,属性具有domain(定义域)和类型,类型又包括:

  • 简单(Simple)和复合(Composite)属性,比如sex只有male/female二选一,但是name有first name和last name两部分组成
  • 单值(Single-valued)和多值(multi-valued)属性,比如一个person只能有一个ID,但是可以有多个phone number
  • 派生属性(derived attribute),比如年龄可以由出生日期计算得到

联系集 R

一个联系(relationship)是两个或者多个实体集之间的关联,比如每位研究生都有自己的导师;一个联系集是相同类型关系的集合,表示两个或者多个实体集之间的关联。更正式来说,一个联系集是多个实体集某些部分的集合:${(e_1,e_2,...,e_n)|e_1\in E_1,e_2\in E_2,...,e_n\in E_n} $。联系可以是一对一、一对多、多对一或者多对多

联系集的度

度(degree)表示一个联系集中包含的实体集的数量,比如一个联系集包含两个实体集,就叫做二元关系或者二元联系,当然联系集也有可能包含超过两个实体集,比如三元联系集(常见的是二元的)

映射基数

映射基数(mapping cardinalities)是指一个实体集可以与另一个实体集发生联系的实体数目,期中数目是指一个还是多个,在描述二元关系中非常有用,也就是上面说的一对一、一对多、多对一或者多对多

码/键

这里一般翻译做码,以示与关系中的键的区分,其实是一样的。超码是可以唯一确定联系的属性集合,候选码是超码中属性数量最少的,主码是人为指定的超码。相关实体集中的主键组合在一起就构成了联系集中的主键,所以一对实体集最多有一个联系集,在考虑主键时一定要考虑映射基数,因为只要不是多对多,就可以只选单的那个实体集的主键来当联系集的主键,而且需要考虑主码的属性不能为空,值不能常变。

ER 图

矩形(Rectangle)表示实体集,上面表示实体集的名称,下面表示实体集的属性名,主键用下划线标注,菱形(Diamond)代表联系集,用线条连接实体集和联系集。

不同属性的表示

假设我们有这么一个实体集,它包含了复合属性name(类似于类),多重属性phone_number(类似于集合)以及派生属性age(age类似于一个函数调用)

|-----------------------|

| ID |

| name |

| first_name |

| last_name |

| {phone_number} |

| date_of_birth |

| age() |

|-----------------------|

有属性的联系集

联系集也可以有自己的属性,比如导师与学生之间可以有个advisor包含date属性,至于这个到底存什么,就要看具体需求

角色

实体集可以与自身产生联系,比如一门课有它的预修课程,我们用角色(role)来标明,角色标签是可选的

image-20250318201951747

基数约束

有向直线表示1,无向直线表示多,限制了一个实体发生关联的另一个实体的数目上限

参与约束

我们有全参与(total participation)用双直线,和部分参与(partial participation),部分参与表示有部分实体不会参与到联系中。参数约束反应了一个实体关联数目的下限,是0次还是1次。

这个也有另一种符号表示形式,比如0...*表示0个或者多个,1..1表示有且仅有一个

二元联系

二元联系比多元的要好,有些三元关系是可以拆成二元的,比如家长与孩子,你可以拆成父亲与孩子和母亲与孩子

;对于本身就不是二元的联系, 可以通过人为增加关系集拆成三个二元关系

弱实体集

一个没有主键的弱实体集被称作弱实体集,比如我们定义一个课程与学期之间的联系,学期是完全依附于课程的,如果硬要区分学期,需要把学期的所有属性作为主键,这是不明智的选择,我们要避免主键过长过复杂,与之相对,我们可以把学期作为弱实体集设计。弱实体集是依附于标识实体集存在的,因为它自身没有主键,而且必须是从标识实体集到弱实体集是全参与一对多的关系。

弱实体集没有超键的概念(至少名字不叫超键,我们把这个类似于超键的东西叫做分辨符(discriminator)或者部分码(partial key),一个弱实体集的主键是由标识集的主键和弱实体集的分辨符共同构成。

弱实体集的标识符用虚下划线标注,标识联系集用双层菱形表示,注意标识实体集的主键并没有显式和弱实体集存储在一起,它们是通过联系集隐式关联的。当然也可以直接把弱实体集存进标识实体集,但是这样会造成不必要的重复,如果数量很多会浪费很多存储空间。

延伸ER特征

这一小节的描述很像oop

实体集的层

属性继承,是指低层的实体会继承上层所有关联实体的全部属性,类似于OOP里面的继承;与之相对的概念是泛化,是指的把相同的属性打包进同一个上层实体。

层设计的限制

  • 分层原因约束:向下分成不同的层的原因有两种,一种是按条件定义,比如只有本科在读才能被归入学生下面的本科生,另一种是用户定义,比如不同组的员工。

  • 独立性约束:一个实体可以只属于一个低层的实体集,在ER图里面写一个disj,另一种情况是可以同时属于多个实体集

  • 完整性约束:上层的实体是不是必须属于下层的某个实体

聚合

可以通过聚合避免重复,简单来说就是可以把一组有联系的实体集整体打包组成复合实体集,再表示与其他实体集的关系

一些ER模型设计的思考

  1. 用一个属性还是一个实体集去表示一个对象?

用一个属性会比较简单,但是对于电话号码这种多重属性,多个号码集中在一个属性会破坏原子性,故还是要分作一个实体集。只有一个单值的就比较适合作为属性。

  1. 是作为一个实体集还是一个联系集?

两个实体集之间发生的动作用一个联系集表示,但是这么做也有缺陷,前面说过两个实体之间只能有一个关系,这个在某些情况下是不正确的,比如一个人可以在同一个银行有多笔贷款,这种情况下贷款就不能作为联系集

  1. 是作为实体集的属性还是联系集的属性?

从对象数据独立性和减少数据冗余考虑

将ER模型转化为数据库表

ER模型终究只是一个概念上的东西,最终实现还是要在数据库中:

  1. 把关系模型转化为一个表的形式
  2. 复合属性会被展开成一个个属性
  3. 多重属性会被处理成一个表

  4. 表示弱实体集,把标识实体集的主键和弱实体集合并

  5. 把联系集表示成表:把两个参与实体集合的主键并在一起表示,加上这个联系表自身的属性
  6. 表的合并:
  7. 多对一的可以把一合并到多的表里面,如果多的那一侧是partial的,可以加null填补
  8. 联系弱实体集及其联系集是冗余的,也可以都合并到标识集里面
  9. 用表表示特化:
  10. 可以在特化的表里面除了主键只保留上层没有的,缺点是信息不全,得多表查询
  11. 特化的表里面保留全部信息,如果是全特化,可以舍弃父表,把父表定义为一个视图,但其实显式的表可能还是需要被定义用于主键约束,缺点是信息可能会重复