1. 程式人生 > >數據庫表設計五大範式所解決的問題

數據庫表設計五大範式所解決的問題

bcnf 名稱 概念 出現 odi 一致性 數學 依賴關系 不存在

上學時學得《數據庫系統概念》,一致似懂非懂,停留在定義和證明層面。最近在做項目,認真的了解了下數據庫的範式問題,只有潛意識懂得了其原理和應用場合才能較快設計出合理的表。

首先,明確概念如下:

主碼    也就是主鍵

候選碼    若關系中的某一屬性組的值能唯一的標識一個元組,而其任何真子集都不能再標識,則稱該屬性組為候選碼。候選碼不唯一,主碼是其中一個而已。

主屬性    包含在任一候選關鍵字中的屬性稱主屬性

其次,也是本文重頭戲,結合例子,講一下各大範式對前者的改進和應用場景。

範式在現實中解決的問題

1、數據冗余

所謂數據冗余,是指一個表中的一個或多個屬性發生改變的時候,會出現多個或更多的屬性的數據重復出現。也就是說,屬性與屬性之間、屬性與屬性組之間或者屬性組與屬性組之間存在著一對多或者多對多的數據關系。如下表:

課程C 教員T 參考書B
------------------------
物 理 李 勇 普通物理學
物 理 李 勇 光學原理
物 理 李 勇 物理習題集
物 理 王 軍 普通物理學
物 理 王 軍 光學原理
物 理 王 軍 物理習題集
數 學 李 勇 數學分析
數 學 李 勇 微分方程
數 學 李 勇 高等代數
數 學 張 平 數學分析
數 學 張 平 微分方程
數 學 張 平 高等代數
. . .
2、插入異常

所謂插入異常,是指某個屬性,特別是主鍵,為空,則盡管其他的屬性有數據,也無法插入。

假定選課關系表為SelectCourse(學號,姓名,年齡,課程名稱,成績,學分),關鍵字為組合關鍵字(學號,課程名稱),即(學號,課程名稱) → (姓名,年齡,成績,學分) 。同時其存在一下聯系:

  (課程名稱) → (學分)

  (學號) → (姓名,年齡)

對於這個表SelectCourse,假設要開設一門新的課程,暫時還沒有人選修。這樣,由於還沒有"學號"關鍵字,課程名稱和學分也無法記錄入數據庫。

3、刪除異常

所謂刪除異常,是指由於某個原因,需要刪除表中的某些沒用的屬性,但是同時也會把其他的一些有用的屬性的數據也同時刪除掉。

同樣是對於上面的表SelectCourse,當學生畢業時,需要從系統裏面刪除掉畢業學生的所有信息,同時也會把課程的信息也一並刪除掉。

4、更新異常

所謂更新異常,是指如果某個屬性的數據發生改變的時候,就需要對應屬性修改很多的數據。

同樣是對於上面的表SelectCourse,若調整了某門課程的學分,數據表中所有行的"學分"值都要更新,否則會出現同一門課程學分不同的情況。

總之,這些屬性的數據之間存在的這些問題,一來可能會占用過多的空間,影響查詢的效率,二來也會為後面的編程帶來不必要的麻煩,三來還會影響數據庫的完整性。為此,有必要對這些表格進行範式的優化。

二、六大範式的說明

總的範式優化圖:

  消除決定因素

| 1NF

  非碼的非平凡 | ↓ 消除非主屬性對碼的部分函數依賴

  函數依賴

| 2NF

  | ↓ 消除非主屬性對碼的傳遞函數依賴

  | 3NF

  | ↓ 消除主屬性對碼的部分和傳遞函數依賴

  | BCNF

  | ↓ 消除非平凡且非函數依賴的多值依賴

  | 4NF

  | ↓消除不是由候選碼所蘊含的連接依賴

  | 5NF


1.1NF(第一範式)

所謂第一範式,是指表中的每一個屬性都是不可再分的,也就是不能一列再分成兩列。這是關系數據庫的基礎。

2.2NF(第二範式)

所謂第二範式,是指所有的非主屬性都完全依賴於關鍵字。從這個定義可以看出,第二範式不存在非主屬性對於部分候選關鍵字的部分依賴,不過允許非主屬性之間存在著傳遞依賴。

下面是第二範式的優化實例:

