数据库规范化原理基础介绍
文章作者 100test 发表时间 2008:04:19 12:37:02
来源 100Test.Com百考试题网
如果你跟数据库打交道的日子足够长的话,你肯定听过“规范化”这个术语。可能会有人问你:“你的数据库是规范化数据库吗?”或者“你的数据库满足BCNF范式吗?”大家常常会把规范化晾在一边,觉得这是个多余的东西,认为只有学院派作风的人才有那个闲心去对数据进行规范化。不过,了解规范化的原理,并把这些原理应用到日常数据库设计任务中并非那么复杂,而且规范化能显著提升数据库管理系统的性能。
本文将为大家介绍规范化的概念,并分别对最常用的几种范式进行详细说明。
什么是规范化?
规范化是对数据库数据进行有效组织的过程。规范化过程的两个主要目的是:消除冗余数据(如把相同的数据存储在超过一个表里)和确保数据的依赖性处于有效状态(相关数据只存储在一个表里)。这两个目标的实现很有意义,因为能够减少数据库和表的空间消耗,并确保数据存储的一致性和逻辑性。
范式
国际数据库界制定了一系列构建数据库必须遵循的特殊规则,以确保数据库的规范化。在关系数据库里,这种规则就是范式,在数据库的世界里用数字来定义不同级别的范式,从低到高共分为五种:第一范式(简称1NF)、第二范式(2NF)、第三范式(3NF)、第四范式(4NF)和第五范式(5NF)。第一范式需要满足的要求最低,第二范式在第一范式的基础上增加了更多的要求,以此类推。在实际应用当中,最常见的是第一范式、第二范式和第三范式,也将是本文介绍的重点,偶有满足第四范式的,而第五范式就更加少见,本文也不再赘述。
在我们开始讨论具体的范式之前,必须要清楚一个概念:这些范式是规则,而且只是规则而已。有时候,我们为了满足实际的商业应用需求,必然会出现偏离这些规则的情况。不管怎样,如果出现了这些偏倚的情况,我们要做的就是评价这些情况可能对系统造成的任何影响以及可能带来的数据不一致性,这非常重要。
第一范式(1NF)
对于关系数据库而言,第一范式就是最基本的规则设置,必须满足以下两项要求:
从同一个表中删除重复列
为各个相关数据组创建独立表格,并以唯一列或列集(主键)来识别每行。
在考虑实际设计一个数据库时,这些规则意味着什么呢?其实很简单。
第一条规则表示在一个表的同一行中不能出现重复数据,指的是数据库表的不可分割属性。举例而言,在一个人力资源的数据库中,存储了主管及其下级之间的对应关系。为了说明第一范式的规则,我们设定了这样的商业规则,即每个主管可以有一个或多个下属,而每个下属只能有一个主管。当我们创建一个列表或电子表格来跟踪这一信息时,我们可能会创建一个具有下列属性列的表:
主管 |
下属1 |
下属2 |
下属3 |
下属4 |
A |
小明 |
小兰 |
小军 |
|
B |
小丹 |
|
|
|
C |
小罗 |
小白 |
小东 |
小王 |
不过,想想第一范式所实行的规则:在同一个表格中删除重复列。显然,从下属1到下属4这四个列都重复了。停下来,想想这样会引发什么问题。如果一个主管只有一个下属,那么下属2-下属4这几个列纯粹是浪费存储空间(要知道存储空间是数据库最有用的东西)。此外,假设某个主管已经有了四个下属,如果他又招聘了一个新下属,该怎么办?很可能就需要修改整个表的结构了。
这时,数据库新手往往会想出第二个“好主意”:试试下面的结构,这样我们就不用再增加一列,而且可以灵活利用数据存储空间:
主管 |
下属(们) |
A |
小明,小兰,小军 |
B |
小丹 |
C |
小罗,小白,小东,小王 |
这样表中下属(们)项可以输入多个值,如果A主管有三个下属,就可以这样输入“小明,小兰,小军”。
这个解决方法已经很接近了,但还是存在缺陷。下属(们)列仍然是重复(多个值)的,而且并非不可分割。如果我们需要增加或删除某位下属时,我们就需要对表的全部内容进行读写操作。如果这还不算很严重,那如果某位主管手下的下属多大上百人呢?而且,这样的结构使将来从数据库搜索数据的查询复杂化。下面才是符合第一范式的表:
主管 |
下属 |
A |
小明 |
A |
小兰 |
A |
小军 |
B |
小丹 |
C |
小罗 |
C |
小白 |
C |
小东 |
C |
小王 |
在这种情况下,每一位下属只能输入一次,而主管可以输入多次。
接着,我们来看看第二条规则:唯一列或列集(主键)来识别每行。看着上面的表你可能会建议把下属列作为主键来用。就我们假定每个下属只能有一个主管而言的商业规则而言,下属列是确实是主键的首选列。不过我们选择存储到这个表中的数据使这一列不太适合充当主键。试想,如果我们雇佣了两个叫小明的员工的话怎么办?我们应该怎么把他们和主管的上下级关系存储到数据库中呢?所以,最好使用真正唯一的识别标志(例如员工ID)作为主键。那么我们最终获得的表将是这样的:
主管ID |
下属ID |
200101 |
200506 |
200101 |
200708 |
200101 |
200709 |
200302 |
200404 |
200010 |
200102 |
200010 |
200303 |
200010 |
200507 |
200010 |
200608 |