真實世界資料及資料庫正規化的應用

Brian Liao
Begonia Design 海棠設計
7 min readApr 26, 2019

隨著WEB&APP的蓬勃發展,分離式架構的盛行,這讓前後端分離設計開發的比重逐漸提高,整合的難度隨之增加。

不論前端是WEB或是APP都脫離不了資料的存取模式,既然跟資料存取有關,就一定會討論到資料庫的應用,初期的資料庫規劃及設計可以說是一切的根本,如果資料庫的設計不當,程式在對資料庫進行各項操作時就會顯得效能低落。

再進一步說明前,有幾個基本的概念需要先了解。首先我們需要知道何謂實體(Entity),在真實世界中舉凡任何存在的東西都是實體(Entity),例如在電商平台中的會員資訊,商品資訊,廠商資訊等等,都是可以拿來當作實體看待的。當有了這些實體之後,我們將這些實體的特性轉換成資料庫中具備結構化的資料,這個動作稱之為資料塑模(Data Modeling)。

實體一旦經過資料塑模後,便可以擁有屬性(Attributes)和關聯性(Relationships)。屬性每一種實體都會有的特性,例如:商品擁有名稱、價格、型號、尺寸等。關聯性指的是兩種以上的實體之間的關係,大致上有一對(1:1),一對多(1:N),多對多(M:N)。

1. 主鍵(Primary Key,PK)的重要性

資料庫關聯式模型最重要的一點就是確保所有的資料表都擁有主鍵(Primary Key,PK),因此每個資料表都應該擁有一或多個欄位作為主鍵。而資料表主鍵的內容必須獨一無二且不能為空值(Null)。當資料表沒有主鍵最直接影響的部分,就是無法確保在查詢資料的時候只有零或一個列相符,雖然在建構資料表的時候沒有建立主鍵是合法的。然而資料表缺少主鍵卻是會產生各種問題,包括資料表會擁有重複與不一致的資料、每個查詢需要花較多的時間、資料表會包含錯誤的資訊內容等。從以上的敘述可以知道,資料表最重要的就是必須擁有主鍵,那好的主鍵必須擁有那些特徵呢?
首先它必須具備下列幾個特點。

1.儲存獨特的值。
2.不能為空值。
3.穩定且不能改變的值。
4.盡可能簡單

在業界中常見的關聯式資料庫管理系統(RDBMS)常用來產生主鍵(Primary Key)的方法,整理如下表。

2. 現實世界中的資料是紊亂的?淺談資料庫正規化(Normalization)

對於經常在處理資料庫的工程師來說,資料庫正規化(Normalization)是基本的功夫,雖說如此,在業界待久了還是會遇到許多"有趣的"設計。

現實世界中的資料通常具備幾個特點,龐大、紊亂是必備的條件,否則它不夠格稱為真實的資料。但這真實的資料是可以經由正規化(Normalization)的調整,使其成為可以使用的資料來源,最主要的目的就是將資料中的重覆欄位降到最低、提高關聯性資料庫的效能。

資料庫在正規化時會有一些規則,並且每條規則都稱為「正規形式」。
如果符合第一條規則,則資料庫就稱為「第一正規化形式(1NF)」。
如果符合前二條規則,則資料庫就被視為屬於「第二正規化形式(2NF)」。

雖然資料庫的正規化最多可以進行到第五正規化形式,但是在實務上,BCNF被視為大部分應用程式所需的最高階正規形式。

在資料表正規化的過程 (1NF 到 BCNF) 中, 每一個階段都是以欄位的「相依性」, 做為分割資料表的依據之一。

完整的正規化步驟

3. 了解這麼多的理論後,不如自己來動手做做看,先從第一正規化做起

舉例一個EC平台的銷售訂單原始資料表,如下所示

表3-1

我們經常從客戶手上拿到類似的資料內容,它不滿足資料庫對於資料表的要求,但是它卻滿足使用者在使用上的要求。
如果按照先前的正規化型式來看,上述的資料內容首先要做的是,找出此資料表中重複的資料。從左到右逐一欄位檢查,我們可以很容易的發現(產品代號、訂購數量、產品名稱、單價、庫存量)屬於重複的資料。我們可以將表3–1做個轉換改成表3–2的方式呈現,並且滿足下列第一階正規化1NF的規則
a. 每一個欄位只能有一個基元值(Atomic)即單一值。
b. 沒有任何兩筆以上的資料是完全重覆。
c. 資料表中有主鍵,而其他所有的欄位都相依於「主鍵」。

轉換後的結果

表1-2

或許有的人會認為上述的資料表型態已滿足1NF的規則,似乎就可以產生在資料庫中了。或許有人會問,這樣的資料表如果產生在資料庫中,會產生怎樣的後遺症呢?可以分三個層面來探討。

a. 新增異常檢查(Insert Anomaly)

無法新增產品資料,如產品代號、產品名稱、單價等。必須要等有訂單成立後才可以新增,主要的原因是,以上的新增動作違反了「實體完整性規則」,因為主鍵「訂單序號」或複合主鍵不可以為空值NULL。

b. 修改異常檢查(Update Anomaly)

產品「全涵氧日拋」重複多次,因此當需要修改「全涵氧日拋」的價格時,有些紀錄未修改到,造成資料不一致的現象。例如有買「全涵氧日拋」的客戶不論購買數量,均減少50元,這樣會導致有些客戶沒有減少、有些客戶減少,導致資料不一致的情況。

c. 刪除異常檢查(Delete Anomaly)

當刪除#3訂單編號時,也會同時刪除產品TC003及其相關的資料。綜合上面的三種異常現象,我們必須進行第二階正規化2NF的規則

4. 進入更嚴謹的第二階正規化規則2NF

檢查是否存在部分功能相依。我們可以依據相依的欄位來進行分割資料表的動作。
訂單_客戶 (訂單編號,訂貨日期,送貨日期,客戶代號,客戶名稱,客戶地址)

表4-1(訂單_客戶)滿足2NF

訂單_產品 (訂單編號,產品代號,訂購數量,產品名稱,單價,庫存量)
完全功能相依的有(訂單編號,產品序號)→訂購數量
部分功能相依的有(產品代號→產品名稱、單價、庫存量)

表4-2(訂單_產品)

由於(訂單_產品)的資料表內容具備部分功能相依,因此我們可以再把(訂單_產品)拆成兩個資料表(訂單明細)及(產品)

表4-3(訂單明細)滿足3NF
表4-4(產品)滿足3NF

5. 進入第三階正規化規則3NF

再回頭看(訂單_客戶)資料表,我們可以發現有一個功能相依性會造成遞移相依性。
客戶代號→客戶名稱,客戶地址。
因此可以將(訂單_客戶)資料表拆成(訂單)及(客戶)兩個資料表
訂單 (訂單編號,訂貨日期,送貨日期,客戶代號)

表5-1(訂單)

客戶 (客戶代號,客戶名稱,客戶地址)

表5-2(客戶)

最後經過1NF到3NF後可以得到訂單明細、產品、訂單、客戶四個資料表。也就完成了初步的資料正規化的步驟。

--

--