Skip to content

Latest commit

 

History

History
58 lines (29 loc) · 8.91 KB

4.2-shi-ti-guan-xi.md

File metadata and controls

58 lines (29 loc) · 8.91 KB

4.2 实体关系

1. 4.2 实体关系

下面从数据库中的表谈起,先问自己一个问题:这些表是从哪儿来的呢?或者说,设计这些表的根据是什么呢?

首先,这些表来源于现实业务活动中的实体。所谓实体,可以理解为可以看得见摸得着的事物的种类,如员工、供应商、原料等。注意,数据建模中所说的实体是事物的种类,不是个体,“员工”是一种实体(为了避免误解,这里用量词“种”,不用“个”),而“张三”只是这种实体下的一个实例。每一种实体都有若干属性信息,如“员工”实体,包含工号、身份证号码、生日等各种属性。一种实体的相关属性信息,往往需要在数据库中设计一个表来管理,如员工信息表、供应商档案表、物料信息表等。

其次,这些表来源于实体跟实体之间的关系。实体跟实体之间是有关系的,如采购订单是供应商跟原料之间产生的关系,数据库中需要表来存储这种关系信息,如采购订单表。

最后,当然还有各种各样的用于管理数据本身的表。

在进行数据库设计之前,首先要分析好本系统需要管理哪些实体,这些实体的关系如何。相信大部分读者都知道实体关系图(E-R图),这个工具就是用来分析实体关系的,本书以实战为宗旨,不会在这方面说得太多,但并不表示这方面的知识不重要,相反,在进行数据建模时,它应该始终在脑中盘旋。

现实世界中实体之间的关系一般有三种:一对一,一对多,多对多。在数据建模时,针对不同的关系,有不同的处理方式。

1.1. 4.2.1 一对一关系

如果实体A与实体B是一对一的关系,那么表示实体A中的一个实例,在实体B中或者没有实例,或者只有唯一一个实例可以与之对应,并且,实体B中的一个实例,在实体A中也是或者没有实例,或者只有唯一一个实例可以与之对应。这种情况下,在进行数据建模时,往往可以有两种处理方式,一是设计两个表分别管理,在某个表中加跟另一个表的关联字段——这里建议在后出现数据的表中加关联字段;另外一种方式是,如果某实体中的实例涵盖了另外一个实体中的所有实例,也可以考虑只设计一个表管理。

案例:实体的一对一关系

某院校,关于学生,有两种实体,一是报名考生,二是学生。报名考生指通过电话、邮件、网络等方式向学校报名的本届高考考生,包括考生号、准考证号、姓名、报名方式、报名专业、联系方式等属性,其中考生号为主属性;学生指被学校正式录取的考生,录取后学校会给考生编学号,学生在校期间学号不变,学生实体包括学号、姓名、就读专业、班级、入学时间、身份证号、手机等属性。这两个实体之间是一对一的关系,因为,一个考生,或者没有对应的学生,或者只对应唯一一个学生,一个学生,只能对应一个考生。数据建模可以考虑以下两种方式。

第一种方式,设计两个表,一个考生表(考生号为关键字),一个学生表(学号为关键字)。由于在本学校的现实业务中,对于某个特定的学生而言,都是先报名后录取的,也就是说一定是先有考生数据,后有学生数据的,所以在学生表中加一个“考生号”关联字段(就是前面所谓的“后出现数据的表”),用以关联考生表。这种方式多了些灵活性,给未来可能的扩展、变更带来了方便,但提取、处理数据有些麻烦,因为需要关联查询。考生与学生的一对一关系如图4-3所示。

由于每个学生必须先报名,有了考生信息后才可能被录取,因此也可以只设计一个表,假设就叫学生表,将所有需要管理的属性合并存放,以考生号为关键字。这种方式提取、处理数据方便,但不利于应对扩展、变更要求,例如,如果什么时候业务发生了变化,允许直接录入未报名的学生(例如转学过来的),事情就麻烦了。

