資料庫正規化基礎說明

本文為初學者解釋資料庫正規化術語。 對這些術語的基本理解在討論關聯式資料庫設計時非常有幫助。

正規化的描述

正規化是將資料組織在資料庫中的過程。 它包括建立資料表,並依照設計來保護資料並透過消除冗餘與不一致依賴使資料庫更具彈性的規則建立資料表間的關係。

冗餘資料會浪費磁碟空間並造成維護問題。 如果存在於多個地點的資料必須被更改,則必須在所有位置以完全相同的方式更改。 如果客戶地址變更只存放在客戶資料表中,且不存在資料庫其他位置,會更容易實作。

什麼是「不一致的依賴」? 使用者直覺上會在客戶資料表中查找特定客戶的地址,但要在該資料表中查找負責拜訪該客戶的員工薪資,可能就不太合理。 員工的薪資與員工相關或依賴於員工,因此應移至員工表。 不一致的相依關係會使資料難以存取,因為尋找資料的路徑可能遺失或損壞。

資料庫正規化有幾條規則。 每條規則稱為「正規形式」。若遵循第一條規則,資料庫稱為「第一正規形式」。若遵守前三條規則,資料庫被視為「第三正規形式」。雖然有其他正規化層次,但第三正規形被認為是大多數應用中所需的最高層級。

如同許多正式規則與規範,現實情境並不總是允許完全遵守。 一般來說,正規化需要額外的資料表,有些客戶會覺得這很繁瑣。 如果你決定違反前三條正規化規則之一,請確保你的應用程式能預見可能發生的問題,例如重複資料和不一致的相依關係。

以下描述包含範例。

第一個正規表單

  • 消除個別表格中重複的群組。
  • 為每組相關資料建立獨立的表格。
  • 用主鍵識別每組相關資料。

不要在單一資料表中用多個欄位來儲存相似的資料。 例如,為了追蹤一個可能來自兩個來源的庫存項目,庫存紀錄可能會包含供應商代碼1和供應商代碼2的欄位。

如果你新增第三個供應商會發生什麼事? 新增欄位不是解決方法;它需要程式和表格的修改,且無法順暢地容納動態數量的廠商。 相反地,將所有供應商資訊放在一個名為 Vendors 的獨立表格中,然後用商品編號鍵將庫存連結到供應商,或用供應商代碼鍵將供應商連結到庫存。

第二個正規表單

  • 為適用於多筆紀錄的值組建立獨立資料表。
  • 將這些表格與外鍵關聯起來。

記錄不應該依賴資料表主鍵以外的任何欄位(必要時可使用複合鍵)。 舉例來說,考慮會計系統中的客戶地址。 客戶資料表需要地址,訂單、出貨、發票、應收帳款和催收資料表也都需要。 與其將客戶地址分別存放在這些資料表中,不如集中存放在 Customers 資料表或獨立的 Addresses 資料表中。

第三個正規表單

  • 刪除不依賴金鑰的欄位。

記錄中不屬於該紀錄鍵的值不應該出現在表格中。 一般而言,當一組欄位的內容可能適用於表格中多於一個記錄時,請考慮將這些欄位放在獨立的資料表中。

例如,在員工招募表中,可能會包含候選人的大學名稱和地址。 但你需要完整的大學名單來進行團體郵寄。 如果大學資訊儲存在候選人表格中,就無法列出目前沒有候選人的大學。 建立一個獨立的大學資料表,並用大學代碼鍵連結到候選人資料表。

例外:遵循第三標準形雖然理論上可取,但並不總是實際可行。 如果你有一個客戶資料表,並且想消除所有可能的領域間依賴關係,你必須為城市、郵遞區號、銷售代表、客戶類別以及其他可能在多筆紀錄中重複的因素建立獨立的表格。 理論上,正規化是值得追求的。 然而,許多小型資料表可能會降低效能或超過開啟的檔案與記憶體容量。

可能更可行的是只對經常變動的資料套用第三正規形。 如果還有一些依賴欄位,請設計你的應用程式,要求使用者在更改任何相關欄位時必須驗證。

其他正規化形式

第四正規形,也稱為 Boyce-Codd 標準形(BCNF),以及第五正規形確實存在,但在實際設計中很少被考慮。 忽略這些規則可能會導致資料庫設計不完美,但不應該影響功能。

範例表的正規化

這些步驟示範了將虛構的學生資料表正規化的過程。

  1. 未正規化表格:

    學生# Advisor Adv-Room 第一組 第二級 第 3 類
    1022 瓊斯 412 101-07 143-01 159-02
    4123 史密斯 216 101-07 143-01 179-04
  2. 第一正規形:無重複群

    表格應該只有兩個維度。 由於一名學生有多個課程,這些課程應該在獨立表格中列出。 上述紀錄中的欄位 Class1、Class 2 和 Class3 顯示設計有問題。

    試算表常常使用第三維度,但表格不應該如此。 另一種看待這個問題的方式是,從一對多關係的角度來看,不要把「一」的一方和「多」的一方放在同一個資料表中。 相反地,透過消除重複群(Class#)來建立另一個第一正規形的表格,如下範例所示:

    學生# Advisor Adv-Room 類別#
    1022 瓊斯 412 101-07
    1022 瓊斯 412 143-01
    1022 瓊斯 412 159-02
    4123 史密斯 216 101-07
    4123 史密斯 216 143-01
    4123 史密斯 216 179-04
  3. 第二正規形式:消除冗餘資料

    請注意上表中每個 Student# 值的多個 Class# 值。 Class# 在功能上不依賴 Student#(主鍵),因此此關係並非第二正規形式。

    以下表格展示了第二正規形:

    學生:

    學生# Advisor Adv-Room
    1022 瓊斯 412
    4123 史密斯 216

    註冊:

    學生# 類別#
    1022 101-07
    1022 143-01
    1022 159-02
    4123 101-07
    4123 143-01
    4123 179-04
  4. 第三正規形式:消除不依賴鍵的資料

    在最後一個例子中,Adv-Room(顧問的辦公室號碼)在功能上依賴於顧問屬性。 解決方案是將該屬性從學生表移到教職員表,如下所示:

    學生:

    學生# Advisor
    1022 瓊斯
    4123 史密斯

    師資:

    名稱 房間 部門
    瓊斯 412 42
    史密斯 216 42