什麼是第三正規型(3NF)?

想像一下,你正在處理一個龐大、非結構化的資料庫,裡面充滿了重複、冗餘的資訊。每次更新或刪除都可能帶來潛在的災難,可能會引發錯誤和不一致性。第三正規化(3NF)是一種經過證實的資料庫規範化方法,可以避免這種混亂。實施3NF可以整理您的資料結構,確保其高效、有組織,並且沒有不必要的冗餘。

在本文中,我們將探討3NF的工作原理、價值所在,以及如何將其付諸實踐。我們還將比較3NF與其他形式,並了解何時應該使用每種形式。每個人都可以從更深入了解這些結構中受益,但如果您是一名資料庫設計師或數據科學家,這些知識尤其有價值,因為它可以顯著簡化您的工作並保持您的資料庫可靠。如果您對整個資料庫設計感興趣,請查看我們完整的資料庫設計課程。

第三正規化(3NF)定義

第三正規形是數據庫規範化的關鍵概念,它消除了不需要的依賴關係。第三正規形建立在第一正規形(1NF)和第二正規形(2NF)的基礎上,這意味著它繼承了它們的規則:1NF要求每個單元格中具有原子(不可分割)值,而2NF則去除了對複合主鍵的部分依賴。第三正規形進一步去除遞歸依賴關係,這種情況是指非關鍵屬性間接地依賴主鍵。

通過專注於這一點,第三正規形確保表中的每個非關鍵列直接與主鍵相關聯,與其他無關。更實際地說,第三正規形有助於最小化冗余,並在插入、更新或刪除數據時避免異常。

在1970年代,埃德加·科德(Edgar F. Codd)引入第三正規形,以明確規範實現完全規範化數據庫結構的條件。幾年後,卡洛·扎尼奧洛(Carlo Zaniolo)對其進行了重新制定,提供了更清晰的解釋,區分了“經典”第三正規形和更嚴格的Boyce-Codd正規形(BCNF)之間的區別。暫時不用過於擔心BCNF,我們稍後會再回來討論。

理解第三正規形的條件

那麼,實現第三正規化需要做些什麼?要使表符合條件,需要滿足一些條件:

  • 已經處於第二正規化(2NF):這意味著它已經是原子的,沒有重複的群組,並且沒有對任何複合鍵的部分依賴。

第三正規化(3NF)包括第二正規化(2NF)和第一正規化(1NF)。圖片由作者提供

  • 沒有遞移依賴性:這個規則很重要。在第三正規化的表中,任何非主鍵列必須僅依賴於主鍵,而不是通過另一個非關鍵列間接依賴。

讓我們看看這實際意味著什麼。

分解表以達到第3正規化

讓我們通過分解表的過程來達到第3正規化。我們將使用來自DataCamp課程的一些示例數據來說明每個步驟。

步驟1:識別遞移依賴

遞移依賴。這是需要拆分表的一個跡象。

看看下面的三个表。哪一个有传递依赖关系?

表 1:课程

Course ID Course Name Difficulty
201 SQL基础 初学者
202 Python入门 初学者
203 理解数据科学 中级

表 2:讲师

Instructor ID Instructor Name Expertise
1 Sarah Johnson 数据科学
2 Tom Williams 机器学习
3 Emily Brown Python

表3:注册人数

Enrollment ID Student Name Course ID Course Name
1001 Alice Smith 201 SQL基础
1002 Bob Green 202 Python入门
1003 Charlie Blue 201 SQL基础

答案是… 表3!

在這個表中,課程名稱取決於課程編號,但並不直接取決於註冊編號(主鍵)。這種間接依賴使得課程名稱成為一個遞移性依賴。

步驟 2:將數據分離成新表

為了處理傳遞依賴性,我們將表 1 拆分為兩個表。每個表將專注於直接相關的數據。

修訂後的註冊表

Enrollment ID Student Name Course ID
1001 Alice Smith 201
1002 Bob Green 202
1003 Charlie Blue 201

課程表

Course ID Course Name
201 SQL 基礎知識
202 Python 入門

現在,每個表格僅包含直接依賴於其主鍵的信息:課程編號現在是課程名稱課程表中的主鍵,而註冊編號註冊表中的主鍵。

通過這種分解,這些表現在符合第三范式的要求,消除了冗余,確保每個表只存儲直接相關的信息。

如果您想動手創建自己的數據庫,可以查看我們的創建PostgreSQL數據庫課程。如果您有一些進階知識,可以嘗試在Snowflake中進行數據建模入門,其中涵蓋了實體關係和維度建模等想法。