假定選課關系表為SelectCourse(學號,姓名,年齡,課程名稱,成績,學分),關鍵字為組合關鍵字(學號,課程名稱),因為存在如下決定關系:

  (學號,課程名稱) → (姓名,年齡,成績,學分)

  這個數據庫表不滿足第二範式,因為存在如下決定關系:

  (課程名稱) → (學分)

  (學號) → (姓名,年齡)

  即存在組合關鍵字中的字段決定非關鍵字的情況。

  由於不符合2NF,這個選課關系表會存在如下問題:

  (1) 數據冗余:

  同一門課程由n個學生選修,"學分"就重復n-1次;同一個學生選修了m門課程,姓名和年齡就重復了m-1次。

  (2) 更新異常:

  若調整了某門課程的學分,數據表中所有行的"學分"值都要更新,否則會出現同一門課程學分不同的情況。

  (3) 插入異常:

  假設要開設一門新的課程,暫時還沒有人選修。這樣,由於還沒有"學號"關鍵字,課程名稱和學分也無法記錄入數據庫。

  (4) 刪除異常:

  假設一批學生已經完成課程的選修,這些選修記錄就應該從數據庫表中刪除。但是,與此同時,課程名稱和學分信息也被刪除了。很顯然,這也會導致插入異常。

  把選課關系表SelectCourse改為如下三個表:

  學生:Student(學號,姓名,年齡);

  課程:Course(課程名稱,學分);

  選課關系:SelectCourse(學號,課程名稱,成績)。

  這樣的數據庫表是符合第二範式的, 消除了數據冗余、更新異常、插入異常和刪除異常。

  另外,所有單關鍵字的數據庫表都符合第二範式,因為不可能存在組合關鍵字。

3、第三範式(3NF)

所謂第三範式,是指每一個非主屬性既不部分依賴於也不傳遞依賴於關鍵字,也就是在第二範式的基礎上消除傳遞依賴(A>B>C)。

假定學生關系表為Student(學號,姓名,年齡,所在學院,學院地點,學院電話),關鍵字為單一關鍵字"學號",因為存在如下決定關系:

  (學號) → (姓名,年齡,所在學院,學院地點,學院電話)

  這個數據庫是符合2NF的,但是不符合3NF,因為存在如下決定關系:

  (學號) → (所在學院) → (學院地點,學院電話)

  即存在非關鍵字段"學院地點"、"學院電話"對關鍵字段"學號"的傳遞函數依賴。

  它也會存在數據冗余、更新異常、插入異常和刪除異常的情況,讀者可自行分析得知。

  把學生關系表分為如下兩個表:

  學生:(學號,姓名,年齡,所在學院);

  學院:(學院,地點,電話)。

  這樣的數據庫表是符合第三範式的,消除了數據冗余、更新異常、插入異常和刪除異常。

4、BCNF

所謂BCNF,是指在第三範式的基礎上進一步消除主屬性對於碼的部分函數依賴和傳遞依賴。

假設倉庫管理關系表為StorehouseManage(倉庫ID,存儲物品ID,管理員ID,數量),且有一個管理員只在一個倉庫工作;一個倉庫可以存儲多種物品。這個數據庫表中存在如下決定關系:

  (倉庫ID,存儲物品ID) →(管理員ID,數量)

  (管理員ID,存儲物品ID) → (倉庫ID,數量)

  所以,(倉庫ID,存儲物品ID)和(管理員ID,存儲物品ID)都是StorehouseManage的候選關鍵字,表中的唯一非關鍵字段為數量,它是符合第三範式的。但是,由於存在如下決定關系:

  (倉庫ID) → (管理員ID)

  (管理員ID) → (倉庫ID)

  即存在關鍵字段決定關鍵字段的情況,所以其不符合BCNF範式。它會出現如下異常情況:

  (1) 刪除異常:

  當倉庫被清空後,所有"存儲物品ID"和"數量"信息被刪除的同時,"倉庫ID"和"管理員ID"信息也被刪除了。

  (2) 插入異常:

  當倉庫沒有存儲任何物品時,無法給倉庫分配管理員。

  (3) 更新異常:

  如果倉庫換了管理員,則表中所有行的管理員ID都要修改。

  把倉庫管理關系表分解為二個關系表:

  倉庫管理:StorehouseManage(倉庫ID,管理員ID);

  倉庫:Storehouse(倉庫ID,存儲物品ID,數量)。

這樣的數據庫表是符合BCNF範式的,消除了刪除異常、插入異常和更新異常。

