今天剛好回憶下正規化,參考這篇 如何理解關係型資料庫的常見設計正規化? 文章,我在此文章進一步改進。
教材書這樣定義:符合某一種級別的關係模式的集合,表示一個關係內部各屬性之間的聯絡的合理化程度。
實話實說,真不懂!!然後看了博主的文章解釋的很好。也就可以理解為:一張資料表的表結構所符合的某種設計標準的級別。就比如王者榮耀的VIP,有VIP1,VIP2,VIP3等等,VPI2是基於VIP1而來的,而不是直接跳過VIP1直到VIP2,所以VIP1的獎勵也可以領取。那麼資料庫正規化也分為1NF,2NF,3NF,4NF,5NF。還有一種是BCNF,對於3NF進一步改進。
一般而已,對於資料庫的設計,滿足第三正規化或者BC正規化就足夠了。
第一規格化是對關係模型的最基本的要求,其定義就是資料庫表的每一列都是不可再分割的。
舉正例可能看不清楚,舉個反例:
如上圖,學生、系、課程這些列還可以再分,所以上表不滿足第一規格化,只要不滿足第一規格化的表都不是關係型資料庫表。
正確的做法是:(順便插入幾條記錄)
僅僅滿足第一規格化還是存在很多問題,比如資料冗餘過大,插入異常,刪除問題,修改冗餘的問題。
注1:根據三種關係完整性約束中實體完整性的要求,關係中的碼(注2)所包含的任意一個屬性都不能為空,所有屬性的組合也不能重複。為了滿足此要求,圖中的表,只能將學號與課名的組合作為碼,否則就無法唯一地區分每一條記錄。
注2:碼:關係中的某個屬性或者某幾個屬性的組合,用於區分每個元組(可以把「元組」理解為一張表中的每條記錄,也就是每一行)。
所以為了解決這些問題,出現了第二正規化。
注:屬性是否真的不可拆分,根據你的設計目標而定,比如說姓名,是否還得繼續拆為性和名呢?看自己。
要了解第二正規化,需要一些前置知識:
定義:若在一張表中,在屬性(或屬性組)X 的值確定的情況下,必定能確定 屬性Y 的值,那麼就可以說:Y函數依賴於X,記作 X -> Y。
比如上面的表,通過學號就可以確定姓名(一條記錄),那麼說明:姓名 依賴於 學號;而通過姓名不一定能確定學號(多條記錄),因為可能有同名,說明:學號 不依賴於 姓名。
大白話:知道某屬性值就可以唯一確定另一屬性的值。
定義:如果非主屬性B函數依賴於構成某個候選關鍵字的一組主屬性A,而且A的任何一個真子集不能被B函數依賴,則稱B完全函數依賴於A。如果已經確定就一個主屬性,那麼可以肯定其他屬性完全依賴於該主屬性。
比如上面的表,通過學號和課程名就可以確定成績(僅學號或者課程名不能查出成績),所以成績完全函數依賴於學號和課程名。
大白話:通過一個屬性值,能唯一確定某值,如果是屬性組,那麼該屬性組中必須所有屬性組合在一起才能確定某屬性值。
定義跟上面相反了,定義:若B函數能依賴於A的真子集,則稱B部分函數依賴於A。
比如上面的表,通過學號和課程名可以確定姓名,但是單單通過學號也可以確定姓名,所以姓名部分依賴於學號和課程名。
大白話:僅對於屬性組來說,如果屬性組中不需要所有屬性組合在一起就能確定某值。
定義:在 Y 不包含於 Z 且 Y 不函數依賴於 X,假設 Z函數依賴於Y,且Y函數依賴於X,那麼就稱Z傳遞函數依賴X。
比如上面的表,通過學號可以查出系名,通過系名可以查出系主任,所以通過學號可以查出系主任,所以稱系主任傳遞函數依賴於學號。
定義:能夠唯一標識一條記錄的屬性或屬性集。
比如上面的表,通過學號可以查出系名,通過學號和姓名也可以查出系名類似這樣的,可以說包含該學號的任意屬性組合都是超鍵。
定於:若關係中的一個屬性或屬性組的值能夠唯一地標識一個元組(就是一條記錄),且他的真子集不能唯一的標識一個元組(完全函數依賴),則稱這個屬性或屬性組做候選碼。或者說:能夠唯一標識一條記錄的最小屬性組。
比如上面的表,可以通過學號確定某個屬性的值,但是對於成績,僅僅使用學號不夠,還得有課程名才可能獲取成績,其實對於課程名單單使用學號也無法確定。所以對於 學號 和 課程名 這個屬性組就是候選碼。而通過學號和姓名可以確定系名,但是單單通過學號也可以確定,而姓名是多餘的,所以姓名不是候選碼。
當有多個候選碼時,可以從候選碼中選取一個/或一組作為主鍵。
比如上面的的表,要唯一確定一條記錄,那麼得知道 學號 和 課程名,而這兩個都得作為主鍵。
在候選碼中挑選,比如候選碼為:(A,B),(A,C)。那麼主屬性為A,B,C。
包含在任何一個候選碼中的屬性成為主屬性。那麼非主屬性也就知道了。
比如上面的表,已經確定 學號 和 課程名 這個屬性組就是候選碼,那麼 學號 和 課程名 都是主屬性,那麼其他屬性就都是非主屬性。
那麼第二正規化的定義是:在滿足第一規格化的前提下,是否存在非主屬性對於候選碼的部分函數依賴或者說對於所有的非主屬性是完全函數依賴於候選碼。若存在,則資料表最高只符合1NF的要求,若不存在,則符合2NF的要求。(大白話:找主鍵,能夠確定某列的值,但是如果有多個主鍵,看看這些主鍵還要不要拆分,判斷條件:這些主鍵能夠確定某列A的值並且不存在這些主鍵中其中一個就能確定某列A值)
判斷的方法是:
例子:
所以上表不滿足第二正規化。那麼需要對錶進行拆分,根據上面的分析,可以拆分為:
現在重新分析這樣是否滿足第二正規化:
現在來看看第一規格化存在的問題是否解決:
資料冗餘過大:有所改進,但是比如還有多個計算機系的學生,那麼系名和系主任兩個列還是重複出現。
插入異常:假設新建一個系,那麼這個系的資訊在還沒學生前不能提前錄入表中,因為沒有主鍵。還存在該問題。
刪除問題:假設某個系的學生都沒有了,刪除後那麼該系的資訊也都沒有了。實際上,雖然沒有學生了,但不代表這個系不存在。還存在該問題。
修改冗餘:假設某個學生轉系,那麼就得修改他的系資訊,而且還得修改多次,比如上面的小山轉系,那麼得修改2次。已經解決,因為可以保證學生表中每位學生只出現一次,所以轉系時只需要改一次。
所以在第二正規化的基礎上,提出了第三正規化來解決這些問題。
定義:在第二正規化的基礎上,消除了非主屬性對於候選碼的傳遞函數依賴。也就是說:要求資料庫表中不包含其他表的非關鍵字資訊(消除冗餘的列,或者說非主鍵外的所有欄位必須互不依賴)。
分析上面的倆張表:
改進學生表:把學校資訊和系資訊拆分成兩張表:
不分析了,很容易看得出滿足第三正規化。
現在來看看之前的問題是否解決:
資料冗餘過大:已經解決。每位學生肯定還得對於一個系名,但至少系主任不會重複出現。
插入異常:假設新建一個系,可以直接錄入系表。已經解決。
刪除問題:假設某個系的學生都沒有了,刪除後,該系的資訊還可以存在,除非真要刪除該系資訊。已經解決。
定義:在滿足第三正規化的基礎上,消除主屬性對於候選碼的部分與傳遞函數依賴。(大白話:在多個主屬性中,消除多餘主屬性)
是對於第三正規化的改進,上面的第三正規化都沒問題的,為什麼還得改進?來看看特殊情況:
那麼關係模式 倉庫(倉庫名,管理員,物品名,數量) 屬於哪一級正規化?分析一波:
可以發現滿足第一規格化,並且不存在非主屬性部分函數依賴和傳遞函數依賴於候選碼,所以滿足第三正規化。
雖然滿足第三正規化,但看看有什麼問題存在:
所有雖然滿足了第三正規化,但該表不是一個很好,主要的原因在於:存在著主屬性對於候選碼的部分函數依賴與傳遞函數依賴。也就是:倉庫名 對於 管理員、物品名 存在部分函數依賴與傳遞函數依賴:
如何解決?拆表:
可以發現上面存在的問題可以解決。
第一規格化:資料庫表中的屬性(或者欄位或者列)不可再分割。
第二正規化:在滿足第一規格化的前提下,找主鍵,能夠確定某列的值,但是如果有多個主鍵,看看這些主鍵還要不要拆分,判斷條件:這些主鍵能夠確定某列A的值並且不存在這些主鍵中其中一個就能確定某列A值
第三正規化:在滿足第二正規化的前提下,消除冗餘的列,或者說非主鍵外的所有欄位必須互不依賴。
BC正規化:在滿足第三正規化的前提下,在多個主屬性中,消除多餘主屬性。
最好理解正規化中出現的問題。並且正規化並不是需要絕對遵守的準則,就像姓名這個欄位,可能不需要繼續拆分,可能需要拆為性和名兩個欄位。
有錯請指出