資料庫"正規化"
1.為什麼要學習資料庫”正規化”?
當我們獨立去完成一個自己的小專案的時候,肯定要去設計”合適”的資料模型即邏輯架構,那麼,我們怎麼知道自己設計的資料模型是最”合適”的呢?肯定得有一個標準去衡量自己設計的資料模型,看到這裡,大家知道為什麼要學習正規化了.
2.”正規化”能解決什麼問題?
剛才說過,學習正規化是為了去設計一個”合適的”資料模型,那麼,一個”合適”的資料模型,它能解決什麼問題呢?
1.消除資料冗餘.
2.消除更新異常.
3.消除插入異常
4.消除刪除異常.
3.正規化的概念
正規化是符合某一種級別的關係模式的集合,它是關係資料庫理論的基礎,也是我們在設計資料庫結構中所要尊循的規則和指導方法. 資料庫有5個基本的正規化:即第一正規化(1NF),第二正規化(2NF),第三正規化(3NF),BCNF(BC正規化),第四正規化(4NF)。甚至還有5NF,6NF,DK正規化,本文只討論前面五種正規化,這五種正規化,就是為了解決第二個點中所說的問題.從1NF到4NF逐級提高標準,大家可以把它理解為猿到人的進化過程。
4.具體的例子
用一個具體的例子來分析這幾種正規化.
學號 | 姓名 | 系名 | 宿舍樓 | 課程號 | 成績 |
---|---|---|---|---|---|
03001 | 周毅 | 電信系 | A樓 | 語文 | 95 |
03001 | 周毅 | 電信系 | A樓 | 數學 | 89 |
04015 | 崔勇 | 計算機系 | C樓 | 大物 | 70 |
04015 | 崔勇 | 計算機系 | C樓 | 英語 | 85 |
03018 | 王文濤 | 電信系 | A樓 | 語文 | 87 |
03019 | 馬季軍 | 法律系 | B樓 | 大物 | 88 |
03019 | 賀智平 | 法律系 | B樓 | 大物 | 56 |
在上面提到了關係模式.而這張表的關係有
1.學號(x)–>姓名(y).
2.學號(x)–>系名(y).
3.系名(x)–>宿舍樓(y).
4.(學號,課程)(x)–>成績(y).
怎樣去理解上面的關係呢?它們的關係就是y=x^2,當x確定時,y一定有唯一值,即x唯一確定y.
4.幾種特殊的函式依賴
1.平凡函式依賴:如果A屬性組唯一確定B,並且B屬性屬於A屬性組,那麼A–>B是平凡函式依賴。eg:在上表中(學號,課程)—>課程.課程屬於(學號,課程)這個屬性組. 對於任以關係模式,平凡函式依賴都是成立的。所以,討論它是,沒有意義的,所以大家瞭解就行.
2.非平凡函式依賴:如果A屬性組唯一確定B,並且B屬性不屬於A屬性組,那麼A—>B是非平凡函式依賴.eg:在上表中(學號,課程)—->成績,成績不屬於(學號,課程)這個屬性組,所以是非平凡函式依賴.
3.部分函式依賴:A屬性組可以確定B,但是B不完全依賴於X,什麼意思呢,eg(學號,課程)—>姓名.(學號,課程)可以唯一確定姓名,但是姓名只需要一個學號就能唯一確定,沒有課程也可以,這就稱B部分依賴A.
4.完全函式依賴:A屬性組唯一確定B,並且A屬性組的任何一個真子集不能唯一確定B。那麼稱B完全依賴於A.eg: (學號,課程)–>成績.(學號,課程中的任何一個都不能唯一確定成績),所以說成績完全依賴於(學號,課程);
5.傳遞函式依賴:如果屬性A–>B,B–>C,那麼A–>C.且B不屬於A,B也不能唯一確定A,那麼A–>C.eg:學號—>系名,系名—>宿舍樓. 那麼學號—>宿舍樓.為傳遞函式依賴.
6.碼:一個屬性或者屬性組能唯一確定本屬性或屬性組之外的所有屬性,即其它屬性完全依賴此屬性或屬性組.eg(學號,課程)唯一確定(姓名,系名,宿舍樓,成績),那麼,怎樣去找碼呢,如果有n個屬性列,那麼所有的組合,一個屬性的組合n種,二個屬性的組合,Cn2(代表從n箇中任意取兩個),三個屬性的組合Cn3(代表從n箇中任意取三個)……….當然,不可能一個一個去試.那是有技巧的,當你已經知道(學號,課程)是碼,那麼以後,包含這個列的組成直接忽略.因為碼是完全函式依賴.
7.主屬性:碼中包含的屬性叫做主屬性.
8.非主屬性:除過碼中包含的屬性之外的所有屬性.
9.單碼:單個屬性是碼.
10.全碼:整個屬性組是碼,稱為全碼.
6.第一正規化(1NF)
如果關係模式R中不包含多值屬性,則R滿足第一正規化.並且,關係模式中所有的屬性都是不可再分事務資料項,第一正規化是對關係模式的最低要求,不滿足第一正規化的資料庫模式稱為關係型資料庫. 具體來看個例子吧:
在上面這個表中,學生對應(學號,姓名),明顯學生既對應學號,又對應姓名.所以,這應該分開做出調整,第一張(下面這張表就滿足第一正規化).
學號 | 姓名 | 系名 | 宿舍樓 | 課程號 | 成績 |
---|---|---|---|---|---|
03001 | 周毅 | 電信系 | A樓 | 語文 | 95 |
03001 | 周毅 | 電信系 | A樓 | 數學 | 89 |
04015 | 崔勇 | 計算機系 | C樓 | 大物 | 70 |
04015 | 崔勇 | 計算機系 | C樓 | 英語 | 85 |
03018 | 王文濤 | 電信系 | A樓 | 語文 | 87 |
03019 | 馬季軍 | 法律系 | B樓 | 大物 | 88 |
03020 | 賀智平 | 法律系 | B樓 | 大物 | 56 |
在看上面我們提到的4個正規化我們要解決的4個問題,第一正規化是否解決了上面的問題,解決了幾個:
* 資料冗餘可以看到姓名,系名,宿舍樓大量的重複.
* 更新異常:如果一個學生改名,則關於這個學生的所有的選課元組都得更新(eg:如果周毅改名,則需要去改兩列).
* 刪除異常:如果計算機的系的學生全部畢業,相應的計算機系以及C樓的資訊也會被刪除.
* 插入異常:如果學校新開了某個系,但是沒有招學生,這個系就無法插入.
7.第二正規化(2NF)
在第一正規化的基礎上,如果每個非主屬性對主屬性都達到了完全函式依賴,則滿足第二正規化的要求(2NF),換去話說,就是消除所有非主屬性對主屬性的部分函式依賴(ps:這是第二正規化的要求),那麼,怎麼去分析呢?看我們上面的例子:
主屬性:(學號,課程); ps:主屬性必須是碼哦.
非主屬性:姓名,系,宿舍樓,成績.
(學號,課程)—>姓名: 姓名由學號就能唯一確定,所以姓名對(學號,課程)是部分函式依賴.
(學號,課程)—>系:系和姓名一樣,由學號能唯一確定.
為了消除關係模式中的部分函式依賴,採用投影分解法,將部分函式依賴從關係模式中分離出來,得到以下兩張表.
SC(學號,課程,成績);
SL(學號,姓名,系名,宿舍樓);
得到兩張表分別為:
SC表
學號 | 課程 | 成績 |
---|---|---|
03001 | 語文 | 95 |
03001 | 數學 | 89 |
04015 | 大物 | 70 |
04015 | 英語 | 85 |
03018 | 語文 | 87 |
03019 | 大物 | 88 |
03020 | 大物 | 56 |
S表
學號 | 姓名 | 系名 | 宿舍樓 |
---|---|---|---|
03001 | 周毅 | 電信系 | A樓 |
04015 | 崔勇 | 計算機系 | C樓 |
03018 | 王文濤 | 電信系 | A樓 |
03019 | 馬季軍 | 法律系 | B樓 |
03020 | 賀智平 | 法律系 | B樓 |
在看上面提到的4個問題我們解決了幾個:
資料冗餘:明顯的可以看出姓名,系名,系主任的資料冗餘得到了明顯的改善.
更新異常:現在,一個學生改名,,只需要改S表中的姓名,而沒有必要改他的每一條選課記錄.
插入異常:如果現在學校新開設一個系,在沒有招生的情況下,系還是不能插入到S表中,因為學號是主屬性.()
刪除異常:一個系的所有學生畢業,再刪除所有學生資訊的同時,會連帶著刪掉所有系的資訊.
既然第二正規化只是降低了資料冗餘度,其它的並沒有得到提高. 那麼,接著,我們一起來看第三正規化:
8.第三正規化(3NF)
同樣,第三正規化是建立在第二正規化的基礎上.而第三正規化的目的是消除非主屬性對主屬性的傳遞函式依賴.
在第二正規化中,我們得到了兩張表:
SC表:選課(學號,課程,成績).
S表:(學號,姓名,系名,宿舍樓)
還記得什麼是傳遞函式依賴吧,如果忘了,翻到上面去看看.分析SC表,我們發現,不存在傳遞函式依賴,而在S表(學號)–>(系名) (系名)—>(宿舍樓)存在傳遞函式依賴,那我們就解決了這個傳遞函式依賴,看看上面的問題能不能得到改善呢?
SC表:選課(學號,課程,分數)
S表:學生(學號,姓名,系名);
D表:系(系,宿舍樓);
得到三張表
SC表
學號 | 課程 | 成績 |
---|---|---|
03001 | 語文 | 95 |
03001 | 數學 | 89 |
04015 | 大物 | 70 |
04015 | 英語 | 85 |
03018 | 語文 | 87 |
03019 | 大物 | 88 |
03020 | 大物 | 56 |
S表
學號 | 姓名 | 系名 |
---|---|---|
03001 | 周毅 | 電信系 |
04015 | 崔勇 | 計算機系 |
03018 | 王文濤 | 電信系 |
03019 | 馬季軍 | 法律系 |
03020 | 賀智平 | 法律系 |
D表
系 | 宿舍樓 |
---|---|
電信系 | A樓 |
法律系 | B樓 |
計算機系 | C樓 |
再看上面的問題我們第三正規化解決了幾個:
插入異常:如果現在學校新開設一個系.就算沒有納入招生計劃,此係還是可以插入到D表中.
刪除異常,就算現在一個系中的所有學生都畢業了,刪除這個系的所有學生的資訊,這個系的資訊也不會被刪除。
大家可以發現,到現在為止,資料冗餘,更新異常,插入異常,刪除異常都得到了改善.它已經能基本滿足我們的需要了.
9.BC正規化(BCNF)
BC正規化:BC正規化是在第三正規化的基礎上的一種特殊情況,既每個表只有一個候選鍵(在一個數據庫中每行的值都不相同,則可稱為候選鍵)。
每一個決定因素都為鍵,則R一定屬於BC正規化,對於BCNF的關係模式,具有以下性質:
(1)所有非主屬性都完全依賴於每個主屬性.(在第二正規化2NF中已經實現)
(2)所有主屬性對每一個不包含它的主屬性都是完全函式依賴;
(3)沒有任何屬性完全函式依賴於非主屬性中任何一組屬性. (第三正規化中已經實現)
那麼,BC正規化就是完全針對主屬性而言的,即上面所說的第二條.所有主屬性對每一個不包含它的主屬性都是完全函式依賴;
看個具體的例子
假設倉庫管理關係表為storehourseMange(倉庫ID,儲存物品ID,管理員ID,數量).
倉庫ID | 儲存物品ID | 管理員ID | 數量 |
---|---|---|---|
A1 | S1 | C1 | 20 |
A1 | S2 | C1 | 30 |
A2 | S3 | C2 | 40 |
A2 | S4 | C2 | 50 |
A2 | S5 | C2 | 60 |
此表滿足:
- 一個管理員只在一個倉庫工作
- 一個倉庫可以儲存多種物品
這個資料庫表存在如下決定關係:
(倉庫ID,儲存物品ID)—->(管理員ID,數量)
(管理員ID,儲存物品ID)—>(倉庫ID,數量)
主屬性:倉庫ID,儲存物品ID,管理員ID.
非主屬性:數量.
碼(還記得碼的概念吧,不記得了翻上去看看):(倉庫ID,儲存物品ID),(管理員ID,儲存物品ID).
先來確定這個張表是否滿足第三正規化(3NF),因為BCNF正規化是建立在第三正規化的基礎之上的.
分析表可以看出.不存在非主屬性對對主屬性的部分函式依賴和傳遞函式依賴.滿足第三正規化.
那麼先來看看上面提到的四個問題:
資料冗餘:看錶很明顯這個問題不存在.
插入異常:如果現在新建一個倉庫,但是不給這個倉庫中存任何物品,那麼,此條資料無法存入.
刪除異常:如果某個倉庫的物品全部出庫,刪除這個物品的同時,對應的倉庫也會被刪除.
更新異常:如果某個倉庫換了管理員,則要改多條資料.
原因是什麼呢?
看這個關係(倉庫ID,)
(管理員ID,儲存物品ID)—->(倉庫ID);看這個關係,三個屬性都是主屬性,但是(管理員ID就能唯一確定倉庫ID),所以倉庫ID對(管理員ID,儲存物品ID)存在部分函式依賴.
分解表得到:
倉庫:(倉庫ID,管理員ID);
物品:(倉庫ID,儲存物品ID,數量);
倉庫:
倉庫ID | 管理員ID |
---|---|
A1 | C1 |
A2 | C2 |
物品:
倉庫ID | 儲存物品ID | 數量 |
---|---|---|
A1 | S1 | 20 |
A1 | S2 | 30 |
A2 | S3 | 40 |
A2 | S4 | 50 |
A2 | S5 | 60 |
再看剛才的問題:
- 插入異常: 新建一個倉庫,就算裡面沒有東西,也可以插入倉庫表.
- 更新異常:,某個倉庫的管理員換了,則只需要改倉庫表中的一條資料.
- 刪除異常:某個倉庫的物品全部出庫,此倉庫也不會被刪除.
10.第四正規化(4NF)
上面解決的是在函式依賴的範疇內有關關係模式的規範化問題,如果一個關係模式達到了BCNF,是否就完美了。看下面這個例子:
在一個教學管理系統中,有一個關係模式Teaching(C,T,B),其中C表示課程,T表示教師,B表示參考書.
存在如下關係:
- 一門課程由多個老師講授,它們使用同一套參考書.
- 每個老師可以講授多門課程,每本參考書可以供多門課程使用.
課程C | 教師T | 參考書B |
---|---|---|
資料庫原理及應用 | 鄧宇 | 資料庫系統概論 |
資料庫原理及應用 | 鄧宇 | SQL Server2000 |
資料庫原理及應用 | 鄧宇 | 離散數學 |
資料庫原理及應用 | 孫澤 | 資料庫系統概論 |
資料庫原理及應用 | 孫澤 | 資料庫系統概論 |
資料庫原理及應用 | 孫澤 | 資料庫系統概論 |
資料結構 | 孫澤 | 資料結構與演算法 |
資料結構 | 孫澤 | 資料結構 |
資料結構 | 孫澤 | 離散數學 |
資料結構 | 曹鵬 | 資料結構與演算法 |
資料結構 | 曹鵬 | 資料結構與演算法 |
資料結構 | 曹鵬 | 離散數學 |
很顯然:這張表是全鍵;
先來看上面所提到的4個問題:
- 資料冗餘:課程,教師,參考書的有關資訊大量重複儲存.
- 插入異常:當某門課增加一個任課老師,必須插入多個元組.
- 更新異常:如果某門課換了老師,則必須修改多行值.
- 刪除異常:若要刪除某一本參考書,則需要刪除多條記錄.
這張表為什麼會出現這樣的問題呢?
大家先來看看這張表的關係:
一門課程有多本參考書,很明顯是一對多的關係. 也就是說課程對參考書有多值依賴關係。
剛才說到了多值依賴,那麼,先來看看什麼叫做多值依賴:
設R(U)是屬性集U上的一個關係模式,X,Y,Z是U的子集,且Z=U-X-Y.關係模式R(U)中多值依賴X–>—>Y成立,當且僅當對R(U)的任一關係r,給定的一對(x,z)值,有一組Y的值.這組值僅僅決定x的值而與z的值無關.
eg: 在上面的關係模式中,對於一個(C,B)值(資料庫原理及應用,SQL Server 2000),有一組T值{鄧宇,孫澤},而這組值僅僅決定於課程C(資料庫原理及應用),所以T的值與B的值無關m僅由C決定,C—>—>T;
將上表分解為兩個關係模式:
T(課程C,教師T) ;
B(課程C,參考書) ;
關係T
課程C | 教師T |
---|---|
資料庫原理及應用 | 鄧宇 |
資料庫原理及應用 | 孫澤 |
資料結構 | 孫澤 |
資料結構 | 曹鵬 |
關係B
課程C | 參考書B |
---|---|
資料庫原理及應用 | 資料庫系統概論 |
資料庫原理及應用 | SQL Server2000 |
資料庫原理及應用 | 離散數學 |
資料結構 | 資料結構與演算法 |
資料結構 | 資料結構 |
資料結構 | 離散數學 |
看看上面的問題有沒有得到改善:
- 資訊冗餘: 得到改善;
- 插入問題:某個課程增加老師季,只要在T表中新增一條記錄就好了.
- 刪除問題:刪除一本書,也只要在BC表中刪除一條記錄即可.
總結一下:
- 上面對於資料庫正規化進行分解的過程中不難看出,應用的正規化登記越高,則表越多。表多會帶來很多問題:
- 查詢時要連線多個表,增加了查詢的複雜度.
- 查詢時需要連線多個表,降低了資料庫查詢效能.
- 而現在的情況,磁碟空間成本基本可以忽略不計,所以資料冗餘所造成的問題也並不是應用資料庫正規化的理由。
- 因此,並不是應用的正規化越高越好,要看實際情況而定。第三正規化已經很大程度上減少了資料冗餘,並且減少了造成插入異常,更新異常,和刪除異常了。我個人觀點認為,大多數情況應用到第三正規化已經足夠,在一定情況下第二正規化也是可以的。