數據庫設計三範式

文章轉載自「開發者圓桌」一個關於開發者入門、進階、踩坑的微信公衆號數據庫

wKioL1i5Ck7AkeuMAAChGHetiEM164.jpg

做爲一個數據庫的學習者,搞懂關係數據庫的三大範式是頗有用的。然而有關數據庫範式的介紹都是採用學術性的定義,語法羞澀,讓人難懂,故寫下本身對數據庫範式的理解,給初學者提供幫助。微信


關係數據庫中的關係必須知足必定的要求。知足不一樣程度要求的爲不一樣範式。數據庫的設計範式是數據庫設計所須要知足的規範。只有理解數據庫的設計範式,才能設計出高效率、優雅的數據庫,不然可能會設計出錯誤的數據庫。數據庫設計


目前,主要有六種範式:第一範式、第二範式、第三範式、BC範式、第四範式和第五範式。知足最低要求的叫第一範式,簡稱1NF。在第一範式基礎上進一步知足一些要求的爲第二範式,簡稱2NF。其他依此類推。ide


範式能夠避免數據冗餘,減小數據庫的空間,減輕維護數據完整性的麻煩,可是操做困難,由於須要聯繫多個表才能獲得所須要數據,並且範式越高性能就會越差。要權衡是否使用更高範式是比較麻煩的,通常在項目中,用得最多的也就是第三範式,使用到第三範式也就足夠了,性能好並且方便管理數據。性能


本文不介紹規範化程度高於3NF的範式,對於不少大型複雜的系統,其數據庫設計都沒有遵循所謂的範式,這也是爲何會出現所謂的逆規範化,範式也須要考慮使用場景,不可一切東西都要範式化。在沒有更多實踐經驗的狀況下,遵循範式是很是好的選擇。學習


在實例中理解三大範式
spa


1NF:字段不可分.net


強調的是列的原子性,即列不可以再分紅其餘幾列。 設計


例1,學生信息表orm


學生編號 姓名 性別 聯繫方式

20080901 張三 男 email:zs@126.com,phone:88886666

20080902 李四 女 email:ls@126.com,phone:66668888

以上的表就不符合,第一範式:聯繫方式字段能夠再分,因此變動爲正確的是:

學生編號 姓名 性別 電子郵件 電話

20080901 張三 男 zs@126.com 88886666

20080902 李四 女 ls@126.com 66668888


例2,學生班級信息


學生編號 姓名 班級

20080901 小明 高三1班

20080902 小葉 高三2班

以上的表就不符合,第一範式:班級字段能夠再分,因此變動爲正確的是:

學生編號 姓名 年級 班級

20080901 小明 高三 1班

20080902 小葉 高三 2班


例3,員工信息表


員工編號 姓名 工做年限

20080901 小明 2009~2011

20080902 小葉 2006~2012

以上的表就不符合,第一範式:工做年限能夠再分,因此變動爲正確的是:

員工編號 姓名 工做年份 離職年份 

20080901 小明 2009 2011

20080902 小葉 2006 2012


例4,學生成績表


學生編號 姓名 課程成績

20080901 小明 80,70,90

20080902 小葉 60,70,85

以上的表就不符合,第一範式:課程成績能夠再分,因此變動爲正確的是:

學生編號 姓名 語文 數學 外語

20080901 小明 80 70 90

20080902 小葉 60 70 85


例5,聯繫人信息表


姓名 性別 電話

小明  男   0101-3464554,13699170707

小葉  女   0101-3464674,13623450707

以上的表就不符合,第一範式:電話能夠再分,因此變動爲正確的是:

姓名 性別 座機 手機

小明  男   0101-3464554 13699170707

小葉  女   0101-3464674 13623450707


例6,公司信息表


公司編號 名稱 地址

20080901 谷歌 美國加利福尼亞州聖克拉拉縣山景市

20080902 百度 中國北京市海淀區上地十街10號百度大廈

以上的表就不符合,第一範式:地址能夠再分,因此變動爲正確的是:

公司編號 名稱 國籍 地址

