[数据库之七] 数据库设计和 E-R 模型
1、设计过程概览
(1)设计阶段
① 收集用户需求阶段
与领域专家和用户进行深入沟通,形成功能需求规格说明。
② 概念设计阶段
选择数据模型,将①中的需求转化为数据库的概念模式。概念模式定义了数据库中表示的实体、实体的属性、实体之间的联系,以及实体和联系上的约束。
③ 逻辑设计阶段
设计者将高层概念模式映射到将使用的数据库系统的实现数据模型上。实现数据模型通常是关系数据模型,该阶段通常将以实体-联系模型定义的概念模式映射到关系模式。
④ 物理设计阶段
指明数据库的物理特征,包括文件组织格式和索引结构的选择。
(2)设计选择
使用实体来指示所有明确识别的个体(比如大学数据库中的教师、学生、系、课程都可以看成是一个实体)
使用联系来只是实体间的多种方式的联系。
-
设计数据库模式时需要避免的两个主要缺陷:
① 冗余:没有合理地设计关系模式,导致相同数据在多处存储,容易导致不一致。
比如开课信息 section 将课程信息 course 融合进来,对同一门课的所有开课,课程信息(课程编号、课程名、系名、学分[course_id、title、dept_name、credits])会重复存储。
这里课程信息 course 应该看成一个实体,并为其设计对应的模式。
② 不完整:一个不好的设计可能会使得企事业结构的某些方面难于甚至无法建模。
比如没有为课程信息单独设计一个关系,会导致新增一门课程将无法表示,除非为该课程安排了开课。
2、实体 - 联系模型
三个基本概念:实体集、联系集、属性。
(1)实体集
实体(entity):现实世界中区别于其他对象的一个 “事物” 或 “对象”。(比如学生可以看成是一个实体)
实体集(entity set):相同类型即具有相同性质(或属性)的一个实体集合。(比如一个学校的所有学生可以看成是一个实体集)
实体通过一组属性(attribute)来表示。属性是实体集中每个成员所拥有的描述性性质。(比如学生有学号、姓名、所属学院、总学分等属性)
(2)联系集
**联系(relationship)**:指多个实体间的相互关联。(如学生和教师间的联系,用 advisor 关系来表示,联系还可以添加属性来描述这种联系,比如教师什么时候称为学生的导师)
**联系集(relationship set)**:相同类型联系的集合。
参与联系集的实体集的数目称为联系集的度(degree),一般联系集都是二元的,也有更多元的联系集。
(3)属性
**域(domain)**:属性可取值的集合。(比如属性 semester 的域可能是集合{ 春,夏,秋,冬 })
分类:
- 简单、复合属性:复合属性是有层次的。(比如属性 address 可分为 street_number、street_name、apartment_number)
- 单值、多值属性:一般一个实体对某个属性都只有单独的一个值,有些可以有多个值。(比如一个教师可以有多个电话号码)
- 派生属性:这类属性的值可以从别的相关属性或实体派生出来,不存储,在需要时计算。(比如教师的生日可以推算出年龄)
3、约束
(1)映射基数
表示一个实体通过一个联系集能关联的实体的个数。
- 一对一(one-to-one):比如一个学生只能有一名导师。
- 一对多(one-to-many):比如一名教师可以知道多名学生。
- 多对一(many-to-one):多个教师属于同一个学院并且一个教师只能归属在一个学院下。
- 多对多(many-to-many):多个学生上同一门课,一个学生可以上多门课。
(2)参与约束
如果实体集 E 中的每个实体都参与到联系集 R 中的至少一个联系中,则 E 在 R 中的参与称为全部的;如果只有部分实体参加,则称为部分的。
(3)码
实体的码是一个足以区分每个实体的属性集。
设 R 是一个涉及实体集 E1, E2, ..., En 的联系集
- 如果联系集 R 没有属性与之相关联,则属性集合
primary-key(E1)∪primary-key(E2)∪...∪primary-key(En)
描述了集合 R 中的一个联系。
-
如果联系集 R 有属性 a1, a2, ..., am 与之相关联,那么属性集合
primary-key(E1)∪primary-key(E2)∪...∪primary-key(En)∪{a1, a2, ..., am}
描述了集合 R 中的一个联系。
在以上两种情况下,属性集合
primary-key(E1)∪primary-key(E2)∪...∪primary-key(En)
构成了联系集的一个超码。
联系集的主码结构依赖于联系集的映射基数:
- 多对多:由多个实体的主码的并集组成。
- 一对多/多对一:由多一方的实体的主码组成。(比如一个老师可以教多个学生,但是一个学生只能有一个老师,这种情况下学生 ID 就可以作为联系集的主码)
- 一对一:两个实体中任意一个的候选码都可以作为主码。
4、从实体集中删除多余的属性
一句话总结:实体集不包含由于跟其他实体的联系(常见的是保留其他实体的主键作为外键关联)而造成冗余的属性,关联属性被 E-R 设计中的联系所替代。
5、实体 - 联系图
E-R 图可以图形化表示数据库的全局逻辑结构。
(1)基本结构
- 矩形:实体集。
- 菱形:联系集。
- 椭圆形:属性。
- 矩形下部分:属性,下划线标识的属性构成主码。
- 线段:将实体集连接到联系集。
- 虚线:将联系集属性连接到联系集。
- 双线:实体在联系集中的参与度。
- 双菱形:连接到弱实体集的标志性联系集。
(2)映射基数
箭头指向 “一”,横线指向 “多”,横线上设置 “min...max”,* 表示任意,双线表示全部参与。
- 一对一
- 一对多
- 多对多
(3)复杂的属性
简单属性、复合属性、多值属性、派生属性。
(4)角色
实体在联系中扮演的功能称为实体的角色,在实体和菱形至今的连线上标注角色名称
(5)弱实体集
弱实体集:没有足够的属性以形成主码的实体集。
强实体集:有主码的实体集。
- 弱实体集必须与另一个成为标识或属主实体集关联在一起才能有意义。
- 弱实体集与其标识实体集相连的联系成为标示性联系。
- 分辨符:区分弱实体集中的实体,E-R 图中用下虚线表示。
- 主码:标注的主码与其分辨符。
【示例】
如表示开课信息的关系 section 中,用 course_id、sec_id、semester、year 属性来唯一标识一个实体,按照 E-R 模型的约定,实体集不应该包含跟其他实体关联的属性,所以应该去掉 course_id,但是剩下三个属性无法唯一标识一个 section 实体,而 course_id 是关系 course 的主码。
这里 section 就是弱实体集,course 就是强实体集,section 必须跟 course 关联才有意义,其分辨符为 { sec_id, semester, year },其主码为 { course_id, sec_id, semester, year }。
6、转换为关系模式
将一个符合 E-R 数据库模式的数据库标识为一些关系模式的集合。
(1)具有简单属性的强实体集的表示
对于从强实体集转换而来的模式,强实体集的主码就是生成的模式的主码。
(2)具有复杂属性的强实体集的表示
通过为每个子属性创建一个单独的属性来处理复合属性,而不为复合属性自身创建一个单独的属性。
Eg:为 address 属性,创建子属性 street、city、state、zip_code。
对于多值属性,为其创建新的关系模式。
Eg:每个教师可能有多个电话号码,则为其创建模式 instructor_phone(id, phone_number)
(3)弱实体集的表示
设 A 是具有属性 a1, a2, ..., am 的弱实体集,设 B 的主码包括属性 b1, b2, ..., bn。我们用名为 A 的关系模式表示实体集 A,该模式的每个属性对应以下集合中的一个成员:
{ a1, a2, ..., am }∪{ b1, b2, ..., bn }
对于从弱实体集转换而来的模式,其主码由其所依赖的强实体集的主码与弱实体集的分辨符组合而成。
Eg: section ( <u>course_id</u>, <u>sec_id</u>, <u>semester</u>, <u>year</u> )
【解析】在大学数据库设计中,在模式 section 上建立了一个属性 course_id 参照 course 模式的主码的外码约束,以及完整性的 “级联删除”,若一个 course 实体被删除,则与之关联的所有 section 实体都将被删除。
(4)联系集的表示
设 R 是联系集,设 a1, a2, ..., am 表示所有参与 R 的实体集的主码的并集构成的属性集合,设 R 的描述属性为 b1, b2, ..., bn。我们用名为 R 的关系模式表示该联系集,下面集合中的每一项表示为模式的一个属性:
{ a1, a2, ..., am }∪{ b1, b2, ..., bn }
按照以下规则选择主码:
- 多对多的二元联系集,主码 = 所有实体集的主码的并集
- 一对一的二元联系集,主码 = 任一实体集的主码
- 一对多/多对一的二元联系集,主码 = 多一方实体的主码
- 没有箭头(即多对多)的 n 元联系集,主码 = 所有实体集的主码的并集
- 有箭头的 n 元联系集,主码 = 不在箭头侧的实体集的主码的并集
① 模式的冗余
一般情况下,连接弱实体集与与其所依赖的强实体集的联系集是冗余的。
Eg:
弱实体集:section( <u>course_id</u>, <u>sec_id</u>, <u>semester</u>, <u>year</u> )
强实体集:course( <u>course_id</u>, title, credits )
联系集:sec_course( <u>course_id</u>, <u>sec_id</u>, <u>semester</u>, <u>year</u> )
很明显 sec_course 是冗余的。
② 模式的合并
实体集 A, 实体集 B, 多对一的联系集 AB, A 在联系中的参与是全部的,则可以将 A 和 AB 模式合并成单个包含两个模式所有属性的并集的模式。
合并后模式的主码是其模式中融入了联系集模式的那个实体集的主码。
Eg:
实体集 A: instructor( <u>id</u>, name, salary )
实体集 B: department( <u>dept_name</u>, building, budget )
联系集 AB: inst_dept( <u>id</u>, <u>dept_name</u> )
A 跟 AB 合并后的模式:instructor( <u>id</u>, name, dept_name, salary )
7、实体 - 联系设计问题
(1)用实体集还是属性
为实体添加新的信息时,如果是比较简单值用属性;如果是复合值或多值,使用新的模式设计的实体集,并添加一个关联集。
(2)使用实体集还是联系集
当描述发生在实体间的行为时采用联系集。
(3)二元还是 n 元联系集
将一个 n 元联系集拆分为多个二元联系集,存在以下问题:
- 为表示联系集创建的实体集,可能不得不为其创建一个标识属性,增加了设计的复杂程度以及对总的存储空间的需求。
- n 元联系集可以更清晰地表示几个实体集参与单个联系集。
- 可能无法将三元联系上的约束转变为二元联系上的约束。
(4)联系属性的布局
一个联系的映射基数比率会影响联系属性的布局。
首先,联系属性放到实体集还是联系集中,取决于这个联系属性的实际意义。
如果要放到实体集中:
- 一对一的联系属性可以放到任意一个参与联系的实体中
- 一对多的联系属性仅可以放到多一方的实体中
对于多对多联系属性,是由参与的实体集联合确定而不是由单独的某个实体集确定的,必须放到多对多联系集中。
8、扩展的 E - R 特性
(1)特化
特化就是对实体分类进行具体分组的过程,优点类似面向对象编程思想中的继承,是一个从初始实体集到一系列不同层次的实体子集的细化的自顶向下的设计过程。
特化从单一实体集出发,通过创建不同的底层实体集来强调同一实体集中不同实体间的差异。底层实体集可以有不适用于高层实体集中所有实体的属性,也可以参与到不适用于高层实体集中所有实体的联系中。
设计者采用特化的原因正是为了表达这种与众不同的特征。比如实体集 person 中,student 和 employee 差别很大,则可以进行特化设计更具体的实体子类。
(2)概化
概化是一种自底向上的设计过程,是特化的逆过程。
概化的进行基于这样的认识:一定数量的实体集共享一些共同的特征(即用相同的属性描述它们,且它们都参与到相同的联系集中)。概化是在这些实体集的共性的基础上将它们综合成一个高层实体集。概化用于强调底层实体集间的相似性并隐藏它们的差异。
(3)属性继承
由特化和概化所产生的高层和底层实体的一个重要特性,高层实体集的属性被底层实体集继承。
(4)概化上的约束
为了更准确地对企业建模,可能需要在特定概化上设置某些约束。
- 不相交:一个实体至多属于一个底层实体集。
- 重叠:一个实体可以同时属于同一个概化中的多个底层实体集。
Eg: 上层为人,下层为学生和老师,不相交意味着一个人不可以同时为老师和学生,重叠则意味着一个人可以同时为老师和学生。