范式间的区别(具体例子)
由于最近要做毕业设计了,所以加强了一下数据库设计的基础知识,主要是范式的应用。在此作些总结吧。
首先是基础概念,也就是术语:
(1) 实体(entity):就是实际应用中要用数据描述的事物,一般是名词。
(2) 字段(fields):就是一项数据,也就是我们平常所说的“列”。
(3) 记录(record):一个实体的一个实例所特有的相关数据项的集合,也就是我们平常所说的“行”。
(4) 键(key):可唯一标识一条记录的一个字段或字段集。
(5) 主键(primary key):用于唯一标识一个表中的一条记录的键。每个主键应该具有下列特征:1. 唯一的。2.最小的(尽量选择最少键的组合)。3.非空。4.不可更新的(不能随时更改)
(6) 外键(foreign keys):对连接父表和子表的相关记录的主键字段的复制。
(7) 依赖表(dependent table):也称为弱实体(weak entity)是需要用父表标识的子表。
(8) 关联表(associative table):是多对多关系中两个父表的子表。
(9) 实体完整性:每个表必须有一个有效的主键。
(10) 参照完整性:没有不相匹配的外键值。
然后就是本文的主题:“范式”了。范式主要有第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、BCNF、第四范式(4NF)。下面就根据例子,一一解释。(以下的例子都出自《database design and development : a visual approach》 Raymond Frost, John Day, Craig Van Slyke 著,且有下划线的表示主键)
具体例子:
假设你需要为一个在线视频娱乐厅设计数据库,用它记录每个会员的消费时间。娱乐厅必须掌握会员的基本信息,包括他们的电子邮箱、访问在线娱乐厅的口令、他们的姓名以及电话号码。当会员每次访问娱乐厅时都会创建一个进程id,而且必需记录进程的开始时间和结束时间。如图:
上图是规范化的设计。下面展示一个非规范化的设计。如图:
那么非规范化的设计有什么利弊呢?
优点:很明显,非规范化设计没有外键。这样就简化了某些相关操作。
缺点:其实潜在的问题是致命的。
1. 更新问题。当有两条主键(id)不一样,但其他信息完全相同的数据遇到更新时,其中一条的数据更新了,但另一条没有更新,结果产生不一致的数据。
2. 插入问题。当插入一条数据时,插入信息只是表属性的一部分。例如上例中只插入一个MEMBER的基本信息(email,password,fname,iname,phone),在非规范化设计中是禁止的,因为该数据信息不完整。
这些问题导致了在构造关系数据库时一些规则的出现,这些就是范式。
第一范式定义:表中所有字段仅包含单值。
很明显,第二行的数据违反了第一范式。因为phone的字段有两个值。PS:汗一个,美国人怎么连密码都是武器???
解决的办法有:
在讨论更高级的范式之前,必须明白确定因子的概念。
确定因子(determinant):是一个字段或一组字段,它控制或确定其他字段的值。
第二范式定义:表中的每个非键字段由整个主键确定,且不能由主键自身的一部分确定。因此,2NF的违例只会出现在主键是由超过一个字段构成的表中。
在上面的STUDENT_ENROLL表中id决定了fname,iname,dorm,phone,而SECTION$call_no又决定了fname,iname,dorm,phone,grade。违反了第二范式,则在更新时,由于Jim Green有两个电话号码而无法更新。
解决的办法有:
第三范式定义:表中不存在可以确定其他非关键字的非键字段。
3NF的违例可能发生在具有多个非键字段的表中。
上图的MEMBERVISIT中,主键(id)决定了email,password,fname,iname,phone。Email决定了password,fname,iname,phone。所以违反了第三范式。会导致Luce存储了两个passwords.。这显然是不对的。
解决的方法:
BCNF定义:每个确定因子是一个键。这个范式特别用于处理非键字段确定主键的一部分主要的情况。
上面的QUARTERLY_BONUS表中,一个非键字段ssn确定employee_id,它是键的一部分。实际上,ssn和employee_id彼此相互确定。所以违反了BCNF范式。会导致更新问题,雇员8857在图中有两个不同的ssn。
解决方法:
第四范式定义:在全键表中,键的一部分可以确定至多一个其他字段的多个值。4NF仅用于全键表。
为了理解第四范式,需要引入多值依赖(multivalued dependency,MVD)的概念:指可以控制或确定另一个字段的多个值的一个或一组字段。
上面的SKILL表中,email是多值依赖的。违反了第四范式。如果我们删除了Luce的German身份。我们也丢失了他爱好网球的信息。
解决方法:
这两个表是没有联系的。每个表仅包含一个MVD。
检测范式违例:
1. 当多个值存储在一个单元中时会发生1NF违例。
2. 2NF违例只会发生在具有关联键的表中,且非键字段只依赖于主键的一部分。
3. 3NF违例发生在一个非键字段确定另一个非键字段的情况下,表可能有一个任何大小的键。
4. BCNF违例出现在非键字段确定主键的一部分的情况下。这些违例只能发生在主键是有关联键组成的表中。
5. 4NF违例发生在表的主键至少由3个键连接而成且没有非键字段的情况下,此外,键的一部分确定键的另一部分的多个值。
解决范式违例的方法:就是将复式的确定因子拆成单一的确定因子。