关系数据 规范化的理解

原则:

规范化的目的是一份数据只存储在一个地方。

 

根据上面的原则来理解3种范式:

第一范式:

列的原子性;

保证行的唯一性---一份数据只存储在一个地方。

第二范式:非属性键与主键的关系

1.满足第一范式

2.非键属性依赖于整体主键,而不是非键属性仅仅依赖于主键中的某个部分。即:无部分依赖:

      违反第二范式就是存在部分依赖(非键属性仅仅依赖于主键中的某个部分)。

违反第二范式这有点像:

      在一个由诸多长老全部举手表才能表决的组织里,你却只听一个或个别长老的话,这可是坏了规矩的。

 

例如,如下的关系就违背了第二范式:

关系名:PersonPet(人宠物)    

主键:PesonId 、PetId

非键属性:PesonName、PetName、PetType

违背第二范式:PesonName只依赖于PesonId

                    PetName只依赖于PetId

举个例子,违反了第二范式存储的数据的样子:

PesonId    PetId           PesonName    PetName 

      1          1                    人才1           宠物1

      2          2                    人才2           宠物2

      3          1                    人才3           宠物1

在现实生活中,人和宠物的关系是多对多的关系,即:

1个人可以有0、1、1以上个宠物

1个宠物可以属于0(如流浪狗)、1(单身IT男)、1个以上(一对情侣)个人

我们从上表因为违反第二范式而存储的数据违反规范化的原则:

规范化的目的是一份数据只存储在一个地方。

 

 即:PetId为1的宠物,在存储数据的时候,被复制了多次,存放的不同的地方。

这样会对数据的增、删、改。会有什么影响:

增:

1.通常来说,当需要对单个事物(单个人、单个宠物)进行处理,而不是处理他们之间关系时,

   因为没有专门为“人”这个实体建立了的表(如:Person表)为了增加一个人,不得不在PersonPet(人宠物表)中添加人

   的相关信息,而在“宠物”相关的列输入无意义的值。

   在单独查询人(不查询宠物)的时,不得不额外去除掉那些来自宠物相关信息。

  

   2.只要一个人有多个宠物,这个人的信息将被多次复制。同样:

   3.只要一个宠物属于多个人,这个宠物的信息也将被多少复制。   

 

删:

当需要对单个事物(单个人、单个宠物)进行处理,而不是处理他们之间关系时,对删除的影响:

如果PesonId为1和3(这对情侣可能同时出现车祸)的人都没,要删除这两个人,存储的数据就是这样的:

PesonId   PetId        PesonName         PetName

NULL            1               NULL                 宠物1

   2              2               人才2                 宠物2

NULL            1               NULL                 宠物1

 

可以看到这样的设计基本废掉了。

改:

数据同步问题, 例如:通过主键(PesonId ,PetId)=(1,1)修改 PetName的值“宠物1”为“宠物007”,如果在编程时没有

注意同步

PesonId   PetId    PesonName   PetName

 3              1            人才3         宠物1

那么就破坏了数据。

 

第三范式:非属性键之间的关系

1.满足第二范式

2.非属性键不依赖于非属性键,即:不存在传递依赖。

 

违反第三范式这有点像:

      在朝廷中有个皇帝(主键)就够了,有人结党私营,搞小团体,听命于一个小头目(非属性键依赖于非属性键),也是坏了规矩的。

 

Book表

主键:BookIsbnNunmber

非属性键:Title

               Price

               PublishName

               PublishCity

 

这个表满足了第二范式.

但是违反了第三范式:

非属性键PublishCity依赖于非属性键PublishName。

 

违反了第三范式将导致如下问题,例如下面违反了第三范式的表存储的数据:

BookIsbnNunmber     Title                Price       PublishName       PublishCity

   1001                 《我是人才》        63.1          人才出版社            地球村

   1002                 《我是蠢材》         87.2         人才出版社            地球村

 

按常规,我们都是通过“主键”去唯一定位要修改的数据,所以,用如下SQL语句:

Update adb.Book

Set PublishCity='月亮城'

Where BookIsbnNunmber=‘1001’;

执行以上SQL后,表中的数据如下:

BookIsbnNunmber        Title              Price       PublishName   PublishCity

1001                       《我是人才》       63.1         人才出版社      月亮城

1002                       《我是蠢材》       87.2         人才出版社       地球村

 

这就产生了数据同步的问题,数据在更新时被破坏了。

 PublishName     PublishCity

人才出版社           月亮城

人才出版社           地球村

由于违反了第三范式(非属性键PublishCity依赖于非属性键PublishName),

我们就得写额外的处理去更新所有列的PublishName

Update adb.Book

Set PublishCity='月亮城'

Where PublishCity='地球村' And PublishName='人才出版社'

这样,说明一点,违反第三范式,为了更细数据时,避免非属性键之间依赖产生的数据同步问题,不得不

        进行而不处理数据同步问题,但是这额外的同步数据操作很容易被忘记,

         更糟糕的是,系统的关系会随着时间的关系不断变化,你也将越来越头痛。

 

 

 

 

 

 

 

 

 

 

 

 

     

 

 

 

posted @ 2013-06-12 21:42  easy5  阅读(534)  评论(0编辑  收藏  举报