第三正規化 (3NF) 就是讓我們的資料更有秩序的一步。簡單說,一個 table 要在 3NF,得符合:
- 它已經在 第二正規化 (2NF)。
- 所有非主鍵屬性 只依賴主鍵,不能依賴其他東西(不能有傳遞依賴!)。
換句話說,3NF 要求 table 裡的所有資料都要直接跟主鍵有關,不能依賴其他非主鍵屬性。
傳遞依賴就是,屬性 A 依賴屬性 B,B 又依賴屬性 C,這樣就有一條依賴鏈 A → B → C。舉例來說,「員工」依賴「部門」,「部門」又依賴「位置」。所以「員工」就傳遞依賴「位置」。
3NF 違規範例
假設我們有個 employees table,裡面存員工資料:
| employee_id | name | department | department_manager |
|---|---|---|---|
| 1 | Otto Lin | Marketing | Leo Zhang |
| 2 | Alex Song | Finance | Maria Chi |
| 3 | Anna Ming | Finance | Maria Chi |
這裡:
employee_id— 主鍵。department跟department_manager— 非主鍵屬性。
乍看之下沒問題,但仔細看會發現:department_manager 不是依賴 employee_id,而是依賴 department。這樣就有傳遞依賴:employee_id → department → department_manager。
可能遇到的問題
如果我們要改部門經理(像「Finance」),就得更新所有有這個部門的 row。如果不小心漏掉一個,資料就不一致了。這種麻煩完全可以避免。
讓 table 達到 3NF
為了消除傳遞依賴,我們把 table 拆成兩個:一個存員工資料,一個存部門資料。
employees table
| employee_id | name | department |
|---|---|---|
| 1 | Otto Lin | 行銷 |
| 2 | Alex Song | 財務 |
| 3 | Anna Ming | 財務 |
departments table
| department | department_manager |
|---|---|
| 行銷 | Leo Zhang |
| 財務 | Maria Chi |
現在一切都很有條理,每個 table 各司其職:
employeestable 存員工資料。departmentstable 存部門跟經理資料。
如果部門經理換人,只要改 departments table 的一行,不用改所有員工的資料。
怎麼判斷 table 違反 3NF?
要判斷 table 有沒有違反 3NF,可以檢查:
- table 裡有沒有傳遞依賴?像屬性 A 依賴 B,B 又依賴 C。
- 所有非主鍵屬性是不是都直接依賴主鍵?如果有東西依賴其他非主鍵屬性,那就不是 3NF。
實戰範例:商店
來看一個 sales table,裡面有銷售資料:
| sale_id | product_name | product_price | customer_name |
|---|---|---|---|
| 1 | 手機 | 20 000 | Otto Lin |
| 2 | 筆電 | 50 000 | Alex Song |
| 3 | 手機 | 20 000 | Anna Ming |
這裡很明顯有重複:商品價格資訊每次銷售都重複。如果價格變了,資料馬上就不一致。
為了消除 3NF 違規,我們把 table 拆成兩個:
salestable 存銷售資料。productstable 存商品跟價格。
sales table
| sale_id | product_id | customer_name |
|---|---|---|
| 1 | 1 | Otto Lin |
| 2 | 2 | Alex Song |
| 3 | 1 | Anna Ming |
products table
| product_id | product_name | product_price |
|---|---|---|
| 1 | 手機 | 20 000 |
| 2 | 筆電 | 50 000 |
現在如果商品價格變了,只要改 products table 的一行,資料就還是很一致。
實作練習
來個小挑戰:你有個 students_courses table,長這樣:
| student_id | student_name | course_name | teacher_name |
|---|---|---|---|
| 1 | Otto Lin | 數學 | Maria Chi |
| 2 | Alex Song | 程式設計 | Leo Zhang |
| 1 | Otto Lin | 程式設計 | Leo Zhang |
請把這個 table 拆成符合 3NF。提示:你需要建立三個 table(students、courses、teachers),然後正確連結它們。
為什麼要遵守 3NF?
為什麼要在意第三正規化 (3NF)?因為它真的讓人生簡單很多。table 達到 3NF,資料就很乾淨——沒有多餘重複,也比較不會出錯。更新資料也快又簡單,因為東西只存一份,不用到處複製貼上。
而且資料庫結構也更彈性。想加新欄位或改舊的,不用大改整個系統。
不過就像所有好故事一樣,有個小提醒:太過頭的正規化會讓 table 變超多,查詢時 JOIN 一堆,有時真的會慢。所以重點是拿捏好。該正規化就正規化,該留點重複也不用怕。
接下來我們會更深入:學怎麼正確建立 table 關聯,打造又方便又可靠的資料庫。衝吧,做出超棒的資料庫設計!
GO TO FULL VERSION