資料庫建表正規化學習
資料庫正規化
設計關係資料庫時,遵從不同的規範要求,設計出合理的關係型資料庫,這些不同的規範要求被稱為不同的正規化,各種正規化呈遞次規範,越高的正規化資料庫冗餘越小。
目前關係資料庫有六種正規化:第一正規化(1NF)、第二正規化(2NF)、第三正規化(3NF)、巴斯-科德正規化(BCNF)、第四正規化(4NF)和第五正規化(5NF,又稱完美正規化)。
基本概念
侯選關鍵字:又叫侯選碼,惟一標識一行資料,其真子集不能是侯選關鍵字,一個表可以存在多個侯選關鍵字,如使用者表的username,userid。
主關鍵字:又叫主鍵,主碼,被選中的用來區分其它行的侯選關鍵字,一個表只有一個主關鍵字。
部分依賴
傳遞依賴:A->B->C,則C傳遞依賴A。
屬性:實體所具有的某一特性,屬性一開始是個邏輯概念,在關係資料庫中,屬性又是個物理概念,屬性可以看作是“表的一列”。
元組:表中的一行就是一個元組。
分量:元組的某個屬性值。在一個關係資料庫中,它是一個操作原子。
碼:表中可以唯一確定一個元組的某個屬性(或者屬性組),如果這樣的碼有不止一個,那麼大家都叫 候選碼,我們從候選碼中挑一個出來做老大,它就叫主碼。
全碼:如果一個碼包含了所有的屬性,這個碼就是全碼。
第一正規化(1NF)
-
定義
資料庫的欄位是單一屬性,不可再分。 -
要求
- 不能是複合屬性,如果存在,應該拆分為多個屬性
- 不能是多值屬性,如果存在,應該建立一個實體,而讓此屬性與其存在1對多的關係)
- 不能是重複屬性
-
概述
確保每列保持原子性,原子性意味著無法繼續拆分,資料庫表中的所有欄位值都應是不可分解的原子值。
第一正規化的合理遵循需要根據系統的實際需求來定。比如某些資料庫系統中需要用到“地址”這個屬性,本來直接將“地址”屬性設計成一個數據庫表的欄位就行。但是如果系統經常會訪問“地址”屬性中的“城市”部分,那麼就非要將“地址”這個屬性重新拆分為省份、城市、詳細地址等多個部分進行儲存,這樣在對地址中某一部分操作的時候將非常方便。
原文:https://blog.csdn.net/kenhins/article/details/51084815
第二正規化(2NF)
-
定義
任何非關鍵欄位不能部分依賴任一侯選關鍵字(即必須完全依賴)。 -
要求
- 表中必須存在侯選關鍵字,即每一行不同於其他任一行,是惟一區分的
- 任何非關鍵欄位不能依賴於侯選關鍵字的一部分
-
概述
確保表中的每列都和主鍵相關,第二正規化在滿足了第一正規化的基礎上,確保表中的每列都和主鍵相關,而不是和主鍵(聯合主鍵)的一部分相關。若表中某幾個欄位只是和聯合主鍵的某部分相關,應將這幾個欄位拿出以聯合主鍵的部分為主鍵另建新表。 -
例項
假定選課關係表為SelectCourse(學號,姓名,年齡,課程名稱,成績,學分),關鍵字為組合關鍵字(學號,課程名稱),因為存在如下決定關係:
(學號,課程名稱) → (姓名,年齡,成績,學分)
學號 | 課程名稱 | 姓名 | 年齡 | 成績 | 學分 |
---|
這個資料庫表不滿足第二正規化,因為存在如下決定關係:
- 學分只和課程相關
(課程名稱) → (學分) - 姓名、年齡、成績只和學號相關
(學號) → (姓名,年齡)
即存在組合關鍵字中的欄位決定非關鍵字的情況。
由於不符合2NF,這個選課關係表會存在如下問題:
- 資料冗餘:
同一門課程由n個學生選修,"學分"就重複n-1次;同一個學生選修了m門課程,姓名和年齡就重複了m-1次。 - 更新異常:
若調整了某門課程的學分,資料表中所有行的"學分"值都要更新,否則會出現同一門課程學分不同的情況。 - 插入異常:
假設要開設一門新的課程,暫時還沒有人選修。這樣,由於還沒有"學號"關鍵字,課程名稱和學分也無法記錄入資料庫。 - 刪除異常:
假設一批學生已經完成課程的選修,這些選修記錄就應該從資料庫表中刪除。但是,與此同時,課程名稱和學分資訊也被刪除了。很顯然,這也會導致插入異常。
把選課關係表SelectCourse改為如下三個表:
- 學生表:Student(學號,姓名,年齡)
學號 | 姓名 | 年齡 |
---|
- 課程表:Course(課程名稱,學分)
課程名稱 | 學分 |
---|
- 選課關係:SelectCourse(學號,課程名稱,成績)
學號 | 課程名稱 | 成績 |
---|
這樣的資料庫表是符合第二正規化的, 消除了資料冗餘、更新異常、插入異常和刪除異常。
另外,所有單關鍵字的資料庫表都符合第二正規化,因為不可能存在組合關鍵字。
第三正規化(3NF)
-
定義
任何非關鍵欄位不能傳遞依賴任一侯選關鍵字 -
要求
- 非關鍵字欄位必須直接依賴任一侯選關鍵字
- 非關鍵欄位C不能依賴非侯選關鍵字B,因為樣會形成傳遞依賴:侯選關鍵字A=>B=>C,因為這時的B往往是外來鍵,即其他表的主鍵,也就是說表中不能含有其他表的非主屬性
-
概述
確保表中的每列都和主鍵直接相關,而不是間接相關。第三正規化是第二正規化的一個子集,即滿足第三正規化必須滿足第二正規化。第三正規化在第二正規化的基礎上消除了傳遞依賴,即任何非主鍵屬性不應依賴於其他非主鍵屬性。 -
例項
假定學生關係表為Student(學號,姓名,年齡,所在學院,學院地點,學院電話),主鍵為"學號",因為存在如下決定關係:
(學號) → (姓名,年齡,所在學院,學院地點,學院電話)
這個資料庫是符合2NF的,但是不符合3NF,因為存在如下決定關係:
(學號) → (所在學院) → (學院地點,學院電話)
即存在非主鍵欄位"學院地點"、"學院電話"對主鍵欄位"學號"的傳遞依賴。
它也會存在資料冗餘、更新異常、插入異常和刪除異常的情況,讀者可自行分析得知。
把學生關係表分為如下兩個表:
- 學生:(學號,姓名,年齡,所在學院);
學號 | 姓名 | 年齡 | 所在學院 |
---|
- 學院:(學院,地點,電話)
學院 | 地點 | 電話 |
---|
這樣的資料庫表是符合第三正規化的,消除了資料冗餘、更新異常、插入異常和刪除異常。
巴斯-科德正規化(BCNF)
-
定義
任何欄位都不能傳遞依賴任一侯選關鍵字 -
要求
- 與第三正規化相比,一個是“任何非關鍵欄位不能”,一個是“任何欄位不能”,顯然更嚴格了
- 侯選關鍵字或其部分欄位不能傳遞依賴其他的侯選關關鍵字
-
概述
在第三正規化基礎上,聯合主鍵的各欄位之間互不依賴。BC正規化是對第三正規化的修正補充,是指在第三正規化的基礎上進一步消除主屬性對於碼的部分函式依賴和傳遞依賴。BCNF需要符合3NF,並且,主屬性不依賴於主屬性。 -
例項1
假設倉庫管理關係表為StorehouseManage(倉庫ID,儲存物品ID,管理員ID,數量),且有一個管理員只在一個倉庫工作;一個倉庫可以儲存多種物品。這個資料庫表中存在如下決定關係:
(倉庫ID,儲存物品ID) →(管理員ID,數量)
(管理員ID,儲存物品ID) → (倉庫ID,數量)
所以,(倉庫ID,儲存物品ID)和(管理員ID,儲存物品ID)都是StorehouseManage的候選關鍵字,表中的唯一非關鍵欄位為數量,它是符合第三正規化的。但是,由於存在如下決定關係:
(倉庫ID) → (管理員ID)
(管理員ID) → (倉庫ID)
即存在關鍵欄位決定關鍵欄位的情況,所以其不符合BCNF正規化。它會出現如下異常情況:- 刪除異常:
當倉庫被清空後,所有"儲存物品ID"和"數量"資訊被刪除的同時,"倉庫ID"和"管理員ID"資訊也被刪除了。 - 插入異常:
當倉庫沒有儲存任何物品時,無法給倉庫分配管理員。 - 更新異常:
如果倉庫換了管理員,則表中所有行的管理員ID都要修改。
- 刪除異常:
把倉庫管理關係表分解為二個關係表:
- 倉庫管理:StorehouseManage(倉庫ID,管理員ID)
倉庫ID | 管理員ID |
---|
- 倉庫:Storehouse(倉庫ID,儲存物品ID,數量)
倉庫ID | 儲存物品ID | 數量 |
---|
這樣的資料庫表是符合BCNF正規化的,消除了刪除異常、插入異常和更新異常。
- 例項2
有一個配件管理表WPE(WNO,PNO,ENO,QNT),其中WNO表示倉庫號,PNO表示配件號,ENO表示職工號,QNT表示數量。
有以下約束要求:
- 一個倉庫有多名職工;
- 一個職工僅在一個倉庫工作;
- 每個倉庫裡一種型號的配件由專人負責,但一個人可以管理幾種配件;
- 同一種型號的配件可以分放在幾個倉庫中。
分析表中的函式依賴關係,可以得到:
- ENO->WNO;
- (WNO,PNO)->QNT
- (WNO,PNO)->ENO
- (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。