這個做法建議使用資料庫設計中的資料正規化(Normalization),來消除重複儲存的資料,同時能解決資料一致性問題以及避免插入、更新、刪除資料時發生異常。

這個做法所說的冗餘數據是一個資料表中同時存在一模一樣的資料,並不是指主鍵與外鍵這種必須建立同樣的數據來維持兩個表之間的關聯關係。

正規化最重要的目的就是最小化資料重複的可能性,例如一個客户 Tom 它在汽車銷售紀錄表中的有兩筆交易紀錄,其中關於 Tom 的基礎資料幾乎都相同, 但是在地址列中有些微差異,最糟糕的是我們並不知道到底哪個地址是真的,這個現象就是資料不一致。

另外因為汽車銷售紀錄表裡面包含了客戶資料,所以我們沒辦法略過客戶的資料不輸入,代表我們並不能只單獨新增新汽車的型號, 所以就只能再銷售成功的當下每次都客戶當成新客戶輸入,把汽車當成新汽車來輸入,這種設計方式的缺點也很明顯,就是同一個客戶買不同型號的汽車 那就會產生兩筆非常類似的資料,不僅浪費硬碟空間,又浪費資料輸入人員的時間,同時又很容易因為操作失誤產生錯誤的資料。

還有需要更新客戶資料的場合,如果有非常多重複的資料那就必須更新每一筆資料的內容,這樣會讓資料庫承受很大的壓力。

最後是刪除,因為資料表包含很多重複的資料,那在刪除的時候就很有可能刪除錯誤的資料,並且也可能把重要的資料刪除掉。


我們可以把汽車銷售紀錄表根據邏輯拆分成四個表。

  1. Customers: 用來保存客戶資訊
  2. Employees: 用來保存銷售人員資訊
  3. AutomobileModels: 用來保存汽車的型號
  4. SalesTransactions: 銷售紀錄表

改成這種設計後 SalesTransactions 就只需要透過外鍵的方式來關聯其它的表,就還是能達到跟原本設計相同的功能。

也可以額外建立資料庫視圖(view),來重現原本的設計,同時又能避免冗餘數據。

SELECT st.SalesID, c.CustFirstName, c.CustLastName, c.Address, c.City, c.Phone, 
    st.PurchaseDate, 
    m.ModelYear, m.Model,
    e.SalesPerson
FROM SalesTransactions st
INNER JOIN Customers c
ON c.CustomerID = st.CustomerID
INNER JOIN Employees e
ON e.EmployeeID = st.SalesPersonID
INNER JOIN AutomobileModels m
ON m.ModelID = st.ModelID;

Summary

  1. 使用正規化(normalization)的目標是消除重複數據,並且減少資料處理時的資源消耗。
  2. 使用正規化消除重複數據,就能避免文內提到的插入、更新、刪除等不正常的情況發生。
  3. 使用正規化消除重複數據,就能盡量減少資料不一致的情況發生。