1. 程式人生 > >【資料庫正規化詳解】1NF-BCNF

【資料庫正規化詳解】1NF-BCNF

關係型資料庫,由於資料分別儲存在不同的表中,因此設計不當就會造成嚴重的資料冗餘。

而如果表的粒度設計得太小,又會放大關係型資料庫讀寫很慢的缺點,表的連線操作會帶來很大的開銷。

因此在設計庫表時,有1NF、2NF、3NF、BCNF、4NF、5NF這些正規化,從前到後要求依次提高。

本文將介紹前4種正規化及使用他們的原因,在實際設計時,一般要求滿足3NF即可。

我的另外兩篇文章:

從ER圖到表的建立,就是符合3NF正規化的,大家在瞭解幾個正規化的原理後,可以參考。

1NF:(關係型資料庫必須滿足的正規化)

定義:

表的設計中,每一列都應是原子的、不可再分。這裡的不可再分也是相對的,例如地址這個屬性,可以細粒度地把它當成複合屬性來看,分為xx國xx省,也可以粗粒度的用一列來表示。

存在的問題:

假設一門課由一個老師教,一個學生可以選多門課。有選課表(學生id,學生姓名,學生性別,教師id,教師姓名,教師性別,課程id,課程名),顯然該表滿足1NF,但存在三種異常。

資料冗餘:一門課程,n個學生選,則老師和課程的資訊就重複儲存了n次。

插入異常:假設想新增一條資料,以表示某學生入學。則有效的資訊只有學生id,學生姓名,學生性別。其他位置必須用NULL值表示,否則無法進行insert操作。

刪除異常:假設一批學生畢業了,要求清空他們的選課記錄,則此時,如果不將學生的資訊用NULL值表示,則所有的教師資訊和課程資訊也將會被清空。

更新異常:假設某個老師要更改自己教的課程名,則選了這門課的所有學生,課程名一列都需要更改。

因為1NF的不足,提出了2NF。

2NF:

定義:

表的設計中,不存在非superkey欄位對任一candidate key欄位的部分函式依賴(部分函式依賴指的是存在複合key中的某些欄位決定非key欄位的情況),也即所有非superkey欄位都完全依賴於任意一組candidate key。

不滿足2NF的例子:

假設某選課系統中存在如下函式依賴,其完全閉包F+={

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

(課程名稱) → (學分),②

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

這個Fc的key是(學號,課程名稱)。由於②和③都存在非關鍵欄位對候選鍵的部分函式依賴(學分依賴候選鍵的一部分),所以它是不滿足2NF的。

修改:

把選課關係表SelectCourse改為如下三個表: 學生:Student(學號, 姓名, 年齡); 課程:Course(課程名稱, 學分); 選課關係:SelectCourse(學號, 課程名稱, 成績)。 這樣的資料庫表是符合第二正規化的,一定程度上減少了資料冗餘、更新異常、插入異常和刪除異常。 另外,所有單關鍵字的資料庫表都符合第二正規化,因為不可能存在組合關鍵字。

滿足2NF也會有資料冗餘、插入/刪除/更新異常的問題,因此提出了3NF。

3NF:

定義:

已知F+,則每張表涉及到的屬性組成一個集合E,考慮它在F+上的函式依賴集,

若對任意的函式依賴 α-->β,滿足如下三個條件之一,則稱為該表的設計滿足3NF。

①α-->β是一個平凡依賴(β∈α)

②α是key

③β-α的每一個屬性A,都∈某一個該表的候選鍵,該條件等價於α不傳遞依賴於superkey

證明③的兩個條件等價:

α不是superkey的情況下才會用到第三個條件來判斷。則α必定是被某個superkey決定的屬性,即有:γ->α   .而α->β,若β不屬於候選鍵的一部分,那麼就會出現γ->β的情況,這是不符合3NF的。但如果β是候選鍵的一部分,那麼γ->β就是一個平凡依賴了。

3NF分解演算法: 1.求出F對應的無冗餘函式依賴集Fc,演算法見我的部落格《求正則覆蓋&判斷保持依賴》 2.對於Fc中的每個函式依賴,都將其作為一個子模式Ri 3.考察每個Ri,若存在至少一個Ri包含原關係R的candidate key則結束(存在一個schema包含一個key就行) 4.否則,將R的key作為一個新的子模式併入分解集中。結束。 首先,我們證明一下演算法的正確性:     首先明確,所有模式的屬性是在無冗餘的Fc上求得的,因此,不可能存在非候選鍵的依賴傳遞:在分解的Ri上,如果有A->B,則AB都是無冗餘的。如果存在B->C,且C是B的一部分,那麼這與B無冗餘矛盾。如果B->A的一部分,那麼這是3NF所允許的,A-B是Ri的候選鍵之一。如果B->D且D不屬於A,B,那麼,這將是一個新的模式Rj。演算法的保持依賴性和無損連線性證明略。
其次我們解釋一下,為什麼需要將候選鍵包含到分解後的模式中
    從分解演算法中我們可以看到,對於所有的非冗餘函式依賴,我們均將其作為一張表分解出去了。因此對於原來的所有函式依賴,必然是被保持的。但是,在屬性上卻有所遺漏。因為可能存在這樣一個屬性:他既不出現在函式依賴左邊,也不出現在函式依賴右邊。但他屬於候選鍵的一部分,我們必須將他包含進分解的模式中,否則,會有屬性的遺漏。  這樣的屬性必然存在於每一個候選鍵中(因為沒有屬效能決定這樣的屬性,所以必須由他自己來決定自己。)  分解例項:

存在的問題: 還是選課系統的背景,假設一名老師只教一門課程;一門課程可由若干個不同的老師來教;每名學生選擇一門課程就對應著一名老師。 根據語義可以得到F+ = { (老師 → 課程), (學生,課程)→老師, (學生,老師) → 課程, } superkey為(老師,學生);(學生,課程)。將表設計為(老師,學生,課程)顯然滿足3NF。 但是,在該表中,由於老師可以確定課程,因此不同學生選了同一門課,在老師和課程這一欄就存在冗餘。 此外,當一個老師開了一門課,但沒有人選時,就必須使用學生是null來標識這個邏輯,有插入異常。
因此BCNF出現了,它的要求是3NF的前兩條。