共用方式為


資料庫正規化基本概念的描述

本文說明初學者的資料庫正規化術語。 討論關係資料庫設計時,對於此術語的基本瞭解很有説明。

正規化的描述

正規化是組織資料庫資料的過程。 它包括建立數據表,並根據設計來保護數據的規則,建立這些數據表之間的關聯性,以及消除備援和不一致的相依性,讓資料庫更具彈性。

備援數據浪費磁碟空間,並造成維護問題。 如果存在於多個位置的數據必須變更,數據必須以完全相同的方式在所有位置變更。 如果數據只儲存在 Customers 數據表中,且資料庫中沒有其他地方,客戶地址變更會更容易實作。

什麼是「不一致的相依性」? 雖然使用者直覺上會在客戶資料表中查找特定客戶的地址,但在那裡找該客戶的員工的薪水可能就不合理了。 員工的薪資與員工相關或相依於員工,因此應該移至員工表。 不一致的相依性可能會使數據難以存取,因為尋找數據的路徑可能會遺失或中斷。

資料庫正規化有幾個規則。 每個規則稱為「一般形式」。如果觀察到第一個規則,則資料庫會以「第一個正常形式」表示。如果觀察到前三個規則,資料庫會被視為「第三個正常格式」。雖然其他正規化層級是可行的,但第三個正常形式會被視為大多數應用程式所需的最高層級。

與許多正式規則和規格一樣,真實世界案例不一定會允許完美的合規性。 一般而言,正規化需要額外的數據表,有些客戶會發現這很麻煩。 如果您決定違反正規化的前三個規則之一,請確定您的應用程式預期可能發生任何問題,例如備援數據和不一致的相依性。

下列描述包括範例。

第一個標準格式

  • 排除個別數據表中的重複群組。
  • 為每個相關數據集建立個別的數據表。
  • 使用主鍵識別每組相關數據。

請勿在單一數據表中使用多個字段來儲存類似的數據。 例如,若要追蹤可能來自兩個可能來源的清查專案,清查記錄可能包含 Vendor Code 1 和 Vendor Code 2 的欄位。

當您新增第三個廠商時,會發生什麼事? 新增欄位不是答案;它需要程式與數據表修改,且無法順暢地容納動態數目的廠商。 相反地,將所有供應商資訊放在名為「供應商」的獨立資料表中,然後透過商品編號鍵將庫存連接至供應商,或透過供應商代碼鍵將供應商連接至庫存。

第二個標準格式

  • 針對套用至多個記錄的值集建立個別的數據表。
  • 將這些數據表與外鍵建立關聯。

記錄不應相依於數據表主鍵以外的任何其他項目(必要時為複合主鍵)。 例如,請考慮會計系統中客戶的位址。 客戶表格需要地址,但訂單、運輸、發票、應收帳款和催收表格也需要地址。 不是將客戶的位址分別存儲在每個資料表中,而是統一存於一個位置,可以選擇存放在客戶資料表中或單獨的位址資料表中。

第三個標準格式

  • 移除不依賴於鍵的欄位。

不屬於該記錄索引鍵之記錄中的值不屬於數據表。 一般而言,每當一組字段的內容可以套用到數據表中的單一記錄以上時,請考慮將這些字段放在個別的數據表中。

例如,在員工招聘數據表中,可能會包含候選人的大學名稱和位址。 但您需要完整的大學清單才能進行群組郵件。 如果大學資訊儲存在 [考生] 數據表中,則無法列出沒有目前候選人的大學。 建立個別的 University 數據表,並將它連結到具有大學代碼索引鍵的 [候選] 數據表。

例外狀況:堅持第三個正常形式,雖然理論上是可取的,但並不總是實用的。 如果您有 Customers 數據表,而且想要消除所有可能的欄位相依性,則必須為城市、郵遞區區編碼、銷售代表、客戶類別,以及可能在多個記錄中複製的任何其他因素建立個別數據表。 理論上,正規化值得追求。 不過,許多小型數據表可能會降低效能,或超過開啟的檔案和記憶體容量。

只對經常變更的數據套用第三個一般格式可能更為可行。 如果保留某些相依欄位,請設計您的應用程式,要求使用者在變更任何欄位時驗證所有相關欄位。

其他正規化形式

第四個正常形式,也稱為 Boyce-Codd 正常形式(BCNF),第五個正常形式確實存在,但在實際設計中很少考慮。 忽略這些規則可能會導致資料庫設計不盡如人意,但不應該影響功能。

將範例數據表正規化

這些步驟示範正規化虛構學生數據表的程式。

  1. 未正規化的數據表:

    學生# 顧問 Adv-Room 類別1 第二類 第三班
    1022 鐘斯 412 101-07 143-01 159-02
    4123 史密斯 216 101-07 143-01 179-04
  2. 第一個一般形式:沒有重複群組

    數據表應該只有兩個維度。 由於一個學生有數個課程,因此這些課程應該會列在個別的數據表中。 上述記錄中的欄位 Class1、Class2 和 Class3 表示設計上的問題。

    電子表格通常會使用第三個維度,但數據表不應該使用。 另一種考慮這個問題的方法是從一對多的關係來看,不要將一方和多方放在同一個數據表中。 相反地,藉由排除重複群組 (Class#), 以第一個標準格式建立另一個數據表,如下列範例所示:

    學生# 顧問 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# (主鍵),因此此關聯性不屬於第二正規化形式。

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

    學生:

    學生# 顧問 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 的辦公室號碼)功能上相依於 Advisor 屬性。 解決方案是將該屬性從 Students 數據表移至 Faculty 數據表,如下所示:

    學生:

    學生# 顧問
    1022 鐘斯
    4123 史密斯

    教職員:

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