首页
实体-联系模型(Entity-Relationship Model)
E/R Diagrams
弱实体集(Weak Entity Sets)
将 E/R 图转化为关系
Haifeng Xu
(hfxu@yzu.edu.cn)
This slide is based on Jeffrey D. Ullman's work, which can be download from his website.
参考书 陈晓勇 编著 《MySQL DBA 修炼之道》
数据库的设计
数据库的设计
数据库的设计通常需要经历四个部分:
- 需求收集与分析(Requirements Collection and Analysis)
- 概念设计(Conceptual Design) —— 设计实体关系模型 (ER Model)
- 逻辑设计(Logical Design)—— 实现从 ER 模型到关系模式(Relation Schemas)的转换。
- 物理设计(Physical Design)
概念设计
概念设计是一个构建概念数据模型的过程,这个概念数据模型在抽象的高层建模;需要足够简单且通常是图形化的;并且能够用于与非技术用户交流数据库的需求。这里主要介绍如何使用 ER 模型来实现概念设计。
E/R 模型
E/R 模型(ER Model)
由于设计人员、研发人员和最终用户看待和使用数据的方式不同, 我们需要一种通用模型进行沟通. 这个模型和技术实现无关. 实体关系图(ER 模型)就是这样一种通用模型.
E/R 模型的目的
E/R 模型允许我们先简略地描绘以下数据库模式的设计.
这里的 E/R 图设计是一些图片, 它们被称为实体-联系图(entity-relationship diagrams).
后面会讲: 将 E/R 设计转化为关系数据库设计.
关于 E/R 设计的框架
关于 E/R 设计的框架
Design is a serious business.
“老板”知道他们想要一个数据库, 但是他们并不知道他们想要在数据库中放些什么.
将关键部分做一个大概描述是开发可运行数据库的一个有效方式.
实体集(Entity Sets)
实体集(Entity Sets)
实体(Entity)="thing" or object.
实体集(Entity Sets): 指相似实体组成的集合. 用长方形标识.
属性(Attribute) 指实体集(或实体集中实体)的性质, 用于描述实体或者关系的性能或者特征. 通常使用椭圆标识.
- 属性是简单值, 如: 整数、字符串、 not structs, sets 等等.
主要属性 指能够用于识别特定实体的属性. 标识于带下划线的椭圆内.
E/R 图(E/R diagram)
E/R 图(E/R diagram)
在一个实体-联系图(Entity-relationship diagram)中:
- 实体集用长方形标识.
- 属性用椭圆形标识, 并用一根线连接到代表实体集的某个长方形.
- 主要属性用带下划线的椭圆标识.
- 实体与实体之间的联系称为关系, 使用菱形标识.
- 多值属性, 使用双椭圆标识.
例子
例子
实体集 Beers 有两个属性, name 和 manf(manufacturer).
每个 Beers 实体都有这两个属性值, 比如: (Bud, Anheuser-Busch).
联系(Relationships)
联系(Relationships)
一个联系(relationship)连接两个或更多的实体集.
关系用菱形表示, 并且用线连接每个所涉及到的实体集.
例子: 联系(Relationships)
例子: 联系(Relationships)
- 酒吧(Bars)销售某些啤酒(Beers).
- 酒客(Drinkers)喜欢某些啤酒(Beers).
- 酒客(Drinkers)经常光顾某些酒吧(Bars).
联系集(Relationship Set)
联系集(Relationship Set)
一个实体集的当前“值”是属于它的一些实体.
- 例子: 比如实体集 Bars 的值是我们例子中的所有酒吧.
联系的“值”是一个联系集(relationship set), 这是一些元组的集合, 元组的分量是相关联的实体集(a set of tuples with one component for each related entity set.)
例子: 联系集(Relationship Set)
例子: 联系集(Relationship Set)
对于关系 Sells, 我们可以有下面的关系集合
Bar |
Beer |
Joe's Bar |
Bud |
Joe's Bar |
Miller |
Sue's Bar |
Bud |
Sue's Bar |
Pete's Ale |
Sue's Bar |
Bud Lite |
多路联系(Multiway Relationships)
多路联系(Multiway Relationships)
有时, 我们需要描述多于两个实体集的联系.
假设酒客只在某些酒吧喝某些牌子的啤酒.
- 我们的三个二元关系 Likes, Sells 和 Frequents 不能对此作出区分.
- 但是一个三路关系可以做到.
例子: 三路联系
例子: 三路联系
一个典型的联系集
一个典型的联系集
Bar |
Drinker |
Beer |
Joe's Bar |
Ann |
Miller |
Sue's Bar |
Ann |
Bud |
Sue's Bar |
Ann |
Pete's Ale |
Joe's Bar |
Bob |
Bud |
Joe's Bar |
Bob |
Miller |
Joe's Bar |
Cal |
Miller |
Sue's Bar |
Cal |
Bud Lite |
多对多联系(Many-Many Relationships)
多对多联系(Many-Many Relationships)
Focus: 二元(binary)联系, 如 Bars 和 Beers 之间的 Sells 联系.
在一个多对多联系(Many-Many Relationship)中, 集合中的任一个实体被联系到其他集合中的许多实体上.
- 比如: 一个酒吧可以销售很多啤酒; 一种啤酒可以由很多酒吧出售.
多对多联系的图示
多对多联系的图示
多对一联系
多对一联系
某些二元联系是多对一联系.
第一个集合中的每一个实体至多与第二个集合中一个实体相连.
但是第二个集合中的实体可以和第一个集合中一个或多个实体相连, 也可以不连.
多对一联系的图示
多对一联系的图示
例子: 多对一联系
例子: 多对一联系
从 Drinkers 到 Beers 的联系 Favorite 是一个多对一的联系.
一个酒客最喜欢的啤酒最多只能一种.
但是某种啤酒, 喜欢喝的人有很多, 也可能没有人喜欢.
一对一联系
一对一联系
在一个一对一联系(one-one relationship)中, 两个实体集中每个实体关联到另一个实体集中至多一个实体.
例子: 考虑 Manf(manufacturer) 和 Beers 之间的联系 (Best-seller)
- 某品牌的啤酒不可能被两家生产产商生产, 并且没有哪个厂商有超过一个 best-seller.
一对一联系的图示
一对一联系的图示
Representing "Multiplicity"
Representing "Multiplicity"
在实体集与实体集之间用箭头表示多对一联系.
用双向箭头表示一对一联系.
Rounded arrow = "exactly one", 即, 第一个实体集中的每个实体恰好只联系到目标集合中一个实体.
例子: 多对一联系
例子: 多对一联系
例子: 一对一联系
例子: 一对一联系
考虑 Manfs 与 Beers 之间的联系 Best-seller.
某些啤酒不是制造商的销售最好的啤酒. 因此一个到 Manf 画一个圆箭头(rounded arrow)将是不合适的.
但是一个啤酒制造商只能有一个销售最好的啤酒.
用 E/R 图表示
用 E/R 图表示
联系的属性(Attributes on Relationships)
联系的属性(Attributes on Relationships)
有时在一个联系上增加一个关于联系的属性是非常有用的.
将该属性看作联系集中元组的某个性质.
例子: 关于联系的属性
例子: 关于联系的属性
price 是关于 bar 和 beer 的(二元)函数, 而不是关于其中某个的(一元)函数.
与上面等价的 E/R 图, 但没有用到联系的属性
与上面等价的 E/R 图, 但没有用到联系的属性
创建一个额外的实体集, 它的属性就是原来联系的属性.
使得这个新的实体集参与到联系中来.
例子: 去除联系的属性转换为等价的 E/R 图
例子: 去除联系的属性转换为等价的 E/R 图
通常, 当把联系中的属性转换到一个额外的实体集上时要放置一个箭头指向那个实体集.
角色(Roles)
角色(Roles)
有时某个实体集在联系中出现不止一次. 如果是这样, 根据实体集在联系中出现的次数, 把联系与实体集用同样多的连线连起来.
每一条连向实体集的连线代表实体集在联系中扮演的不同角色.
因此, 对联系和实体之间的边加注标签(或曰命名), 称之为角色(Roles)
例子: 角色(Roles)
例子: 角色(Roles)
例子: 角色(Roles)
例子: 角色(Roles)
多路联系到二元联系的转换
多路联系到二元联系的转换
E/R 模型不限制联系是二元联系. 有一些数据模型约束联系必须是二元的. 如 UML 和 ODL
连接(connecting)实体集: 其实体被看作是多路联系的联系集的元组.
针对组成原来多路联系元组的每个实体集, 从连接实体集中引入多对一联系.
子类(Subclasses)
子类(Subclasses)
子类(Subclasses) = special case = fewer entities = more properties.
例子: Ales 是一类啤酒.(应用于酿造的许多种自然或人工培养酵母可以概略的分为三种:爱尔啤酒(ale或top-fermenting)酵母、窖藏啤酒(lager或bottom-fermenting)酵母和野生酵母)
- 不是每种啤酒都是 ale, 但有些是.
- 假设 ales 啤酒除了具有普通啤酒的所有性质(属性和联系)外, 还具有属性 color.
E/R 图中子类的表示
E/R 图中子类的表示
假设子类的结构是树状结构.
- 即, 没有多样继承(no multiple inheritance).
Isa 三角形表示子类的联系.
- 三角形的一边与子类相连, 而与此边相对的一角与父类相连.
例子: 子类
例子: 子类
E/R vs. Object-Oriented Subclasses
E/R vs. Object-Oriented Subclasses
在面向对象的语言中, 对象被认为只存在一个类或子类中.
相反, E/R 实体集中的实体被允许有代表.
- 规则: 如果实体 $e$ 用一个子类来代表, 则 $e$ 可以用该子类的父类来代表(并且在树状结构中可以向上递归.)
例子: 实体的代表(Representatives of Entities)
例子: 实体的代表(Representatives of Entities)
键(Keys)
键(Keys)
实体集 E 的键(key) 是由一个或多个属性构成的集合 K. 来自于该实体集 E 的任何两个实体在 K 中的属性上的值是不一致的.
我们必须对每个实体集划定一个键.
E/R 图中键的表示
E/R 图中键的表示
对于组成键的属性用下划线标出.
在一个 Isa 层次中, 只有根实体集具有键, 并且它在该体系中作为所有实体集的一个键.
例子: name is Key for Beers
例子: name is Key for Beers
例子: 一个由多属性构成的键
例子: 一个由多属性构成的键
注意到 hours 和 room 也可以作为实体集 Courses 的一个键, 但这里我们必须选择其中一个键来标识出.
弱实体集(Weak entity sets)
弱实体集(Weak entity sets)
有时, 一个实体集的实体需要额外的“帮助”来唯一确定它们.
实体集 E 称为是弱实体集(Weak entity sets), 如果为了唯一确定 E 中的实体, 我们需要跟踪 E的一个或多个“多对一的”联系, 包括与之连接的相关实体集的键.
换句话说, 一个实体集键是由另一个实体集的部分或全部属性构成. 这样的实体集叫做弱实体集(weak entity set).
弱实体集的来源
需要弱实体集有两个主要原因:
- 有时实体集处于一个与 "isa层次" 分类无关的层次体系中.
- 连接实体集. (是作为消除多路联系的一种方法.) 这些实体集通常没有自己的属性. 它们的键是由它们所连接的实体的键属性构成.
例子: 弱实体集(Weak entity sets)
例子: 弱实体集(Weak entity sets)
name 几乎可以作为足球运动员的键, 但有时存在重名的可能.
number 当然不能作为一个键, 因为两个球队中可能有成员是同一个号码的.
我们假设同一支球队中不存在号码相同的球员. 因此运动员在球队中的号码 number, 加上所属球队的名称 name 就可以唯一确定该运动员了. 球员效力于某个球队用联系 Plays-on 来描述.
在 E/R 图中的表示
在 E/R 图中的表示
- 双矩形表示一个弱实体集.
- 双菱形表示一个多对一的联系, 它有助于提供弱实体集的键.
- 这里圆箭头表明 $\text{Players}\rightarrow\text{Teams}$ 从数学上讲是一个映射.
弱实体集的规则
弱实体集的规则
一个弱实体集具有一个或多个“多对一”联系到其他(支持)实体集.
- 不是每个从弱实体集出发的多对一联系必须是支持联系(supporting relationship)
- 但是支持联系必须有一个圆箭头(即“多对一”中的“一”必须加以保证).
弱实体集的规则 -- (2)
弱实体集的规则 -- (2)
弱实体集的键是由它自身划下划线的属性以及支持实体集中的键属性构成.
- 例如: 刚才例子中, 球员的号码 number 和所属球队的名称 name 作为弱实体集 Players 的一个键.
设计技巧(Design Techniques)
设计技巧(Design Techniques)
- 避免冗余.
- 限制使用弱实体集.
- 能用属性的地方就不要用实体集.
避免冗余(Avoiding Redundancy)
避免冗余(Avoiding Redundancy)
冗余(Redundancy) = 就是同一件事情以不同的方式重复了两次或多次.
冗余带来的问题是浪费空间, 最重要的是会产生不一致性.
- 以两种方式表达同样的事实, 如果改变了其一而忘记对另一件作修改就会带来不一致性.
- 回忆函数依赖的异常.
例子: 好的设计
例子: 好的设计
这个设计对于每个制造商只给出了一个地址.
例子: 糟糕的设计
例子: 糟糕的设计
这个设计对于啤酒的制造商说了两次: 一次是作为啤酒的属性, 另一次是与啤酒相关联的实体.
例子: 不好的设计 -- (2)
例子: 不好的设计 -- (2)
在这个设计中, 啤酒厂家的地址明显会出现重复(冗余)的现象. 并且如果某个啤酒厂家暂时不生产啤酒, 则会丢失其地址信息.
实体集 vs. 属性
实体集 vs. 属性
一个实体集应至少满足下面的条件之一:
- It is more than the name of something; it has at least one nonkey attribute.
- It is the "many" in a many-one or many-many relationship.
例子: 好的设计
例子: 好的设计
- Manfs 应该设计为一个实体集, 因为它含有一个非键属性 addr.
- Beers 设计为一个实体集, 因为“多对一”联系 ManfBy 中“多”的一方.
例子: 好的设计
例子: 好的设计
没有必要将 manf 作为一个实体集, 因为我们除了记录生产厂商(manufactures)的名字外并不记录其他信息.
例子: 不好的设计 -- (3)
例子: 不好的设计 -- (3)
由于生产厂商(manufactures) manf 除了名字外没有其他信息, 并且也不是任何联系(relationship)的 "many" 端, 因此它不应该被设计为一个实体集.
不要过度使用弱实体集
不要过度使用弱实体集
- 数据库设计新手经常怀疑(疑惑)任何事物都可以作为自身的一个键.
- They make all entity sets weak, supported by all other entity sets to which they are linked.
- 现实中, 我们通常为实体集创建唯一的 ID.
- 例如 社会保障号码(Social-Security Numbers), 车辆识别码(automobile VIN's) 等等.
何时需要弱实体集
什么时候我们需要用到弱实体集?
通常的原因是没有整体权威上能够创建唯一的 ID 时才需要弱实体集.
例子: 不太可能达成这样的协议, 在世界上所有足球队中分配唯一的球员人数. (It is unlikely that there could be an agreement to assign unique player numbers across all football teams in the world.)
从 E/R 图到关系
从 E/R 图到关系
- 实体集(Entity set) ==> 关系
- 联系(Relationships) 转换为属性仅是如下两类的关系:
- 相联系实体集的键(The keys of the connected entity sets).
- 联系自身的属性(Attributes of the relationship itself).
实体集 --> 关系
实体集 --> 关系
转换为关系: Beers(name, manf)
联系 --> 关系
联系 --> 关系
合并关系
合并关系(Combining Relations)
可以合并为一个关系的情况:
- 关于某个实体集 E 的关系.
- 对于 E 是 "many" 端的那些多对一联系.
例子: Drinkers(name, addr) 和 Favorite(drinker, beer) 合并为关系 Drinker1(name, addr, favBeer).
这里实体集 Drinkers 是多对一联系 Favorite 中多的一方.
合并多对多联系时的风险
合并多对多联系时的风险
合并 Drinkers 和 Likes 可能会带来错误. 这会导致冗余, 例如:
处理弱实体集
处理弱实体集
关于弱实体集的关系必须包含关于其完整键(包括那些属于其他实体集的键)的属性, 以及其自身的非键属性.
一个支撑联系(a supporting relationship)是冗余的, 不导出任何关系(除非它具有属性).
弱实体集 --> 关系
弱实体集 --> 关系
子类: 三种途径
Subclasses: Three Approaches
- 面向对象(Object-oriented): One relation per subset of subclasses, with all relevant attributes.
- 利用Nulls(Use nulls): One relation; entities have NULL in attributes that don't belong to them.
- E/R style: One relation for each subclass:
- 键属性(Key attribute(s)).
- 子类的属性(Attributes of that subclass).
例子: 子类 --> 关系
例子: 子类 --> 关系
面向对象
面向对象(Object-oriented)
E/R Style
E/R Style
Using Nulls
使用空值(Using Nulls)
End
Thanks very much!
This slide is based on Jeffrey D. Ullman's work, which can be download from his website.