資料庫三正規化

roran發表於2020-04-05

什麼是三正規化

設計關係型資料庫時,遵從不同的規範要求,設計出合理的關係型資料庫,這些不同的規範要求被稱為不同的正規化,各種正規化呈遞次規範,越高的正規化資料庫冗餘越小。

目前關係型資料庫有六種正規化:第一正規化(1NF)、第二正規化(2NF)、第三正規化(3NF)、巴斯-科德正規化(BCNF)、第四正規化(4NF)和第五正規化(5NF,又稱完美正規化)。一般來說,資料庫只需要滿足第三正規化就行了。

 

第一正規化:保證每列的原子性

第一正規化是最基本的正規化。如果資料庫表中的所有欄位值都是不可分解的原子值,就說明該資料庫滿足了第一正規化。

第一正規化需要根據系統的實際需求來定,比如有一張使用者資訊表:

一般來說"住址"設計成一個欄位就行,但是如果經常訪問"住址"中城市的部分,那麼就非要將"住址"這個屬性重新拆分為"省份"、"城市"、"地址"等多個部分進行儲存,這樣在對"住址"中某一部分進行操作的時候將非常方便。這麼設計才算滿足了資料庫的第一正規化,修改之後的表結構如圖:

 

第二正規化:保證一張表只描述一件事情

這是通俗的說法,用第二正規化的定義描述第二正規化,說的是在滿足第一正規化的基礎上,資料庫表中不存在非關鍵欄位對任一候選關鍵欄位的部分函式依賴,也即所有非關鍵欄位都完全依賴於任一組候選關鍵字。

看不懂是嗎,沒關係,我也看不懂,下面舉一個例子,有一張表如下圖:

上表滿足第一正規化,即每個欄位不可再分,但是這張表設計得並不好,或者說,這張表的設計並不滿足第二正規化。因為這張表裡面描述了兩件事情:學生資訊、課程資訊,"學分"完全依賴於"課程名稱"、"姓名"與"年齡"完全依賴於"學號"。這麼做的後果是:

1、資料冗餘:同一門課程由n個學生選修,"學分"重複n-1次;同一個學生選修了m門課程,姓名和年齡重複m-1次

2、更新異常:若調整了某門課程的學分,資料表中所有行的"學分"值都需要更新,否則會出現同一門課程學分不同的情況

3、插入異常:假設要開一門新課程,暫時沒有人選修,那麼由於沒有"學號"關鍵字,"課程"與"學分"也無法記錄入資料庫

4、刪除異常:假設一批學生已經完成課程的選修,這些選修記錄就應該從資料庫表中刪除。但是,與此同時,"課程"和"學分"也被刪除了,顯然,這最終可能會導致插入異常

所以,此表的結構必須修改,修改後如下:

增加了表,將學生資訊與課程資訊通過一張中間表關聯,很好地解決了上面的幾個問題,這就是第二正規化的中心----保證一張表只講一件事情。

 

第三正規化----保證每列都和主鍵直接相關

第三正規化又和第二正規化相關,用第三正規化的定義描述第三正規化就是,資料庫表中如果不存在非關鍵欄位任一候選關鍵欄位的傳遞函式依賴則符合第三正規化,所謂傳遞函式依賴指的是如果存在"A-->B-->C"的決定關係,則C傳遞函式依賴於A。也就是說表中的欄位和主鍵直接對應不依靠其他中間欄位,說白了就是,決定某欄位值的必須是主鍵

舉個例子,看一下如下的表結構:

第三正規化和第二正規化有點像,從這張資料庫表結構中可以看出,"姓名"、"年齡"、"學院"和主鍵"學號"直接關聯,但是"學院地點"、"學院電話"卻不直接和主鍵"學號"相關聯,和"學院電話"直接相關聯的是"學院",如果表結構這麼設計,同樣會造成和第二正規化一樣的資料冗餘、更新異常、插入異常、刪除異常的問題。

修改之後的表結構如下圖:

同樣,這麼設計表結構將合理地多,也解決了前面的四個問題。

 

後記

定理是死的,人是活的,在前人給我們總結出這些正規化的前提下,使用這些正規化靈活地應用到實際需求中,才是最重要的。

相關文章