該文章,GitHub已收錄,歡迎老闆們前來Star!git
GitHub地址: https://github.com/Ziphtracks/JavaLearningmanualgithub
設計關係數據庫時,聽從不一樣的規範要求,設計出合理的關係型數據庫,這些不一樣的規範要求被稱爲不一樣的範式,各類範式呈遞次規範,越高的範式數據庫冗餘越小。數據庫
範式來自英文Normal form,簡稱NF。要想設計—個好的關係,必須使關係知足必定的約束條件,此約束已經造成了規範,分紅幾個等級,一級比一級要求得嚴格。知足這些規範的數據庫是簡潔的、結構明晰的,同時,不會發生插入(insert)、刪除(delete)和更新(update)操做異常。app
目前關係數據庫有六種範式:第一範式(1NF)、第二範式(2NF)、第三範式(3NF)、巴斯-科德範式(BCNF)、第四範式(4NF)和第五範式(5NF,又稱完美範式)。知足最低要求的範式是第一範式(1NF)。在第一範式的基礎上進一步知足更多規範要求的稱爲第二範式(2NF),其他範式以次類推。通常來講,數據庫只需知足第三範式(3NF)就好了。函數
第一範式強調每一列都是不可分割的原子數據項。 性能
說到原子
這個詞,確定有小夥伴就先到了原子性問題,其實這麼想也是沒有錯的。那就讓我帶大家去剖析一下第一範式。spa
首先,我用Excel表格模擬數據庫中的表,並在表中填入了一些數據。以下:設計
當你看到這些數據的時候,是否有些數據讓你感到不適?個人答案,是的。當我看到系名/系主任
這一列數據的時候感受這並不合符咱們數據庫的設計理念,由於它徹底能夠拆分爲兩個列的。其實每個人的思想中的已經有了這個範式要求的概念,只是你並不知道這個概念叫作第一範式。code
若是有的小夥伴說,這些數據都讓感到不適,那我就在這裏誇上你一句,你很聰明。可是請你跟緊個人思路,我會一步一步的將數據落實到範式中!orm
表1顯然不遵循第一範式,那咱們就把它修改一下,讓其遵循第一範式的要求。
將系名/系主任
的列拆分紅了兩個列系名
和系主任
後,很明顯改數據已經遵循的第一範式的要求。再來看看這張表2,聰明的你是否是第一眼又發現了問題呢?
存在的問題:
- 存在很是嚴重的數據冗餘,姓名、系名、系主任
- 添加數據問題:當在數據表中添加一個新系和系主任時,好比:在數據表中添加高主任管理化學系。你會發現添加以後,在一個數據表中就會多出來了高主任和化學系,而這兩個數據並無對應哪一個學生,顯然這時不合法的數據。
- 刪除數據問題:若是Jack同窗畢業多年了,咱們數據表中沒有必要在留Jack相關的數據了,就會想到把Jack相關的刪除掉。當你在表2的表結構中刪除了Jack相關數據,你會發現整個劉主任和管理系以及會計和酒店管理都消失了,難道數據表中沒有這些數據就證實這個學校沒有它們嗎?顯然這更加離譜了!
瞭解了只遵循第一範式帶來的麻煩,咱們就須要去看一下第二範式是怎麼定義的,是否能解決第一範式留下來的問題!
第二範式在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中也挑選學號作主碼。雖然解決了數據冗餘問題,可是僅僅這樣仍是不夠的,上述問題中其餘的兩個問題並無獲得解決!
存在的問題:
- 數據刪除問題
- 數據添加問題
注意: 在第二範式中存在的這兩個問題,就是在第一範式中存在問題的其中兩個並無獲得解決。
既然第一範式和第二範式都沒有解決這兩個問題,那第三範式幫你解決!
第三範式在2NF基礎上,消除傳遞依賴。
說到傳遞依賴,那咱們的數據表中還有哪些傳遞依賴呢?這時候你會發現表4中含有傳遞依賴的。表4中的傳遞依賴關係爲:姓名 - > 系名 - > 系主任。該傳遞依賴關係爲系主任傳遞依賴於姓名。再根據此傳遞依賴關係分析咱們添加和刪除問題就漏洞百出了。消除傳遞依賴的辦法仍是將表4進行拆分。拆分後的表結構以下:
當咱們把表4拆分紅表5和表6時,你再來分析添加和刪除問題就會有不同的結果。假設在數據表中添加高主任管理的化學系時,該數據只會添加到表6中,不會發生傳遞依賴而影響其餘數據。那假設Jack同窗畢業了,要將Jack同窗的相關數據從表中刪除,這時咱們須要刪除表6中的學號3數據和表3中的學號3數據便可,它們也沒有傳遞依賴關係,一樣不會影響到其餘數據。
在這裏我詳細講解了數據庫的三大範式,爲何通常咱們只研究三大範式而不去延申至六大範式呢?在上面數據庫範式概念的時候,我也有講過。這裏我還須要強調一下!
數據庫六大範式,一級比一級要求得嚴格。各類範式呈遞次規範,越高的範式數據庫冗餘越小。範式便是對數據庫表設計的約束,約束越多,表設計就越複雜。表數據過於複雜,對於咱們後期對數據庫表的維護以及擴展、刪除、備份等種種操做帶來了必定的難度。因此,在實際開發中咱們只須要遵循數據庫前面的三大範式便可,不須要額外延申擴展。
注意: 在剖析三大範式的時候,最終版本的表結構就是表3 + 表5 + 表6
。我須要在這裏說明一個問題,其實這樣設計表是能夠的,但並非很合理。由於咱們在建表的時候是有主鍵和外鍵約束的。這三張表中,第一列的表默認爲主鍵,其中主鍵爲學號還能夠接收,若是主鍵爲系名那就佔用的空間變大了。在表的級聯查詢中會損耗性能。因此,通常咱們在設計表的時候,是須要主外鍵約束的,而其主外鍵基本是都是佔用內容空間很小的數字。當你的表結構和需求知足主鍵遞增時,則能夠經過設置auto_increment
參數來完成!
這裏若是不瞭解MySQL主外鍵約束的小夥伴,能夠參考此文章MySQL基礎來查補缺漏知識點。