該文章,GitHub已收錄,歡迎老板們前來Star!
GitHub地址: https://github.com/Ziphtracks/JavaLearningmanual
資料庫范式
一、什么是資料庫范式
設計關系資料庫時,遵從不同的規范要求,設計出合理的關系型資料庫,這些不同的規范要求被稱為不同的范式,各種范式呈遞次規范,越高的范式資料庫冗余越小,
范式來自英文Normal form,簡稱NF,要想設計—個好的關系,必須使關系滿足一定的約束條件,此約束已經形成了規范,分成幾個等級,一級比一級要求得嚴格,滿足這些規范的資料庫是簡潔的、結構明晰的,同時,不會發生插入(insert)、洗掉(delete)和更新(update)操作例外,
二、資料庫范式分類
目前關系資料庫有六種范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又稱完美范式),滿足最低要求的范式是第一范式(1NF),在第一范式的基礎上進一步滿足更多規范要求的稱為第二范式(2NF),其余范式以次類推,一般來說,資料庫只需滿足第三范式(3NF)就行了,
三、資料庫三大范式剖析
3.1 第一范式(1NF)
第一范式強調每一列都是不可分割的原子資料項,
說到原子這個詞,肯定有小伙伴就先到了原子性問題,其實這么想也是沒有錯的,那就讓我帶你們去剖析一下第一范式,
首先,我用Excel表格模擬資料庫中的表,并在表中填入了一些資料,如下:

當你看到這些資料的時候,是否有些資料讓你感到不適?我的答案,是的,當我看到系名/系主任這一列資料的時候感覺這并不合符我們資料庫的設計理念,因為它完全可以拆分為兩個列的,其實每一個人的思想中的已經有了這個范式要求的概念,只是你并不知道這個概念叫做第一范式,
如果有的小伙伴說,這些資料都讓感到不適,那我就在這里夸上你一句,你很聰明,但是請你跟緊我的思路,我會一步一步的將資料落實到范式中!
表1顯然不遵循第一范式,那我們就把它修改一下,讓其遵循第一范式的要求,

將系名/系主任的列拆分成了兩個列系名和系主任后,很明顯改資料已經遵循的第一范式的要求,再來看看這張表2,聰明的你是不是第一眼又發現了問題呢?
存在的問題:
- 存在非常嚴重的資料冗余,姓名、系名、系主任
- 添加資料問題:當在資料表中添加一個新系和系主任時,比如:在資料表中添加高主任管理化學系,你會發現添加之后,在一個資料表中就會多出來了高主任和化學系,而這兩個資料并沒有對應哪個學生,顯然這時不合法的資料,
- 洗掉資料問題:如果Jack同學畢業多年了,我們資料表中沒有必要在留Jack相關的資料了,就會想到把Jack相關的洗掉掉,當你在表2的表結構中洗掉了Jack相關資料,你會發現整個劉主任和管理系以及會計和酒店管理都消失了,難道資料表中沒有這些資料就證明這個學校沒有它們嗎?顯然這更加離譜了!
了解了只遵循第一范式帶來的麻煩,我們就需要去看一下第二范式是怎么定義的,是否能解決第一范式留下來的問題!
3.2 第二范式(2NF)
第二范式在1NF的基礎上,非屬性碼的屬性必須完全依賴于主碼,(在1NF基礎上消除非屬性碼的屬性對主碼的部分函式依賴)
看到第二范式的概念,現在你應該是一個不懂的狀態,那讓我帶你了解幾個概念吧,這樣你就會懂了!
函式依賴(完全、部分、傳遞)
函式依賴: A - > B,如果通過A屬性(或屬性組)的值可以確定唯一B屬性的值,則可以成為B依賴于A(- >符號是確定關系),例如:可以通過學號來確定姓名,可以通過學號和課程來確定該課程的分數等等
- 完全函式依賴: A - > B,如果A是一個屬性組,則B屬性的確定需要依賴A屬性組中的所有屬性值,例如:分數的確定需要依賴于學號和課程,而學號和課程可以稱為一個屬性組,如果有學號沒有課程,我們只知道是誰的分數,而不知道是那一學科的分數,如果有課程沒有學號,那我們只知道是哪一個學科的分數,而不知道是誰的分數,所以該屬性組的兩個值是必不可少的,這就是完全函式依賴,
- 部分函式依賴: A - > B,如果A是一個屬性組,則B屬性的確定需要依賴A屬性組中的部分屬性值,例如:如果一個屬性組中有兩個屬性值,它們分別是學號和課程名稱,那姓名的確定只依賴這個屬性組中的學號,于課程名稱無關,簡單來說,依賴于屬性組的中部分成員即可成為部分函式依賴,
- 傳遞函式依賴: A - > B - > C,傳遞函式依賴就是一個依賴的傳遞關系,通過確定A來確定B,確定了B之后,也就可以確定C,三者的依賴關系就是C依賴于B,B依賴于A,例如:我們可以通過學號來確定這位學生所在的系部,再通過系部來確定系主任是誰,而這個三者的依賴關系就是一種傳遞函式依賴,
候選碼、主屬性碼與非屬性碼
- 碼: 如果在一張表中,一個屬性或屬性組,被其他所有屬性所完全函式依賴 ,則稱這個屬性(或屬性組)為該表的候選碼,簡稱碼,然而碼又分為主屬性碼和非屬性碼,例如:分數的確定沒有學號和課程是不行的,所以分數完全函式依賴于課程和學號,
- 主屬性碼: 主屬性碼也叫主碼,即在所有候選碼挑選一個做主碼,這里相當于是主鍵,例如:分數完全函式依賴于課程和學號,該碼屬性組中的值就有課程、學號和分數,所以我們要在三個候選碼中,挑選一個做主碼,那就可以挑選學號,
- 非屬性碼: 除主碼屬性組以外的屬性,叫做非屬性碼,例如:在分數完全函式依賴于課程和學號時,其中學號已經讓我們選為主碼,那么我們就可以確定,除了學號以外的屬性值,其他的屬性值都是非屬性碼,也就是說在這個完全函式依賴關系中,課程和分數是非屬性碼,
當我們了解這些概念后,回過頭來再看2NF的概念:在1NF的基礎上,非屬性碼的屬性必須完全依賴于主碼(在1NF基礎上消除非屬性碼的屬性對主碼的部分函式依賴)
我們還使用分數完全函式依賴于學號和課程這個函式依賴關系,此關系中非屬性碼為:課程和分數,主碼為學號,梳理清楚關系后,遵循在1NF基礎上,非屬性碼的屬性必須完全依賴于主碼的第二范式,就需要繼續修改表結構了,遵循1NF和2NF的表結構如下:


正如你所看到的,我們把表2根據1NF和2NF拆分成了表3和表4,這時候你再看表3,表3中的分數就完全函式依賴于表3中的學號和課程,表4中也挑選學號做主碼,雖然解決了資料冗余問題,但是僅僅這樣還是不夠的,上述問題中其他的兩個問題并沒有得到解決!
存在的問題:
- 資料洗掉問題
- 資料添加問題
注意: 在第二范式中存在的這兩個問題,就是在第一范式中存在問題的其中兩個并沒有得到解決,
既然第一范式和第二范式都沒有解決這兩個問題,那第三范式幫你解決!
3.3 第三范式(3NF)
第三范式在2NF基礎上,消除傳遞依賴,
說到傳遞依賴,那我們的資料表中還有哪些傳遞依賴呢?這時候你會發現表4中含有傳遞依賴的,表4中的傳遞依賴關系為:姓名 - > 系名 - > 系主任,該傳遞依賴關系為系主任傳遞依賴于姓名,再根據此傳遞依賴關系分析我們添加和洗掉問題就漏洞百出了,消除傳遞依賴的辦法還是將表4進行拆分,拆分后的表結構如下:


當我們把表4拆分成表5和表6時,你再來分析添加和洗掉問題就會有不一樣的結果,假設在資料表中添加高主任管理的化學系時,該資料只會添加到表6中,不會發生傳遞依賴而影響其他資料,那假設Jack同學畢業了,要將Jack同學的相關資料從表中洗掉,這時我們需要洗掉表6中的學號3資料和表3中的學號3資料即可,它們也沒有傳遞依賴關系,同樣不會影響到其他資料,
四、范式的表設計
在這里我詳細講解了資料庫的三大范式,為什么一般我們只研究三大范式而不去延申至六大范式呢?在上面資料庫范式概念的時候,我也有講過,這里我還需要強調一下!
資料庫六大范式,一級比一級要求得嚴格,各種范式呈遞次規范,越高的范式資料庫冗余越小,范式即是對資料庫表設計的約束,約束越多,表設計就越復雜,表資料過于復雜,對于我們后期對資料庫表的維護以及擴展、洗掉、備份等種種操作帶來了一定的難度,所以,在實際開發中我們只需要遵循資料庫前面的三大范式即可,不需要額外延申擴展,
注意: 在剖析三大范式的時候,最終版本的表結構就是表3 + 表5 + 表6,我需要在這里說明一個問題,其實這樣設計表是可以的,但并不是很合理,因為我們在建表的時候是有主鍵和外鍵約束的,這三張表中,第一列的表默認為主鍵,其中主鍵為學號還可以接收,如果主鍵為系名那就占用的空間變大了,在表的級聯查詢中會損耗性能,所以,一般我們在設計表的時候,是需要主外鍵約束的,而其主外鍵基本是都是占用內容空間很小的數字,當你的表結構和需求滿足主鍵遞增時,則可以通過設定auto_increment引數來完成!
這里如果不了解MySQL主外鍵約束的小伙伴,可以參考此文章MySQL基礎來查補缺漏知識點,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/29435.html
標籤:MySQL
上一篇:Mysql 多欄位去重 【轉】
下一篇:MySQL事務處理