又如,有這樣一個配件管理表WPE(WNO,PNO,ENO,QNT),其中WNO表示倉庫號,PNO表示配件號,ENO表示職工號,QNT表示數量。

有以下約束要求:

(1)一個倉庫有多名職工;

(2)一個職工僅在一個倉庫工作;

(3)每個倉庫裏一種型號的配件由專人負責,但一個人可以管理幾種配件;

(4)同一種型號的配件可以分放在幾個倉庫中。

分析表中的函數依賴關系,可以得到:

(1)ENO->WNO;

(2)(WNO,PNO)->QNT

(3)(WNO,PNO)->ENO

(4)(ENO,PNO)->QNT

可以看到,候選鍵有:(ENO,PNO);(WNO,PNO)。所以,ENO,PNO,WNO均為主屬性,QNT為非主屬性。顯然,非主屬性是直接依賴於候選鍵的。所以此表滿足第三範式。

而我們觀察一下主屬性:(WNO,PNO)->ENO;ENO->WNO。顯然WNO對於候選鍵(WNO,PNO)存在傳遞依賴,所以不符合BCNF.

解決這個問題的辦法是分拆為兩個表:管理表EP(ENO,PNO,QNT);工作表EW(ENO,WNO)。但這樣做會導致函數依賴(WNO,PNO)->ENO丟失。

雖然,不滿足BCNF,也會導致一些冗余和一致性的問題。但是,將表分解成滿足BCNF的表又可能丟失一些函數依賴。所以,一般情況下不會強制要求關系表要滿足BCNF。

5、4NF(第四範式)

對於第四範式,從理論層面來講是,關系模式R∈1NF,如果對於R對於R的每個非平凡多值依賴X→→Y(Y不屬於X),X都含有候選碼,則R∈4NF。4NF就是限制關系模式的屬性之間不允許有非平凡且非函數依賴的多值依賴。顯然一個關系模式是4NF,則必為BCNF。

也就是說,當一個表中的非主屬性互相獨立時(3NF),這些非主屬性不應該有多值。若有多值就違反了第四範式。

這裏提到的多值依賴詳見博客:

有這樣一個用戶聯系方式表TELEPHONE(CUSTOMERID,PHONE,CELL)。CUSTOMERID為用戶ID,PHONE為用戶的固定電話,CELL為用戶的移動電話。

本來,這是一個非常簡單的第3範式表。主鍵為CUSTOMERID,不存在傳遞依賴。但在某些情況下,這樣的表還是不合理的。比如說,用戶有兩個固定電話,兩個移動電話。這時,表的具體表示如下:

CUSTOMERID

PHONE

CELL

1000

8828-1234

149088888888

1000

8838-1234

149099999999

由於PHONE和CELL是互相獨立的,而有些用戶又有兩個和多個值。這時此表就違反第四範式。

在這種情況下,此表的設計就會帶來很多維護上的麻煩。例如,如果用戶放棄第一行的固定電話和第二行的移動電話,那麽這兩行會合並嗎?等等

解決問題的方法為,設計一個新表NEW_PHONE(CUSTOMERID,NUMBER,TYPE).這樣就可以對每個用戶處理不同類型的多個電話號碼,而不會違反第四範式。

顯然,第四範式的應用範圍比較小,因為只有在某些特殊情況下,要考慮將表規範到第四範式。所以在實際應用中,一般不要求表滿足第四範式。

6、5NF(第五範式)

第五範式(5NF):是最終範式。消除了4NF中的連接依賴。

第五範式有以下要求:

(1)必須滿足第四範式

(2)表必須可以分解為較小的表,除非那些表在邏輯上擁有與原始表相同的主鍵。

第五範式是在第四範式的基礎上做的進一步規範化。第四範式處理的是相互獨立的多值情況,而第五範式則處理相互依賴的多值情況。

有一個銷售信息表SALES(SALEPERSON,VENDOR,PRODUCT)。SALEPERSON代表銷售人員,VENDOR代表供和商,PRODUCT則代表產品。

在某些情況下,這個表中會產生一些冗余。可以將表分解為PERSON_VENDOR表(SALEPERSON,VENDOR);PERSON_PRODUCT表(SALEPERSON,PRODUCT);VENDOR-_PRODICT表(VENDOR,PRODUCT)

數據庫表設計五大範式所解決的問題