只要設計出來的資料庫能夠符合應用系統現在甚至未來的需求就是好的資料庫設計。但是要符合應用系統的需求說來簡單,要怎麼做卻是很多程式開發新手的心中的痛,常見的情況是在開發系統初期,因為忽略了或過度簡化了資料庫設計,一開始並不覺得哪裡有問題,在開發過程中不斷的為了需求新增資料庫物件,不斷的疊床架屋,到了中後期之後,發現有需求異動了,這時候回頭改才發現建構的資料結構亂如麻,改了一個地方,另一個功能卻爆炸了。因此為了避免這種窘狀的發生,最常見的作法就是繼續的疊床架屋上去,最後交到業主手上的就是一套可以使用但是卻難以維護、資料庫效能日漸低落的系統。
我認為需要的
知識
- 要設計資料庫當然要對資料庫、對DB Object 有一定的了解,知道每種Object的用途(可以參考Session 1 Database object)
- Table正規化
工具
- 實體關聯圖(Entity Relationship Diagram)
- 資料流程圖(Data Flow Diagram)
Table正規化
正規化(Normalization)一連串的步驟,用來修改Table減少重複資料以及資料不一致的情形,每進行了任一個步驟,資料庫的狀態就會處於特定的正規化狀態,關聯式資料庫(RDB)定義了下列幾種的正規化:
- 第一正規化(1 Normal form,1NF)
- 第二正規化(2NF)
- 第三正規化(3NF)
- BC正規化(Boyce-Codd NF)
- 第四正規化(4NF)
- 第五正規化(5NF)
正規化的使用並不是愈高愈好,因為正規化的層級愈高產生的關聯Table也就愈多,有可能造成查詢資料時的join次數過多使得查詢效率降低,因此正規化要做到怎樣程度,需要視自己的需求來決定,通常我們在做一般的Web Application,大多只需要做到2NF或3NF就夠了,因此再這裡我就不多作後面正規化的介紹。
第一正規化(1NF)
在介紹1NF之前,可以先檢查自己在使用Excel時編出來的表格長什麼樣子,因為我們公司有導入Libreoffice,我在User site常聽到Libreoffice calc不好用想換回Excel,問他是怎樣不好用,會回說都資料都加總不起來,看了他的資料表後,原來他的資料類似這樣
客戶 | 訂單日期 | 銷售明細 | 訂單金額 | 配件明細 | 訂單金額 | 總金額 | 業務員 |
陳春嬌 | 2016/2/3 | 衣服5件:500元/件 褲子2件:500元/件 大衣3件:500元/件 | 5000元 | 項鍊4個:100元/個 | 400元 | 5400元 | 王大同 |
李志明 | 2016/3/5 | 帽子5件:100元/件 衣服3件:500元/件 夾克7件:1000元/件 | 9000元 | 手鍊10個:100元/個 別針10個:100元/個 | 2000元 | 11000元 | 張曉明 |
一看差點暈倒,大嬸,你把試算表當成Word打,這不是Libreoffice的錯(Libreoffice表示:寶寶心裡委屈,但寶寶不說),老實說這種用法用開源免費的Libreoffice就夠了,用要收錢的Excel會讓Excel哭阿。回過頭來看,跟這個相關的第一正規化就是把只給人看的資料轉化成也能給電腦分析判斷的步驟,要符合第一正規化必須要滿足下列規則:
- 不能有重複的欄位
- 每個欄位都必須是資料的最小單元
- 每一筆資料都有自己的主鍵
符合第一正規化的規格
客戶ID | 客戶 | 訂單日期 | 產品ID | 銷售明細 | 數量 | 單位ID | 單位 | 單價 | 明細金額 | 總金額 | 業務員ID | 業務員 |
101 | 陳春嬌 | 2016/2/3 | 1 | 衣服 | 5 | 11 | 件 | 500 | 2500 | 5400 | 201 | 王大同 |
101 | 陳春嬌 | 2016/2/3 | 2 | 褲子 | 2 | 11 | 件 | 500 | 1000 | 5400 | 201 | 王大同 |
101 | 陳春嬌 | 2016/2/3 | 3 | 大衣 | 3 | 11 | 件 | 500 | 1500 | 5400 | 201 | 王大同 |
101 | 陳春嬌 | 2016/2/3 | 4 | 項鍊 | 4 | 12 | 個 | 100 | 400 | 5400 | 201 | 王大同 |
102 | 李志明 | 2016/3/5 | 5 | 帽子 | 5 | 11 | 件 | 100 | 500 | 11000 | 202 | 張曉明 |
102 | 李志明 | 2016/3/5 | 1 | 衣服 | 4 | 11 | 件 | 500 | 2000 | 11000 | 202 | 張曉明 |
102 | 李志明 | 2016/3/5 | 6 | 夾克 | 7 | 11 | 件 | 1000 | 7000 | 11000 | 202 | 張曉明 |
102 | 李志明 | 2016/3/5 | 7 | 手鍊 | 10 | 12 | 個 | 100 | 1000 | 11000 | 202 | 張曉明 |
102 | 李志明 | 2016/3/5 | 8 | 別針 | 10 | 12 | 個 | 100 | 1000 | 11000 | 202 | 張曉明 |
第二正規化(2NF)
要符合2NF要達到以下的條件:
- 要符合1NF
- 只有跟主題有關的資料才會被存放在同一個Table中,其他的資料必須放在另一個Table
- 這些不同表格之間的關係由Foreign Key來展示
所以已經1NF的表格在2NF時會變成下列的4個表,在拆分時必須要達到無損,也就是需要注意資料雖拆成數個,但是資料必須沒有遺失。
- 交易資料表
客戶ID | 訂單日期 | 產品ID | 數量 | 單位ID | 總金額 | 業務員ID | 業務員 |
101 | 2016/2/3 | 1 | 5 | 11 | 5400 | 201 | 王大同 |
101 | 2016/2/3 | 2 | 2 | 11 | 5400 | 201 | 王大同 |
101 | 2016/2/3 | 3 | 3 | 11 | 5400 | 201 | 王大同 |
101 | 2016/2/3 | 4 | 4 | 12 | 5400 | 201 | 王大同 |
102 | 2016/3/5 | 5 | 5 | 11 | 11000 | 202 | 張曉明 |
102 | 2016/3/5 | 1 | 4 | 11 | 11000 | 202 | 張曉明 |
102 | 2016/3/5 | 6 | 7 | 11 | 11000 | 202 | 張曉明 |
102 | 2016/3/5 | 7 | 10 | 12 | 11000 | 202 | 張曉明 |
102 | 2016/3/5 | 8 | 10 | 12 | 11000 | 202 | 張曉明 |
- 客戶資料表
ID | 客戶名稱 |
101 | 陳春嬌 |
102 | 李志明 |
- 產品資料表
ID | 產品名稱 | 單價 |
1 | 衣服 | 500 |
2 | 褲子 | 500 |
3 | 大衣 | 500 |
4 | 項鍊 | 100 |
5 | 帽子 | 100 |
6 | 夾克 | 1000 |
7 | 手鍊 | 100 |
8 | 別針 | 100 |
- 單位資料表
ID | 單位名稱 |
11 | 件 |
12 | 個 |
第三正規化(3NF)
要符合3NF要達到以下的條件:
- 要符合2NF
- 所有主題外的欄位都必須是用來描述主題本身的屬性,也就是說,所有其他欄位的值都是靠主題來決定。
除了交易資料表,其他的表都已經符合3NF,所以把交易資料表拆成兩個表來符合3NF
- 交易資料表
客戶ID | 訂單日期 | 產品ID | 數量 | 單位ID | 總金額 | 業務員ID |
101 | 2016/2/3 | 1 | 5 | 11 | 5400 | 201 |
101 | 2016/2/3 | 2 | 2 | 11 | 5400 | 201 |
101 | 2016/2/3 | 3 | 3 | 11 | 5400 | 201 |
101 | 2016/2/3 | 4 | 4 | 12 | 5400 | 201 |
102 | 2016/3/5 | 5 | 5 | 11 | 11000 | 202 |
102 | 2016/3/5 | 1 | 4 | 11 | 11000 | 202 |
102 | 2016/3/5 | 6 | 7 | 11 | 11000 | 202 |
102 | 2016/3/5 | 7 | 10 | 12 | 11000 | 202 |
102 | 2016/3/5 | 8 | 10 | 12 | 11000 | 202 |
- 業務員資料表
ID | 業務員 |
201 | 王大同 |
202 | 張曉明 |
沒有留言:
張貼留言