规范化-数据库设计原则

关系数据库设计的核心问题是关系模型的设计。本文将结合具体的实例,介绍数据库设计规范化的流程。数据库

摘要

关系型数据库是当前普遍应用的数据库类型,关系数据库设计是对数据进行组织化和结构化的过程,核心问题是关系模型的设计。对于数据库规模较小的状况,咱们能够比较轻松的处理数据库中的表结构。然而,随着项目规模的不断增加,相应的数据库也变得更加复杂,关系模型表结构更为庞杂,这时咱们每每会发现咱们写出来的SQL语句的是很笨拙而且效率低下的。更糟糕的是,因为表结构定义的不合理,会致使在更新数据时形成数据的不完整。所以,就有必要学习和掌握数据库的规范化流程,以指导咱们更好的设计数据库的表结构,减小冗余的数据,借此能够提升数据库的存储效率,数据完整性和可扩展性。本文将结合具体的实例,介绍数据库规范化的流程。数据结构


序言

本文的目的就是经过详细的实例来阐述规范化的数据库设计原则。在DB2中,简洁、结构明晰的表结构对数据库的设计是至关重要的。规范化的表结构设计,在之后的数据维护中,不会发生插入(insert)、删除(delete)和更新(update)时的异常。反之,数据库表结构设计不合理,不只会给数据库的使用和维护带来各类各样的问题,并且可能存储了大量不须要的冗余信息,浪费系统资源。数据库设计

要设计规范化的数据库,就要求咱们根据数据库设计范式――也就是数据库设计的规范原则来作。可是一些相关材料上提到的范式设计,每每是给出一大堆的公式,这给设计者的理解和运用形成了必定的困难。所以,本文将结合具体形象的例子,尽量通俗化地描述三个范式,以及如何在实际工程中加以优化应用。学习


规范化

在设计和操做维护数据库时,关键的步骤就是要确保数据正确地分布到数据库的表中。 使用正确的数据结构,不只便于对数据库进行相应的存取操做,并且能够极大地简化应用程序的其余内容(查询、窗体、报表、代码等)。正确进行表设计的正式名称就是"数据库规范化"。后面咱们将经过实例来讲明具体的规范化的工程。关于什么是范式的定义,请参考附录文章 1.优化


数据冗余

数据应该尽量少地冗余,这意味着重复数据应该减小到最少。好比说,一个部门雇员的电话不该该被存储在不一样的表中, 由于这里的电话号码是雇员的一个属性。若是存在过多的冗余数据,这就意味着要占用了更多的物理空间,同时也对数据的维护和一致性检查带来了问题,当这个员工的电话号码变化时,冗余数据会致使对多个表的更新动做,若是有一个表不幸被忽略了,那么就可能致使数据的不一致性。spa


 

规范化实例

为了说明方便,咱们在本文中将使用一个SAMPLE数据表,来一步一步分析规范化的过程。设计

首先,咱们先来生成一个的最初始的表。code

CREATE TABLE "SAMPLE" (
          "PRJNUM" INTEGER NOT NULL, 
          "PRJNAME" VARCHAR(200), 
          "EMYNUM" INTEGER NOT NULL,
          "EMYNAME" VARCHAR(200), 
          "SALCATEGORY" CHAR(1), 
          "SALPACKAGE" INTEGER)   
         IN "USERSPACE1";

ALTER TABLE "SAMPLE" 
    ADD PRIMARY KEY
        ("PRJNUM", "EMYNUM");

Insert into SAMPLE(PRJNUM, PRJNAME, EMYNUM, EMYNAME, SALCATEGORY, SALPACKAGE)
values(100001, 'TPMS', 200001, 'Johnson', 'A', 2000), (100001, 'TPMS', 200002,
'Christine', 'B', 3000), (100001, 'TPMS', 200003, 'Kevin', 'C', 4000), (100002,
'TCT', 200001, 'Johnson', 'A', 2000), (100002, 'TCT', 200004, 'Apple', 'B',
3000);
表1-1

表1-1

考察表1-1,咱们能够看到,这张表一共有六个字段,分析每一个字段都有重复的值出现,也就是说,存在数据冗余问题。这将潜在地形成数据操做(好比删除、更新等操做)时的异常状况,所以,须要进行规范化。orm


 

第一范式

参照范式的定义,考察上表,咱们发现,这张表已经知足了第一范式的要求。htm

一、由于这张表中字段都是单一属性的,不可再分;

二、并且每一行的记录都是没有重复的;

三、存在主属性,并且全部的属性都是依赖于主属性;

四、全部的主属性都已经定义

事实上在当前全部的关系数据库管理系统(DBMS)中,都已经在建表的时候强制知足第一范式。所以,这张SAMPLE表已是一张知足第一范式要求的表。考察表1-1,咱们首先要找出主键。能够看到,属性对<Project Number, Employee Number>是主键,其余全部的属性都依赖于该主键。


 

从一范式转化到二范式

根据第二范式的定义,转化为二范式就是消除部分依赖。

考察表1-1,咱们能够发现,非主属性<Project Name>部分依赖于主键中的<Project Number>; 非主属性<Employee Name>,<Salary Category>和<Salary package>都部分依赖于主键中的<Employee Number>;

表1-1的形式,存在着如下潜在问题:

1. 数据冗余:每个字段都有值重复;

2. 更新异常:好比<Project Name>字段的值,好比对值"TPMS"了修改,那么就要一次更新该字段的多个值;

3. 插入异常:若是新建了一个Project,名字为TPT, 可是尚未Employee加入,那么<Employee Number>将会空缺,而该字段是主键的一部分,所以将没法插入记录;

Insert into SAMPLE(PRJNUM, PRJNAME, EMYNUM, EMYNAME, SALCATEGORY, SALPACKAGE) values(100003, 'TPT', NULL, NULL, NULL, NULL)

4. 删除异常:若是一个员工 200003, Kevin 离职了,要将该员工的记录从表中删除,而此时相关的Salary信息 C 也将丢失, 由于再没有别的行纪录下 Salary C的信息。

Delete from sample where EMYNUM = 200003
Select distinct SALCATEGORY, SALPACKAGE from SAMPLE

所以,咱们须要将存在部分依赖关系的主属性和非主属性从知足第一范式的表中分离出来,造成一张新的表,而新表和旧表之间是一对多的关系。由此,咱们获得:

CREATE TABLE "PROJECT" (
          "PRJNUM" INTEGER NOT NULL, 
          "PRJNAME" VARCHAR(200))
         IN "USERSPACE1";

ALTER TABLE "PROJECT" 
    ADD PRIMARY KEY
        ("PRJNUM");

Insert into PROJECT(PRJNUM, PRJNAME) values(100001, 'TPMS'), (100002, 'TCT');
表1-2

表1-2

表 1-3
CREATE TABLE "EMPLOYEE" (
          "EMYNUM" INTEGER NOT NULL, 
          "EMYNAME" VARCHAR(200), 
"SALCATEGORY" CHAR(1), 
"SALPACKAGE" INTEGER)
         IN "USERSPACE1";

ALTER TABLE "EMPLOYEE" 
    ADD PRIMARY KEY
        ("EMYNUM");

Insert into EMPLOYEE(EMYNUM, EMYNAME, SALCATEGORY, SALPACKAGE) values(200001,
'Johnson', 'A', 2000), (200002, 'Christine', 'B', 3000), (200003, 'Kevin', 'C',
4000), (200004, 'Apple', 'B', 3000);

Employee Number    Employee Name    Salary Category    Salary Package
200001    Johnson    A    2000
200002    Christine    B    3000
200003    Kevin    C    4000
200004    Apple    B    3000
CREATE TABLE "PRJ_EMY" (
          "PRJNUM" INTEGER NOT NULL, 
          "EMYNUM" INTEGER NOT NULL)
         IN "USERSPACE1";

ALTER TABLE "PRJ_EMY" 
    ADD PRIMARY KEY
        ("PRJNUM", "EMYNUM");

Insert into PRJ_EMY(PRJNUM, EMYNUM) values(100001, 200001), (100001, 200002),
(100001, 200003), (100002, 200001), (100002, 200004);

同时,咱们把表1-1的主键,也就是表1-2和表1-3的各自的主键提取出来,单独造成一张表,来代表表1-2和表1-3之间的关联关系:

表 1-4

表 1-4

这时候咱们仔细观察一下表1-2, 1-3, 1-4, 咱们发现插入异常已经不存在了,当咱们引入一个新的项目 TPT 的时候,咱们只须要向表1-2 中插入一条数据就能够了, 当有新人加入项目 TPT 的时候,咱们须要向表1-3, 1-4 中各插入一条数据就能够了。虽然咱们解决了一个大问题,可是仔细观察咱们仍是发现有问题存在。


 

从二范式转化到三范式

考察表前面生成的三张表,咱们发现,表1-3存在传递依赖关系,即:关键字段< Employee Number > --> 非关键字段< Salary Category > -->非关键字段< Salary Package >。而这是不知足三范式的规则的,存在如下的不足:

一、 数据冗余:<Salary Category>和<Salary Package>的值有重复;

二、 更新异常:有重复的冗余信息,修改时须要同时修改多条记录,不然会出现数据不一致的状况;

三、 删除异常:一样的,若是员工 200003 Kevin 离开了公司,会直接致使 Salary C 的信息的丢失。

Delete from EMPLOYEE where EMYNUM = 200003
Select distinct SALCATEGORY, SALPACKAGE from EMPLOYEE

所以,咱们须要继续进行规范化的过程,把表1-3拆开,咱们获得:

表 1-5

表 1-5

表 1-6

表 1-6

这时候若是 200003 Kevin 离开公司,咱们只须要从表 1-5 中删除他就能够了, 存在于表1-6中的Salary C信息并不会丢失。可是咱们要注意到除了表 1-5 中存在 Kevin 的信息以外, 表1-4中也存在 Kevin 的信息, 这很容易理解, 由于 Kevin 参与了项目 100001, TPMS, 因此固然也要从中删除。

至此,咱们将表1-1通过规范化步骤,获得四张表,知足了三范式的约束要求,数据冗余、更新异常、插入异常和删除异常。

在三范式之上,还存在着更为严格约束的BC范式和四范式,可是这两种形式在商业应用中不多用到,在绝大多数状况下,三范式已经知足了数据库表规范化的要求,有效地解决了数据冗余和维护操做的异常问题。


 

结束语

在本文描述的过程当中,咱们经过结合实例的方法,通俗地演绎了数据表规范化的过程,并展现了在此过程当中数据冗余、数据库操做异常等问题是如何获得解决的。

在具体的工程应用中,运用数据库规范化的方法来设计数据库表,将是具备现实意义的。

参考资料


 转自:http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-0605jiangt/