图4-3 实体考生与学生的一对一关系

需要解释一下,当采用两个表管理时,为什么建议把关联字段放到业务上后出现数据的表中。在前面的案例中,其实在考生表中加关联字段“学号”,在学生表中加关联字段“考生号”,都是可以考虑的,无碍大局。把关联字段放到后出现数据的表中,可以避免插入数据时需要同时更新两个表,减少出错的潜在风险。例如,新增学生时,将关联的考生号跟学生的属性一起插入到学生表中,总比在学生表中插入学生信息,然后再在考生表中找到对应考生写入关联学号要好些。这主要是基于性能、效率、稳定性的考虑。有时候可能两个表的数据并没有先后之分,那么关联字段放到哪个表中就无所谓了。

1.2. 4.2.2 一对多关系

如果实体A与实体B是一对多的关系,那么表示实体A中的一个实例,在实体B中可以对应多个实例,而实体B中的一个实例,在实体A中只能对应一个实例。例如,母亲与子女、主管与下属、省与市、班级与学生等,都是一对多的典型例子。在进行数据建模时,这种情况一般需要设计两个表,分别代表两种实体,在“多”的那个表中设计关联字段。

案例:实体的一对多关系

某公司的组织方式,一个部门有多个员工,一个员工只允许在一个部门任职。这里包括两种实体,一是“部门”,一是“员工”。由于一个员工只能属于一个部门,一个部门可以有多个员工,因此这两种实体是一对多的关系。数据建模,需要设计两个表,一个是员工表(以员工工号为关键字),一个是部门表(以部门代号为关键字),由于员工是“多”的一方,因此在员工表中加关联字段“部门代号”(外键),用于跟部门表关联,表达某员工属于哪个部门。部门与员工的一对多关系如图4-4所示。

图4-4 实体部门与员工的一对多关系

1.3. 4.2.3 多对多关系

如果实体A与实体B是多对多的关系,那么表示实体A中的一个实例,在实体B中可以对应多个实例,而实体B中的一个实例,在实体A中也可以对应多个实例。在现实业务中,一对一的关系其实非常少,一对多的关系也不多见,大部分情况下都是多对多的关系。例如,供应商与原材料,一家供应商可以提供多种原材料,一种原材料可以由多家供应商供货,供应商与原材料之间的关系是多对多的关系;学生与图书的关系,一个学生可以借阅多本图书,一本图书可以被多个学生借阅,学生与图书之间的关系是多对多的关系。在数据建模时,这种情况一般会设计三个表,两个表分别表示两种实体,另外需要一个表表示两种实体之间的关系。需要注意的是,现实中的实体有多对多的关系,但在数据库中,表跟表之间是没有什么多对多的关系的,它们要么没有关系,要么就是一对一或者一对多的关系。数据建模时,会将一个多对多的关系,转换成两个一对多的关系。

案例:实体的多对多关系

某原料仓库,使用货架管理,所有的原材料都存放在货架上,货架进行规范编号,第一层的叫A01、A02等,第二层的叫B01、B02等,同一货架上允许存放多种原料,同一种原料可能会存放在多个货架上。例如,A02货架上存放了80kg编号为L01的螺丝,30kg编号为L02的螺丝,而B01货架上存放了110kg编号为L01的螺丝,20kg编号为Y99的油漆。根据这种业务情况可知,实体“原料”与实体“货架”的关系为多对多的关系,因为同一货架可以对应多种物料,同一种物料可以对应多个货架。进行数据库设计时,可以设计三个表,一个“原料”表,用以存放所有的原料基本信息;一个“货架”表,用以存放所有的货架基本信息;一个“货架存货”表,用以表达每个货架上存放了哪些原料,数量是多少。“原料”表与“货架存货”表、“货架”表与“货架存货”表之间的关系都是一对多的关系,如图4-5所示。

图4-5 实体原料与货架的多对多关系