資料庫正規化(Database Normalization)完整指南:新手必讀
更新日期: 2025 年 3 月 4 日
本文為 資料庫正規化 基本介紹系列文,第 1 篇:
- 資料庫正規化(Database Normalization)完整指南:新手必讀 👈進度
- 資料正規化完整指南:從 JSON 數據到結構化資料
- 從 JSON 到資料庫:使用 Django ORM 建構音樂活動管理系統
- Django Custom Command 匯入 JSON 資料指南
- Python datetime 格式化指南:從基礎到實戰解析
- 深入理解 Django 的 BASE_DIR
- Django update_or_create() 用法詳解
在設計關聯式資料庫時,資料的組織方式直接影響到查詢效能、資料一致性,以及維護的難易度。
如果沒有妥善規劃,可能會出現重複數據、異常更新,甚至導致資料不一致的情況。
為了避免這些問題,「資料庫正規化」(Database Normalization) 應運而生。
本篇文章將為新手詳細介紹資料庫正規化的概念、優勢、不同的正規化階段(范式),以及實際應用方式。
希望讀完後,你能夠理解正規化的目的,並應用於你的資料庫設計中。
什麼是資料庫正規化?
資料庫正規化是一種結構化設計方法,用來將資料表分解成更小、更具邏輯性的表格,以減少冗餘、避免異常(Anomalies),並提高資料一致性。
這個過程通常分為不同的階段(范式,Normal Forms, NF),每個階段都進一步優化資料表的結構。
舉個簡單的例子:
假設我們有一張「學生」資料表:
學生ID | 姓名 | 課程名稱 | 課程教師 |
---|---|---|---|
001 | 小明 | 資料庫設計 | 張老師 |
002 | 小華 | 資料庫設計 | 張老師 |
003 | 小美 | 網頁設計 | 王老師 |
這樣的設計存在問題,例如:
- 資料重複:同一位老師的名字被多次存儲。
- 更新異常:如果張老師改名,則所有相關記錄都必須更新。
- 刪除異常:如果某課程只有一位學生,刪除該學生時,課程資訊也會被刪除。
這些問題可以透過正規化來解決。
為什麼要進行正規化?
進行資料庫正規化有幾個主要目的:
- 減少資料冗餘(Redundancy)
- 避免相同資料被重複存儲,減少資料庫的儲存空間浪費。
- 消除異常(Anomalies)
- 插入異常(Insertion Anomaly):例如,要新增一門新課程但沒有學生,則無法插入課程資料。
- 更新異常(Update Anomaly):例如,修改教師名稱時,需修改多個記錄,容易導致資料不一致。
- 刪除異常(Deletion Anomaly):例如,若刪除某門課程的最後一位學生,該課程的資料可能會遺失。
- 提高資料一致性與完整性(Consistency & Integrity)
- 透過將資料拆分到不同的表,確保數據的正確性。
- 提高查詢效能
- 雖然正規化後可能需要更多的 JOIN 操作,但對於頻繁更新的系統,正規化能減少更新的負擔,提高效率。
資料庫正規化的不同階段(范式)
正規化通常被分為多個級別,每個級別稱為「范式」(Normal Form, NF)。
目前常見的范式有第一范式(1NF)、第二范式(2NF)、第三范式(3NF),還有進一步的BCNF、第四范式(4NF)與第五范式(5NF)。
以下是各個范式的詳細解釋:
第一范式(1NF)— 消除重複欄位
條件:
每個欄位只能存放一個值,不能存放一組值或多個資料。
例如,在「課程」欄位中,不能同時存放「資料庫設計、網頁設計」,而是要拆成兩筆獨立的記錄,每筆只包含一個課程名稱。
每一筆資料(每一行)都必須有一個能夠唯一識別它的「身份證明」,通常是「主鍵」(Primary Key)。
也就是說,不能有完全相同的記錄重複出現在表格中,而是要有一個獨特的識別碼(像是學生ID)來區分不同的資料。
示例(未滿足 1NF)
學生ID | 姓名 | 課程名稱 |
---|---|---|
001 | 小明 | 資料庫設計, 網頁設計 |
002 | 小華 | 資料庫設計 |
改正後(滿足 1NF)
學生ID | 姓名 | 課程名稱 |
---|---|---|
001 | 小明 | 資料庫設計 |
001 | 小明 | 網頁設計 |
002 | 小華 | 資料庫設計 |
這樣的設計確保每個欄位只存儲單一值。
第二范式(2NF)— 消除部分依賴
條件:
必須滿足 1NF
也就是說,資料表已經符合第一范式(1NF),每個欄位都只能存放單一值,不能有重複的欄位或一欄存多個值的情況。
表內所有非主鍵欄位,都必須完全依賴於主鍵,而不能只是部分依賴
這表示資料表中的每個欄位都應該完整地依賴於主鍵,不能只依賴其中的一部分。
如果一張表的主鍵是由多個欄位組成(複合主鍵),那麼表中的其他欄位不能只依賴其中一部分,而是要依賴整個主鍵。
示例(未滿足 2NF)
學生ID | 課程名稱 | 課程教師 |
---|---|---|
001 | 資料庫設計 | 張老師 |
002 | 資料庫設計 | 張老師 |
這張表的主鍵由「學生ID + 課程ID」組成,因為一個學生可以選修多門課,而一門課也可以有多個學生修課。
「課程名稱」這個欄位只依賴「課程ID」,並沒有依賴「學生ID」這部分,因此它是「部分依賴」,違反了 2NF。
改正後(滿足 2NF) 拆成兩張表:
- 學生表
學生ID | 課程名稱 |
---|---|
001 | 資料庫設計 |
002 | 資料庫設計 |
- 學校資訊表
課程名稱 | 課程教師 |
---|---|
資料庫設計 | 張老師 |
這樣的設計確保每個表中的非主鍵欄位完全依賴於主鍵。
第三范式(3NF)— 消除傳遞依賴
條件:
必須滿足 2NF
這表示資料表已經符合第二范式(2NF),也就是:
所有非主鍵欄位只能直接依賴主鍵,而不能透過其他非主鍵欄位間接依賴。
這表示資料表中的非主鍵欄位(例如學生的地址、學校名稱)應該直接由主鍵決定,而不能透過另一個非主鍵欄位來決定。
示例(未滿足 3NF)
學生ID | 學生姓名 | 學校名稱 |
---|---|---|
001 | 小明 | 台灣大學 |
002 | 小華 | 台灣大學 |
這裡,「學校名稱」並不是直接依賴「學生ID」,而是透過「學生姓名」間接依賴,因此違反 3NF。
改正後(滿足 3NF) 拆成兩張表:
- 學生表
學生ID | 學生姓名 |
---|---|
001 | 小明 |
002 | 小華 |
- 學校資訊表
學生姓名 | 學校名稱 |
---|---|
小明 | 台灣大學 |
小華 | 台灣大學 |
這樣就確保了所有非主鍵欄位都直接依賴於主鍵。
為什麼稱為「范式」?
「范式」這個詞來自於數學和科學領域,通常指的是一種標準化的模型或範例。
在資料庫領域,范式(Normal Form)表示資料表達結構的一種「規範化形式」,用來確保數據儲存的最佳方式。
具體來說,稱為「范式」的原因有以下幾點:
- 提供一種標準(Standardization)
- 正規化過程透過一系列規則(如 1NF, 2NF, 3NF…)來標準化資料表的設計,避免不必要的數據冗餘與異常。
- 來自數學的概念
- 關聯式資料庫的設計基礎源於數學中的「關係代數」,而「Normal Form」在數學中表示某種標準化的狀態,因此被引入資料庫設計中,稱為「范式」。
- 強調最佳實踐
- 資料庫范式是一種指導方針,讓開發者知道如何設計高效、可擴展的資料庫架構。
- 來自英文翻譯
- Normal Form 的「Normal」指的是「標準化」、「正規化」的概念,而「Form」指的是「形式、格式」。在中文裡,「范式」這個詞最接近「標準化的模式」,因此被用來翻譯 Normal Form。
范式的作用
不同的范式代表不同程度的資料庫正規化,每一級范式都比前一級更進一步地優化資料結構:
- 第一范式(1NF):消除重複欄位,使每個欄位只能存放「單一值」。
- 第二范式(2NF):消除部分依賴,確保所有非主鍵欄位完全依賴於主鍵。
- 第三范式(3NF):消除傳遞依賴,確保所有非主鍵欄位直接依賴主鍵,而非透過其他欄位間接依賴。
進一步還有 BCNF(Boyce-Codd Normal Form)、第四范式(4NF)、第五范式(5NF),這些較高級的范式在更複雜的情境下使用。
結論
資料庫正規化是一個重要的設計原則,能夠幫助我們降低資料冗餘、提升數據一致性、避免異常發生。
然而,在實務應用中,有時過度正規化可能會導致查詢效能下降,因此要根據實際需求適度進行正規化與反正規化的權衡。
希望這篇文章能幫助你理解正規化的概念與應用方式,讓你的資料庫設計更加高效且穩健!🚀