使用第三范式的好處和限制

那麼,為什麼要付出這一切努力達到第三范式呢?以下是主要好處:

  • 提高資料完整性:通過消除遞移依賴性,3NF有助於確保更新和刪除不會導致跨表格的衝突或過時資料。
  • 減少冗余:減少冗余意味著您的資料庫更容易維護,並且減少了存儲使用。
  • 更簡單的資料維護:將相似資訊保存在專用表格中使得更新記錄更容易,無需追蹤冗余項目。

雖然3NF結構支持數據準確性,但有時也可能導致數據更為分割,有時由於額外的表聯接使得複雜查詢變慢。在需要速度超過規範化需求的情況下,BCNF或4NF可能是更實際的選擇。

比較:第一、第二、第三和BC范式

讓我們來看看形式上的區別。

比較表格:第一、第二和第三正規形式

這是一個比較表格,可以幫助您了解1NF、2NF和3NF的要求。

Feature 1NF 2NF 3NF
原子數據
沒有部分依賴
沒有傳遞性依賴

第三正規形式 vs. Boyce-Codd正規形式(BCNF)

BCNF是3NF的一种“更严格”的形式,进一步消除由于重叠候选键而产生的异常。在复杂情况下特别有用,3NF本身无法完全消除依赖关系时。当非主属性依赖于组合候选键的一部分时,BCNF适用。我知道这听起来很复杂,让我们通过一个例子来分解。

当前结构(在3NF中)

分解以实现3NF后,我们得到了这两个表:

Enrollments表

Enrollment ID Student Name Course ID
1001 Alice Smith 201
1002 Bob Green 202
1003 Charlie Blue 201

Courses表

Course ID Course Name
201 SQL基础
202 Python 簡介

在這個結構中,每個表都處於第三正規化,沒有推移依賴,並且數據被適當地歸一化。

引入一個新需求

現在,讓我們為Courses添加一個新屬性:Classroom,表示每門課程所在的教室。這個新屬性可能導致需要 BCNF。

更新後的課程表(3NF)

Course ID Course Name Classroom
201 SQL基礎 101教室
202 Python入門 102教室
203 理解資料科學 101教室

在這裡,課程編號仍然是主要的鍵,所有其他屬性都直接依賴於它。但是,假設有一個新規則,每個教室一次只能容納一個科目。我們還假設課程名稱SQL 基礎” 可以在不同的課程編號(例如 201、204 等)下提供,如果它們在不同的時間安排的話。在這種情況下,每次提供的”SQL 基礎“仍然會在”101教室”進行,無論具體的課程編號為何。因此,課程名稱也唯一確定了教室

這意味著我們現在有兩個候選鍵:

  1. 課程編號
  2. 課程名稱

有了這兩個候選鍵,我們現在面臨一個 3NF 無法解決的問題:教室依賴於課程名稱而不僅僅是課程 ID

應用 BCNF

為了解決這個依賴問題,我們需要進一步將 課程 表拆分為兩個獨立的表,以更好地符合BCNF:

  1. 一個新的課程表,只包括課程ID課程名稱
  2. 一個CourseDetails表,存儲課程名稱教室的關聯。

這是它的外觀:

修訂課程表(BCNF)

Course ID Course Name
201 SQL基礎
202 Python入門
203 理解數據科學

課程詳情表(BCNF)

Course Name Classroom
SQL基礎 101教室
Python入門 102教室
理解數據科學 101教室

有了這個新結構,每張表都滿足BCNF條件:

  • Courses 表中,課程ID 是主鍵,所有屬性都僅依賴於它。
  • CourseDetails表中,課程名稱是主鍵,教室只依賴於課程名稱

此設置可消除由重疊候選鍵引起的依賴性問題,確保嚴格規範化結構。

結論

第三正規化是數據庫設計師保持數據清潔、一致且不受問題依賴性影響的寶貴工具。憑藉第三正規化,數據完整性得到增強,使管理更加順暢並減少冗余。請記住,雖然第三正規化在大多數情況下運作良好,但對於更複雜的數據庫可能受益於額外的形式,如BCNF或4NF。

如果您認為本文有幫助,請考慮邁出下一步,獲取我們的SQL Associate 認證。這是驗證您的SQL和數據庫管理技能並向潛在雇主展示您專業知識的絕佳途徑!

Source:
https://www.datacamp.com/tutorial/third-normal-form