裝載於"http://www.cnblogs.com/KissKnife/數據庫
理論性的東西,每每容易把人人都看得懂的東西寫成連鬼都看不懂,近似於主任醫生開的藥方。從前學範式的時候,把書中得概念翻來覆去看,看得痛心疾首深惡痛絕,再加上老師深切誤導,最後一塌糊塗。藉助網絡資源,本身寫了一篇,本身是看懂了,但願對你們也有所幫助,有錯誤幫忙指正。網絡
數據庫範式(Normal forms):是用於規範關係型數據庫設計,以減小謬誤發生的一種準則。app
1NF(first normal form): dom
Table faithfully represents a relation and has no repeating groups.數據庫設計
數據庫表必須如實地展示「關係」,而且不容許有「重複組」出現。函數
這樣的概念真是使人痛心疾首,咱們只好再搬出1NF的的做者之一Chris Date的解釋:性能
1. There's no top-to-bottom ordering to the rows.學習
(任意兩行沒有特定的順序關係。不存在一個特定的理由要某一行必須在另外一行以前。)spa
2. There's no left-to-right ordering to the columns.設計
(任意兩列沒有特定的順序關係。)
3. There are no duplicate rows.
(不容許存在重複的行。若是一張表沒有Unique Key,事實上它是違反1NF的。)
4. Every row-and-column intersection contains exactly one value from the applicable domain (and nothing else).
(不容許出現空值Null,這一點不一樣做者是有爭議的。事實上咱們經常違背這點。)
5. All columns are regular [i.e. rows have no hidden components such as row IDs, object IDs, or hidden timestamps].
(不容許存在隱藏字段。不知道Oracle的Rowid屬不屬於這個?)
有人從第四點的「one value」大肆挖掘,因而咱們就見到了書上這樣的定義:「若是一個關係模式R的全部屬性都是原子的,即不可再分的基本數據項,則RÎ1NF」。
這一點被認爲是1NF的核心,「關係模式R」↔「表」,「屬性」 ↔ 「列」,下面是一種與1NF不一致的狀況,一般這是一類很明顯的設計缺陷:
ID |
Artist |
FavoriteColor |
…… |
1 |
Babyface |
Blue,Yellow |
…… |
2 |
Sting |
Green |
…… |
對上例咱們不能把它拆分紅FavoriteColor一、FavoriteColor2……由於首先咱們不能肯定該拆分紅幾列;其次FavoriteColor1與FavoriteColor2在結構、含意方面都是相同的,這實際上也是一類「repeating group」;同時這種設計會致使某些查詢困難,好比「有哪些藝人喜歡黃色?」
解決方案是將表拆分紅兩個:
ID |
Artist |
…… |
1 |
Babyface |
…… |
2 |
Sting |
…… |
ID |
FavoriteColor |
1 |
Blue |
1 |
Yellow |
2 |
Green |
總結:
對1NF最核心的 「原子性」,違反此規範的可能性:接近於0%。不過,網上不少帖子說在關係型數據庫中根本不可能違背1NF,我認爲這是不對的。
2NF(second normal form):
No non-prime attribute in the table is functionally dependent on a part (proper subset) of a candidate key.
不存在非主屬性對任一候選鍵的部分函數依賴。
若是解釋完下面幾個概念,這個定義就能夠讀懂了:
Superkey:超級鍵(L),若是屬性或屬性組合能惟一標識一條記錄,則它是一個Superkey。
Candidate key:候選鍵,當Superkey只包含一個屬性時,則它是一個候選鍵;當Superkey包含一組屬性時,僅當這一組屬性不包含另外一Superkey時,它是一個候選鍵。換句話說,候選鍵是「純淨的」、最小化的Superkey。
Non-prime attribute:非主屬性,未在任何候選鍵中出現的屬性,即爲非主屬性。
舉例來講,對錶{First_name,Last_name,Address},假定全名不重複,則:
Superkey:
{First_name,Last_name}
{First_name,Last_name,Address}
Candidate key:
{First_name,Last_name}
Non-prime attribute:
Address
淺白版:「2NF針對的是複合候選鍵(即鍵包含的字段個數>1)的狀況,非主屬性不能只依賴於複合候選鍵中的一部分字段。」顯然,若是是非複合候選鍵,若是它符合1NF,那麼它必定符合2NF。
假設有這樣一張涉及藝人與唱片公司的關係表:
Artist 藝人 |
Company 唱片公司 |
DurationYears 簽約總年數 |
CompAddr 公司住址 |
Babyface |
Solar |
4 |
Indiana |
Babyface |
Laface |
2 |
Indiana |
顯然,{Artist,Company}爲能夠做爲一個候選鍵,DurationYears在這沒有問題,但CompAddr是違反2NF的,它只依賴於候選鍵的一部分(依賴於Company),這是違反2NF的,爲了消除這種狀況,咱們能夠:
Artist 藝人 |
CompID 唱片公司 |
DurationYears 簽約總年數 |
Babyface |
1 |
4 |
Babyface |
2 |
2 |
ID |
Company 唱片公司 |
CompAddr 公司住址 |
1 |
Solar |
Indiana |
2 |
Laface |
Indiana |
總結:
對於2NF,若是關係中的候選鍵只包含一個屬性,能夠直接略過。
在考慮2NF的過程當中,不要把幾個無關的實體的屬性雜揉放在一個關係中,好比Artist是一個實體、Company是一個實體,它們能夠有一系列的關聯表(也是實體),但在關聯表中儘可能不要引入前兩個實體的無關屬性。
3NF(Third normal form)
Every non-prime attribute is non-transitively dependent on every key of the table.
不存在非主屬性對任一鍵(候選鍵)的傳遞依賴。
傳遞依賴,你能夠顧名思義,這裏就再也不引入定義了,舉個例子,有下面一張表:
Tournament 賽事 |
Year 年份 |
Winner 冠軍 |
Winner Date of Birth 冠軍生日 |
Indiana Invitational |
1998 |
Al Fredrickson |
21 July 1975 |
Cleveland Open |
1999 |
Bob Albertson |
28 September 1968 |
Des Moines Masters |
1999 |
Al Fredrickson |
21 July 1975 |
Indiana Invitational |
1999 |
Chip Masterson |
14 March 1977 |
這裏的候選鍵爲{Tournament,Year},顯然有這樣的決定關係:
{Tournament,Year}→Winner
{Tournament,Year}→Winner→Winner Date of Birth
其中第二條就屬於違反3NF的狀況,由於Winner Date of Birth依賴於Winner而不是直接依賴於候選鍵。這種狀況下,能夠將Winner,Winner Date of Birth單獨做爲一張表,這裏不贅述。
總結:
我以爲大多數人憑藉直觀感受,就可以使設計的關係符合3NF,因此這些理論,你只須要姑且讀之。
BCNF(Boyce-Codd normal form)(Boyce與Codd是該範式的兩名做者。)
Every non-trivial functional dependency in the table is a dependency on a superkey.
表中的任何非平凡函數依賴,都必須是對superkey的依賴。
non-trivial functional dependency:非平凡函數依賴,若是存在一個決定關係x→y,且y並不是x的子集,則叫着y非平凡函數依賴於x。
BCNF與3NF的最大區別是它並不只針對非主屬性(non-prime attribute)來講,它發生的時候經常是表中根本不存在非主屬性,以致於它不可能違反2NF或3NF。而BCNF的出現就是爲了擴大「打擊面」。
因而BCNF的主旨是:補充對發生在主屬性(prime attribute)身上的函數依賴的約束,由於對於非主屬性的約束已經在3NF中完成了。
例子,使用關係表描述學生、課程、教師的關係(假定一名教師只負責一門課程,一門課程則能夠由多位教師負責):
Student 學生 |
Course 課程 |
Teacher 教師 |
S1 |
C1 |
T1 |
S1 |
C2 |
T2 |
S2 |
C1 |
T1 |
S2 |
C2 |
T3 |
S2 |
C3 |
T2 |
候選鍵:
{Student,Course}
{Student,Teacher}
所以這裏不存在非主屬性,而在主屬性的函數依賴中,存在Teacher→Course,這屬於違反BCNF的狀況。
但是,問題是這個表看起來還挺正常的啊?!它的毛病在於,咱們沒法阻止相似最後一行這樣的數據插入,而這會致使與前提「一名教師只負責一門課程」違背。因此咱們仍是須要將它拆分:
Student 學生 |
Teacher 教師 |
S1 |
T1 |
S1 |
T2 |
S2 |
T1 |
S2 |
T3 |
Teacher 教師 |
Course 課程 |
T1 |
C1 |
T2 |
C2 |
T3 |
C2 |
這樣,在「Teacher-Course」表中,藉助主鍵的幫助,最後能夠避免違背「一名教師只負責一門課程」這個前提。
那麼,若是沒有這樣一個前提,是初的設計是否符合BCNF?目前看來是的。
真實的狀況可能更爲複雜,下面這個更接近於個人一些經歷:
1)學生須要學習多門課程
2)一門課程可能有多位教師負責
3)一位教師可能負責多門課程
4)某一班級的某一課程對應的教師是固定的(一位)
據此,爲了描述學生、課程、教師三者的關係,從這一團亂麻中最先跳出來的大概是這樣的表:
Student 學生 |
Class 班級 |
Course 課程 |
Teacher 教師 |
候選鍵:
{Student,Course}
咱們能夠明顯地看到Student→Class違反了2NF,因而:
Student 學生 |
Class 班級 |
Class 班級 |
Course 課程 |
Teacher 教師 |
從這兩張表,仔細考慮,即使咱們經過Class關聯兩張表,仍是沒法得出學生與課程的關係(只能得出可供該學生選擇的課程),因此咱們須要再添加一張表:
Student 學生 |
Course 課程 |
最後大概是這麼三張表,可能還有其它的方案,這裏只是舉例說明,就不糾纏了。
在BCNF以後,還有4NF,5NF,DKNF,6NF,等何時有空了再看看是什麼東東。
"
再轉一篇百度文庫裏的文章, 沒有上篇那麼通俗易懂可是內容很全
"
範式
就關係數據庫而言,一向認爲:從其餘元素中消除數據冗餘問題,去除重複每每以減小冗餘, 從特定的表中最小化冗餘意味着擺脫沒必要要的數據。
商業上來說,主要目標是一般保存空間和組織的數據可用性和可管理性,而不犧牲性能。此外,要求強烈繁忙的應用程序和最終用戶的須要每每須要以多種方式打破規則的範式,以知足性能要求。第三範式之外的範式經常被忽視和有時甚至是第三範式自己就是多餘的。
範式是一個升級的過程,每一個上層的模式都是創建在下一級範式之上的。
消除數據冗餘的影響以下:
❑物理空間須要存儲的數據減小。
❑數據變得更有組織。
❑範式化容許修改少許的數據(即單記錄)。換言之,一個表的具體字段記錄更新時,會影響其餘引用他的表。
首先咱們對一些概念性的東西來進行一個總結,經過對這些概念的理解,歷來從根本上作到合理的數據庫設計:
異常
添加異常:當咱們添加一條記錄的時候,他依賴的主表記錄尚未記錄,而該記錄已經插入成功。
刪除異常:當咱們的主表記錄刪除,而依賴他的子表沒有清空對應的記錄。
更新異常:當咱們的主表記錄有更新草組,而已來他的子表沒有相應的更新記錄。依賴,決定因子
函數依賴:當Y的值由X決定的時候,咱們就說Y函數依賴於X,這就相似於一個線性方程:Y=X+1;相似的ERD圖中,咱們這樣表示 ,很清楚的看到表Category,中的主鍵是CategoryID,他決定着其餘字段的值Name和Pic,咱們就說Name或者Pic 函數依賴於CategoryID,他們之間就是一個函數依賴關係。
決定因素:如上例中,CategoryID就是一個決定因素,他決定其餘字段的值,Y=X+1中,X就決定着Y的值,雖然加了一個常量。
傳遞依賴:當X決定Y,Y決定Z的時候,咱們就說Z傳遞依賴於X,,從這個ERD圖中,咱們看到Account賬號表中的City字段,他被AccountID所決定,而City字段的值又決定了College的值,由於大學確定是被城市所決定,因此College就傳遞依賴於AccountID。
候選鍵:候選鍵(潛在的或容許的主鍵)能夠扮演主鍵的角色他能夠是一個表中的一個字段或組合字段——也就是一條記錄中的惟一標識。,咱們看到這個表,Customer表(客戶表),字段分別表示,客戶ID,客戶名,貨幣縮寫碼,貨幣,轉換匯率,地址。這個表咱們沒有定義主鍵,可是咱們能夠推測那些能夠成爲主鍵,那麼那些鍵就叫作候選鍵。,咱們就看到了,全部能成爲主鍵的可能,表中的#就是主鍵的標識符。
徹底函數依賴:當X決定Y,可是X不被X和Z的組合所決定,換句話說,YE依賴於獨立的X,若是Y依賴於X加上一些其餘的東西,那就不是徹底函數依賴,本質上,決定因素X不能是一個組合鍵。,咱們來看到旅遊表Travel,Country是旅遊的國家,Populication是旅遊的城市,同時TravelID和CountryID是主鍵,能夠看出來只有CountryID決定着Populcation人口,可是這裏有兩個主鍵,因此Populication並無徹底函數依賴於主鍵組合,只部分依賴於CountryID
多值依賴:某個字段中的值之一個集合,或者是用某種分隔符分割開來的元素集合,咱們就稱爲多值依賴。很經典的,Path保存的這個遞歸表的全部上司的級別,好比老大的ID是1,老2是2,Path 就保存1,2,像這樣的字段,咱們就稱爲多值依賴。
循環依賴:循環依賴就如其名,是一個個閉環的依賴系統。A依賴於B,B依賴於C,C依賴於A。範式(學術定義)
第一範式(1NF):消除表中全部重複的記錄,除了主鍵之外的全部其餘字段所有依賴於主鍵。
第二範式(2NF):全部非鍵值字段必須所有徹底函數依賴於主鍵,當一個字段徹底函數依賴於一組組合主鍵的部分函數依賴是不容許的。
第三範式(3NF):消除傳遞依賴,意味着一個字段必須非間接的依賴於主鍵 正規化範式(BCDF):全部表中的決定因素必須是一個候選鍵,若是隻有一個候選鍵,那麼就和第三範式是同樣的。
第四範式(4NF):消除多值依賴。
第五範式(5NF):消除循環依賴。
咱們從一個比較容易的位置來理解範式,經過上述的理解,加上實際的操做範式,讓咱們對數據庫的設計有一個比較深的認識,以決定什麼狀況下用範式。
第一範式(1NF):經過建立一個新表來移除重複的元素,使他們成爲一個主從關係或者是one to many的關係,相似下圖:。
第二範式(2NF):創建在1NF的基礎上,就是移除重複的值到一個新表中去,新表有惟一的主鍵,而主表有一個對新表的外鍵的引用,排除存在的部分依賴。以下圖:Bookid 是book表的主鍵,而author是author1的主鍵,在book表中創建author,主表有一個對子表的外鍵引用,而不是把author也定義爲主鍵,那樣就存在部分函數依賴,由於bookid就已經肯定了title,page,isbn等等信息。
第三範式:消除傳遞依賴,以下圖:咱們把多對多的關係變化成上圖的關係。這是一種簡單的形式,下面展現一個另一種狀況:這裏的表分別是客戶(客戶名,貨幣號,貨幣,貨幣,匯率,地址),提供商(客戶名,貨幣號,貨幣,匯率,地址)。首先他們的地址決定了他們的貨幣狀況,而地址又是由客戶或者提供商決定的,因此他們之間存在一個傳遞依賴關係,並且最好是把相同的存在於不一樣的數據移植到一個新表中去。前面咱們提到了這個關係,也是一個不知足第三範式的表,City和College以及主鍵存在傳遞關係,因此能夠把College移植到一個新表中去,還有一些存在訂單的表中,有相似(qty(數量),price(單價),total(總價))的結構,qty和price決定了total,而訂單號決定了qty和,price,因此也存在一中依賴關係,咱們要刪除total字段,可是不是都遵循範式的表都是好的結構,咱們仍是要根據實際狀況,好比在一個數據倉庫的設計中,彙總字段就是必須的。
超三範式(Beyond 3NF)中的one to one關係,這個主要用戶當咱們表中一些字段常常存在空值的時候,咱們將存在的NULL字段移到一個新表中去,而後創建1對1的關係。
BCNF範式:BCNF劃分紅多個表的表格,以確保沒有一個單一的表有更多不止一個潛在的主鍵。這是個人理解BCNF 。在我看來,是BCNF 用於商業環境是「過分設計「的。從本質上講,從數學的角度上它的漂亮,但在商業環境中它不是很酷。下面的例子是一個BCNF轉換:
第四範式:消除多值依賴,很經典的一個環境就是,咱們的遞歸表問題,一個Manager有多個Employee,而後每條記錄都有一個Path老表示這種關係,因此path和EmployeeId就存在一個多對多的關係。咱們就應該從新創建一個新表,用來消除Path字段,新表中就保留一個EmployeeId做爲外鍵,另一個EmployeeId用來表示他的下屬。
第五範式:消除循環依賴,以下圖:在這個實例中Solution表中的鍵都是主鍵,他們存在這樣的關係,每兩個組合的主鍵決定另一個主鍵。比方項目1和經理1就決定了有哪些下屬屬於項目1和經理1關係,而一個經理1和他的下屬員工又決定了他們參與了那些項目。因此他們之間實際上是一個循環的依賴。
反範式:這種類型的應用在商業正常化環境將致使業績不佳,更精確的數學的必要性比商業要低的多。所以:
一樣的,對於第4範式,咱們不少時候都沒有必要去消除他們裏面多值的依賴,那樣對性能來講簡直是個噩夢。因此不少狀況下,咱們都是用相似的處理CSDN上的,顯示本身的技術就是這樣的反範式化轉換。
在商業環境中,絕大多數超越第3範式的設計都是不切實際的。由於應用程序在3NF級別就能變現的至關出色。咱們上述的不少例子,將指向箭頭反過來就是先了反範式化。因此咱們要對總體的結構有個比較深的認識,才肯定咱們是否範式話或者反範式化,範式化越深的東西越致使表的增多,也就意味着查詢的join開銷。
總結一下反範式化的一些準則:
分離活動和靜態的數據,數據可分爲獨立的物理表,即
活動和靜態表。那些累計的歷史數據致使咱們佔據了絕大多數的空間。這是影響性能的最常常的數據,在數據倉庫設計中,咱們常常將無效的靜態的數據移植到數據倉庫中,因爲OLAP和數據挖掘。
在表之間複製字段,在那些不是直接有連接表的之間複製字段,使得咱們沒必要每次進行查詢都要經過第3方表,越少的join操做,使得性能的大幅度提高。
在夫表中創建統計字段,這樣能夠減去消耗大的聚合操做,可是實時更新會給咱們帶來另外的麻煩。
分離繁重和輕鬆的字段,就像把活動和靜態的數據數據表分離同樣,這個避免持續物理掃描不多使用的數據字段,尤爲是當這些字段不包含空值。這是一個潛在的合理利用4NF在分離表格分爲兩個表格,相關的一對一關係。
"
上面的文章是有圖的, 因爲圖太多了就沒貼, 能夠在這裏下載有圖完整版
最後附上本身記的老師的理解:
2NF: 每一個非主屬性徹底函數依賴於碼。(沒有非主屬性屬於2NF)
3NF: 每一個非主屬性既不部分依賴於碼,也不傳遞依賴於碼。
BCNF:每一個非主屬性和主屬性既不部分依賴於碼,也不傳遞依賴於碼。(完全解決刪除異常問題)
最後的最後附一張很是簡單明瞭的圖:
網上的關於多值依賴的解釋:
"
什麼是多值依賴?書上的概念是:設R(U)是屬性集U上的一個關係模式。X,Y,Z是U的子集,而且Z=U-X-Y.關係模式R(U)中多值依賴X→→Y成立,當且僅當對R(U)的任一關係r,給定的一對(x,z)值,有一組Y的值,這組值僅僅決定於x,與z無關!太抽象了!看不懂!
"