20080901 谷歌 美國 加利福尼亞州聖克拉拉縣山景市

20080902 百度 中國 北京市海淀區上地十街10號百度大廈


對於例6地址的拆分可根據需求進行,不必定非要拆分。若是需知道哪一個國家並按其分類,那麼顯然第一個表格是不容易知足需求的,也不符合第一範式。所以是否符合第一範式的要求在必定程度上取決於後期對數據的查詢和使用上,固然,第一範式是前人總結的通用方法,遵循它會獲得意想不到的好處。



2NF:有主鍵,非主鍵字段依賴主鍵


首先是知足 1NF,另外包含兩部份內容,一是表必須有一個主鍵;二是沒有包含在主鍵中的列必須徹底依賴於主鍵。


主鍵很重要,要記住在設計表的時候不管如何也要添加主鍵,沒有主鍵的表會給你帶來噩夢般的體驗,會給系統開發、功能維護、數據維護帶來沒必要要的麻煩。舉個例子,上面例5,聯繫人信息表就沒有添加主鍵,以下數據你想刪除小明的信息該如何操做,根據姓名嗎?不行,由於有重名的狀況,只能經過姓名+電話兩個字段組合爲一個惟一的條件進行刪除。


姓名 性別 電話

小明  男   0101-3464554,13699170707

小葉  女   0101-3464674,13623450707

小朱  女   0101-3464675,13623450705

小明  男   0101-3464676,13623450706


而有了主鍵,狀況會是怎樣的呢?你只須要根據聯繫人編號便可刪除,一步到位。


聯繫人編號 姓名 性別 電話

1 小明  男   0101-3464554,13699170707

2 小葉  女   0101-3464674,13623450707

3 小朱  女   0101-3464675,13623450705

4 小明  男   0101-3464676,13623450706


切記,在任什麼時候刻,一張表必定要有主鍵,若是你沒法肯定業務中哪一個字段做爲主鍵,那麼你就創建一個ID字段做爲主鍵,多一個ID字段不會影響什麼。


例1,學生信息表(主鍵學號)


學號 姓名 性別 年齡 課程名稱 學分

2008 張三 男 15 語文    45

2008 張三 男 15 數學    55

2009 李四 女 16 語文    45

2009 李四 女 16 數學    55

以上的表就不符合,第二範式:主鍵(學號)沒法惟一肯定課程名稱和學分,也就是說部分非主鍵字段不依賴主鍵,因此變動爲正確的是:


學生信息表


學號 姓名 性別 年齡

2008 張三 男 15 

2008 張三 男 15 


課程表


課程名稱 學分

語文     45

數學     55


學生選課表


學號  課程名稱

2008  語文

2008  數學

2009  語文

2009  數學


例2,學生借書表


學生證號 學生證辦理時間 借書證號 借書證辦理時間

2008 2010年9月1號 201001  2010年10月1號

2009 2010年9月2號 201011  2011年10月1號

以上的表就不符合,第二範式:借書證號和借書證辦理時間這些非主鍵字段不依賴學生證號這個主鍵,因此變動爲正確的是:


學生證表


學生證號 學生證辦理時間

2008 2010年9月1號

2009 2010年9月2號 


借書證表


借書證號 借書證辦理時間

201001  2010年10月1號

201011  2011年10月1號


例3,訂單表訂單編號和商品編號爲聯合主鍵


訂單編號 商品編號 商品名稱 數量 單位 價格 客戶 所屬單位 聯繫方式

001 1 挖掘機 1 臺 1200000¥ 張三 上海玖智 020-1234567

001 2 衝擊鑽 8 把 230¥     張三 上海玖智 020-1234567

002 3 剷車   2 輛 980000¥  李四 北京公司 010-1234567

這樣就產生一個問題:這個表中是以訂單編號和商品編號做爲聯合主鍵。這樣在該表中商品名稱、單位、商品價格等信息不與該表的主鍵相關,而僅僅是與商品編號相關。因此在這裏違反了2NF的設計原則。而若是把這個訂單信息表進行拆分,把商品信息分離到另外一個表中,把訂單項目表也分離到另外一個表中,就很是完美了。以下所示:


訂單信息表


訂單編號 客戶 所屬單位 聯繫方式

001 張三 上海玖智 020-1234567

002 李四 北京公司 010-1234567


訂單項目表


訂單編號 商品編號 數量

001 1 1

001 2 8

002 3 2


商品信息表


商品編號 商品名稱 單位 商品價格

1 挖掘機 臺 1200000¥

2 衝擊鑽 個 230¥

3 剷車 輛 980000¥



3NF:非主鍵字段不能相互依賴


首先是 2NF,另外非主鍵列必須直接依賴於主鍵,不能存在傳遞依賴。即不能存在:非主鍵列 A 依賴於非主鍵列 B,非主鍵列 B 依賴於主鍵的狀況。 通俗解釋:任意一個字段都只依賴表中的同一個字段。


例1,家庭成員表


戶主 兒子 女兒 女兒的小熊 女兒的海綿寶寶

Jack Tom  Lucy  Bear       spongebob

Jobs july Lily  Bear2      spongebob2

以上的表就不符合,第三範式:其中 兒子 女兒 等非主鍵列都徹底依賴於主鍵(戶主),因此符合 2NF,不過問題是 女兒的小熊 女兒的海綿寶寶 直接依賴的是 女兒字段 (非主鍵列),而不是直接依賴於主鍵,它經過傳遞才依賴於主鍵,因此不符合 3NF。 因此變動爲正確的是:


戶主信息表


戶主 兒子 女兒

Jack Tom  Lucy

Josb  July  Lily


女兒信息表


女兒 女兒的小熊 女兒的海綿寶寶

Lucy  Bear       spongebob

Lily  Bear2      spongebob2


例2,訂單表(主鍵是OrderID)


OrderID OrderDate CustomerID CustomerName CustomerAddr CustomerCity

101  2011年 100 xx聯合公司 中央大街100號 紐約

102  2012年 100 xx聯合公司 中央大街100號 紐約

103  2014年 200 yy聯合公司 白宮          紐約

以上的表就不符合,第三範式:其中 OrderDate,CustomerID等非主鍵列都徹底依賴於主鍵(OrderID),因此符合 2NF,不過問題是 CustomerName,CustomerAddr,CustomerCity 直接依賴的是 CustomerID(非主鍵列),而不是直接依賴於主鍵,它是經過傳遞才依賴於主鍵,因此不符合 3NF。 因此變動爲正確的是:


訂單表


OrderID OrderDate CustomerID

101  2011年 100

102  2012年 100

103  2014年 200


客戶信息表


CustomerID CustomerName CustomerAddr CustomerCity

100 xx聯合公司 中央大街100號 紐約

200 yy聯合公司 白宮          紐約


例3,學生信息表(主鍵是學號)


學號 姓名  所在系 系名稱 系地址 

101  小明  001 數學系 1號樓

102  小葉  002 文學系 5號樓

103  小炫  003 物理系 6號樓

以上的表就不符合,第三範式:其中學號,姓名,所在系等非主鍵列都徹底依賴於主鍵(學號),因此符合 2NF,不過問題是系名稱,系地址直接依賴的是所在系(非主鍵列),而不是直接依賴於主鍵,它是經過傳遞才依賴於主鍵,因此不符合 3NF。 因此變動爲正確的是:


學生表


學號 姓名  所在系

101  小明  001 

102  小葉  002 

103  小炫  003


院系信息表


系編號 系名稱 系地址 

001 數學系 1號樓

002 文學系 5號樓

003 物理系 6號樓


第二範式(2NF)和第三範式(3NF)的概念很容易混淆,區分它們的關鍵點在於,2NF:非主鍵列是否徹底依賴於主鍵,仍是依賴於主鍵的一部分;3NF:非主鍵列是直接依賴於主鍵,仍是直接依賴於非主鍵列。


經過對每一個範式的定義介紹,加上幾個在實踐中的反例進行講解,可在必定程度上加快理論的理解,縮短理論和實踐之間的距離,可快速上手3範式在開發中的應用。