如何深入理解關系型數據庫的三大范式


該文章,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表格模擬數據庫中的表,並在表中填入了一些數據。如下:

image-20200613164428707
image-20200613164428707

當你看到這些數據的時候,是否有些數據讓你感到不適?我的答案,是的。當我看到系名/系主任這一列數據的時候感覺這並不合符我們數據庫的設計理念,因為它完全可以拆分為兩個列的。其實每一個人的思想中的已經有了這個范式要求的概念,只是你並不知道這個概念叫做第一范式。

如果有的小伙伴說,這些數據都讓感到不適,那我就在這里誇上你一句,你很聰明。但是請你跟緊我的思路,我會一步一步的將數據落實到范式中!

表1顯然不遵循第一范式,那我們就把它修改一下,讓其遵循第一范式的要求。

image-20200613164455095
image-20200613164455095

系名/系主任的列拆分成了兩個列系名系主任后,很明顯改數據已經遵循的第一范式的要求。再來看看這張表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的表結構如下:

image-20200613170300513
image-20200613170300513
image-20200613170326468
image-20200613170326468

正如你所看到的,我們把表2根據1NF和2NF拆分成了表3和表4。這時候你再看表3,表3中的分數就完全函數依賴於表3中的學號和課程。表4中也挑選學號做主碼。雖然解決了數據冗余問題,但是僅僅這樣還是不夠的,上述問題中其他的兩個問題並沒有得到解決!

存在的問題:

  • 數據刪除問題
  • 數據添加問題

注意: 在第二范式中存在的這兩個問題,就是在第一范式中存在問題的其中兩個並沒有得到解決。

既然第一范式和第二范式都沒有解決這兩個問題,那第三范式幫你解決!

3.3 第三范式(3NF)

第三范式在2NF基礎上,消除傳遞依賴。

說到傳遞依賴,那我們的數據表中還有哪些傳遞依賴呢?這時候你會發現表4中含有傳遞依賴的。表4中的傳遞依賴關系為:姓名 - > 系名 - > 系主任。該傳遞依賴關系為系主任傳遞依賴於姓名。再根據此傳遞依賴關系分析我們添加和刪除問題就漏洞百出了。消除傳遞依賴的辦法還是將表4進行拆分。拆分后的表結構如下:

image-20200613172237233
image-20200613172237233
image-20200613172303711
image-20200613172303711

當我們把表4拆分成表5和表6時,你再來分析添加和刪除問題就會有不一樣的結果。假設在數據表中添加高主任管理的化學系時,該數據只會添加到表6中,不會發生傳遞依賴而影響其他數據。那假設Jack同學畢業了,要將Jack同學的相關數據從表中刪除,這時我們需要刪除表6中的學號3數據和表3中的學號3數據即可,它們也沒有傳遞依賴關系,同樣不會影響到其他數據。

四、范式的表設計

在這里我詳細講解了數據庫的三大范式,為什么一般我們只研究三大范式而不去延申至六大范式呢?在上面數據庫范式概念的時候,我也有講過。這里我還需要強調一下!

數據庫六大范式,一級比一級要求得嚴格。各種范式呈遞次規范,越高的范式數據庫冗余越小。范式即是對數據庫表設計的約束,約束越多,表設計就越復雜。表數據過於復雜,對於我們后期對數據庫表的維護以及擴展、刪除、備份等種種操作帶來了一定的難度。所以,在實際開發中我們只需要遵循數據庫前面的三大范式即可,不需要額外延申擴展。

注意: 在剖析三大范式的時候,最終版本的表結構就是表3 + 表5 + 表6。我需要在這里說明一個問題,其實這樣設計表是可以的,但並不是很合理。因為我們在建表的時候是有主鍵和外鍵約束的。這三張表中,第一列的表默認為主鍵,其中主鍵為學號還可以接收,如果主鍵為系名那就占用的空間變大了。在表的級聯查詢中會損耗性能。所以,一般我們在設計表的時候,是需要主外鍵約束的,而其主外鍵基本是都是占用內容空間很小的數字。當你的表結構和需求滿足主鍵遞增時,則可以通過設置auto_increment參數來完成!

這里如果不了解MySQL主外鍵約束的小伙伴,可以參考此文章MySQL基礎來查補缺漏知識點。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM