天天看點

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)

文章目錄

  • 什麼是”範式(NF)”
  • 1. 第一範式(1NF)
  • 2. 第二範式(2NF)
    • 2.1 函數依賴
      • 2.1.1完全函數依賴
      • 2.1.2 部分函數依賴
    • 2.2 碼
    • 2.3 非主屬性
  • 3. 第三範式(3NF)
  • 4. 小結

什麼是”範式(NF)”

按照教材中的定義,範式是“符合某一種級别的關系模式的集合,表示一個關系内部各屬性之間的聯系的合理化程度”。很晦澀吧?實際上你可以把它粗略地了解為一張資料表的表結構所符合的某種設計标準的級别。就像家裡裝修買建材,最環保的是E0級,其次是E1級,還有E2級等等。資料庫範式也分為1NF,2NF,3NF,BCNF,4NF,5NF。一般在我們設計關系型資料庫的時候,最多考慮到BCNF就夠。符合高一級範式的設計,必定符合低一級範式,例如符合2NF的關系模式,必定符合1NF。

接下來就對每一級範式進行一下解釋。

1. 第一範式(1NF)

符合1NF的關系(你可以了解為資料表。“關系模式”和“關系”的差別,類似于面向對象程式設計中”類“與”對象“的差別。”關系“是”關系模式“的一個執行個體,你可以把”關系”了解為一張帶資料的表,而“關系模式”是這張資料表的表結構。1NF的定義為:符合1NF的關系中的每個屬性都不可再分。

表1

所示的情況,就不符合1NF的要求。

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

表1

實際上,1NF是所有關系型資料庫的最基本要求,你在關系型資料庫管理系統(RDBMS),例如SQL Server,Oracle,MySQL中建立資料表的時候,如果資料表的設計不符合這個最基本的要求,那麼操作一定是不能成功的。也就是說,隻要在RDBMS中已經存在的資料表,一定是符合1NF的。如果我們要在RDBMS中表現表中的資料,就得設計為

表2

的形式:

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

表2

但是僅僅符合1NF的設計,仍然會存在資料備援過大,插入異常,删除異常,修改異常的問題,例如對于

表3

中的設計:

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

表3

  1. 每一名學生的學号、姓名、系名、系主任這些資料重複多次。每個系與對應的系主任的資料也重複多次——資料備援過大
  2. 假如學校建立了一個系,但是暫時還沒有招收任何學生(比如3月份就建立了,但要等到8月份才招生),那麼是無法将系名與系主任的資料單獨地添加到資料表中去的 (注1)——插入異常
  • 注1:根據三種關系完整性限制中實體完整性的要求,關系中的碼(注2)所包含的任意一個屬性都不能為空,所有屬性的組合也不能重複。為了滿足此要求,圖中的表,隻能将學号與課名的組合作為碼,否則就無法唯一地區分每一條記錄。
  • 注2:碼:關系中的某個屬性或者某幾個屬性的組合,用于區分每個元組(可以把“元組”了解為一張表中的每條記錄,也就是每一行)。
  1. 假如将某個系中所有學生相關的記錄都删除,那麼所有系與系主任的資料也就随之消失了(一個系所有學生都沒有了,并不表示這個系就沒有了)。——删除異常
  2. 假如李小明轉系到法律系,那麼為了保證資料庫中資料的一緻性,需要修改三條記錄中系與系主任的資料。——修改異常。

正因為僅符合1NF的資料庫設計存在着這樣那樣的問題,我們需要提高設計标準,去掉導緻上述四種問題的因素,使其符合更高一級的範式(2NF),這就是所謂的“規範化”。

2. 第二範式(2NF)

在關系理論中的嚴格定義我這裡就不多介紹了(因為涉及到的鋪墊比較多),隻需要了解2NF對1NF進行了哪些改進即可。其改進是,2NF在1NF的基礎之上,消除了非主屬性對于碼的部分函數依賴。接下來對這句話中涉及到的四個概念——“函數依賴”、“碼”、“非主屬性”、與“部分函數依賴”進行一下解釋。

2.1 函數依賴

我們可以這麼了解(但并不是特别嚴格的定義):若在一張表中,在屬性(或屬性組)X的值确定的情況下,必定能确定屬性Y的值,那麼就可以說Y函數依賴于X,寫作 X → Y。也就是說,在資料表中,不存在任意兩條記錄,它們在X屬性(或屬性組)上的值相同,而在Y屬性上的值不同。這也就是“函數依賴”名字的由來,類似于函數關系 y = f(x),在x的值确定的情況下,y的值一定是确定的。

例如,對于表3中的資料,找不到任何一條記錄,它們的學号相同而對應的姓名不同。是以我們可以說姓名函數依賴于學号,寫作 學号 → 姓名。但是反過來,因為可能出現同名的學生,是以有可能不同的兩條學生記錄,它們在姓名上的值相同,但對應的學号不同,是以我們不能說學号函數依賴于姓名。表中其他的函數依賴關系還有如:

系名 → 系主任學号 → 系主任

(學号,課名) → 分數

但以下函數依賴關系則不成立:

學号 → 課名

學号 → 分數

課名 → 系主任

(學号,課名) → 姓名

從“函數依賴”這個概念展開,還會有三個概念:

2.1.1完全函數依賴

在一張表中,若 X → Y,且對于 X 的任何一個真子集(假如屬性組 X 包含超過一個屬性的話),X ’ → Y 不成立,那麼我們稱 Y 對于 X 完全函數依賴,記作 X F→ Y。(那個F應該寫在箭頭的正上方,沒辦法打出來……,正确的寫法如圖1)

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

圖1

例如: 學号 F→ 姓名 (學号,課名) F→ 分數 (注:因為同一個的學号對應的分數不确定,同一個課名對應的分數也不确定)

2.1.2 部分函數依賴

假如 Y 函數依賴于 X,但同時 Y 并不完全函數依賴于 X,那麼我們就稱 Y 部分函數依賴于 X,記作 X P→ Y,如圖2。

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

圖2

例如:(學号,課名) P→ 姓名 傳遞函數依賴假如 Z 函數依賴于 Y,且 Y 函數依賴于 X (感謝 @百達 指出的錯誤,這裡改為:『Y 不包含于 X,且 X 不函數依賴于 Y』這個前提),那麼我們就稱 Z 傳遞函數依賴于 X ,記作 X T→ Z,如圖3。

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

圖3

2.2 碼

設 K 為某表中的一個屬性或屬性組,若除 K 之外的所有屬性都完全函數依賴于 K(這個“完全”不要漏了),那麼我們稱 K 為候選碼,簡稱為碼。在實際中我們通常可以了解為:假如當 K 确定的情況下,該表除 K 之外的所有屬性的值也就随之确定,那麼 K 就是碼。一張表中可以有超過一個碼。(實際應用中為了友善,通常選擇其中的一個碼作為主碼) 例如:對于表3,(學号、課名)這個屬性組就是碼。該表中有且僅有這一個碼。(假設所有課沒有重名的情況)

2.3 非主屬性

包含在任何一個碼中的屬性成為主屬性。

例如:

對于表3,主屬性就有兩個,學号 與 課名。

終于可以回過來看2NF了。首先,我們需要判斷,表3是否符合2NF的要求?根據2NF的定義,判斷的依據實際上就是看資料表中是否存在非主屬性對于碼的部分函數依賴。若存在,則資料表最高隻符合1NF的要求,若不存在,則符合2NF的要求。判斷的方法是:

第一步:找出資料表中所有的碼。

第二步:根據第一步所得到的碼,找出所有的主屬性。

第三步:資料表中,除去所有的主屬性,剩下的就都是非主屬性了。

第四步:檢視是否存在非主屬性對碼的部分函數依賴。

對于表3,根據前面所說的四步,我們可以這麼做:

第一步:

  1. 檢視所有每一單個屬性,當它的值确定了,是否剩下的所有屬性值都能确定。
  2. 檢視所有包含有兩個屬性的屬性組,當它的值确定了,是否剩下的所有屬性值都能确定。
  3. ……
  4. 檢視所有包含了六個屬性,也就是所有屬性的屬性組,當它的值确定了,是否剩下的所有屬性值都能确定。

看起來很麻煩是吧,但是這裡有一個訣竅,就是假如A是碼,那麼所有包含了A的屬性組,如(A,B)、(A,C)、(A,B,C)等等,都不是碼了(因為作為碼的要求裡有一個“完全函數依賴”)。

圖4表示了表中所有的函數依賴關系:

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

圖4

這一步完成以後,可以得到,表3的碼隻有一個,就是 (學号、課名) 。

第二步:主屬性有兩個:學号 與 課名

第三步:非主屬性有四個:姓名、系名、系主任、分數

第四步:

對于(學号,課名) → 姓名,有 學号 → 姓名,存在非主屬性 姓名 對碼(學号,課名)的部分函數依賴。

對于(學号,課名) → 系名,有 學号 → 系名,存在非主屬性 系名 對碼(學号,課名)的部分函數依賴。

對于(學号,課名) → 系主任,有 學号 → 系主任,存在非主屬性 對碼(學号,課名)的部分函數依賴。

是以表3存在非主屬性對于碼的部分函數依賴,最高隻符合1NF的要求,不符合2NF的要求。

為了讓表3符合2NF的要求,我們必須消除這些部分函數依賴,隻有一個辦法,就是将大資料表拆分成兩個或者更多個更小的資料表,在拆分的過程中,要達到更高一級範式的要求,這個過程叫做”模式分解“。模式分解的方法不是唯一的,以下是其中一種方法:

選課(學号,課名,分數)

學生(學号,姓名,系名,系主任)

我們先來判斷以下,選課表與學生表,是否符合了2NF的要求?

對于選課表,其碼是(學号,課名),主屬性是學号和課名,非主屬性是分數,學号确定,并不能唯一确定分數,課名确定,也不能唯一确定分數,是以不存在非主屬性分數對于碼 (學号,課名)的部分函數依賴,是以此表符合2NF的要求。

對于學生表,其碼是學号,主屬性是學号,非主屬性是姓名、系名和系主任,因為碼隻有一個屬性,是以不可能存在非主屬性對于碼 的部分函數依賴,是以此表符合2NF的要求。

圖5表示了模式分解以後的新的函數依賴關系

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

圖5

表4表示了模式分解以後新的資料

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

表4

(這裡還涉及到一個如何進行模式分解才是正确的知識點,先不介紹了)

現在我們來看一下,進行同樣的操作,是否還存在着之前的那些問題?

  1. 李小明轉系到法律系

    隻需要修改一次李小明對應的系的值即可。——有改進

  2. 資料備援是否減少了?

    學生的姓名、系名與系主任,不再像之前一樣重複那麼多次了。——有改進

  3. 删除某個系中所有的學生記錄

    該系的資訊仍然全部丢失。——無改進

  4. 插入一個尚無學生的新系的資訊。

    因為學生表的碼是學号,不能為空,是以此操作不被允許。——無改進

是以說,僅僅符合2NF的要求,很多情況下還是不夠的,而出現問題的原因,在于仍然存在非主屬性系主任對于碼學号的傳遞函數依賴。為了能進一步解決這些問題,我們還需要将符合2NF要求的資料表改進為符合3NF的要求。

3. 第三範式(3NF)

3NF在2NF的基礎之上,消除了非主屬性對于碼的傳遞函數依賴。也就是說, 如果存在非主屬性對于碼的傳遞函數依賴,則不符合3NF的要求。

接下來我們看看表4中的設計,是否符合3NF的要求。

對于選課表,主碼為(學号,課名),主屬性為學号和課名,非主屬性隻有一個,為分數,不可能存在傳遞函數依賴,是以選課表的設計,符合3NF的要求。

對于學生表,主碼為學号,主屬性為學号,非主屬性為姓名、系名和系主任。因為 學号 → 系名,同時 系名 → 系主任,是以存在非主屬性系主任對于碼學号的傳遞函數依賴,是以學生表的設計,不符合3NF的要求。

為了讓資料表設計達到3NF,我們必須進一步進行模式分解為以下形式:

選課(學号,課名,分數)

學生(學号,姓名,系名)

系(系名,系主任)

對于選課表,符合3NF的要求,之前已經分析過了。

對于學生表,碼為學号,主屬性為學号,非主屬性為系名,不可能存在非主屬性對于碼的傳遞函數依賴,是以符合3NF的要求。

對于系表,碼為系名,主屬性為系名,非主屬性為系主任,不可能存在非主屬性對于碼的傳遞函數依賴(至少要有三個屬性才可能存在傳遞函數依賴關系),是以符合3NF的要求。。

新的函數依賴關系如圖6

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

圖6

新的資料表如表5

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

表5

現在我們來看一下,進行同樣的操作,是否還存在着之前的那些問題?

  1. 删除某個系中所有的學生記錄

    該系的資訊不會丢失。——有改進

  2. 插入一個尚無學生的新系的資訊。

    因為系表與學生表目前是獨立的兩張表,是以不影響。——有改進

  3. 資料備援更加少了。——有改進

結論

由此可見,符合3NF要求的資料庫設計,基本上解決了資料備援過大,插入異常,修改異常,删除異常的問題。當然,在實際中,往往為了性能上或者應對擴充的需要,經常 做到2NF或者1NF,但是作為資料庫設計人員,至少應該知道,3NF的要求是怎樣的。

==============時隔半年,終于決定把這個坑填上,來晚了 ===========

BCNF範式

要了解 BCNF 範式,那麼先看這樣一個問題:

若:

某公司有若幹個倉庫;每個倉庫隻能有一名管理者,一名管理者隻能在一個倉庫中工作;

一個倉庫中可以存放多種物品,一種物品也可以存放在不同的倉庫中。每種物品在每個倉庫中都有對應的數量。

那麼關系模式 倉庫(倉庫名,管理者,物品名,數量) 屬于哪一級範式?

答:已知函數依賴集:倉庫名 → 管理者,管理者 → 倉庫名,(倉庫名,物品名)→ 數量

碼:(管理者,物品名),(倉庫名,物品名)

主屬性:倉庫名、管理者、物品名非主屬性:數量

∵ 不存在非主屬性對碼的部分函數依賴和傳遞函數依賴。

∴ 此關系模式屬于3NF。

基于此關系模式的關系(具體的資料)可能如圖所示:

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

好,既然此關系模式已經屬于了 3NF,那麼這個關系模式是否存在問題呢?我們來看以下幾種操作:

先新增加一個倉庫,但尚未存放任何物品,是否可以為該倉庫指派管理者?——不可以,因為物品名也是主屬性,根據實體完整性的要求,主屬性不能為空。

某倉庫被清空後,需要删除所有與這個倉庫相關的物品存放記錄,會帶來什麼問題?——倉庫本身與管理者的資訊也被随之删除了。

如果某倉庫更換了管理者,會帶來什麼問題?——這個倉庫有幾條物品存放記錄,就要修改多少次管理者資訊。

從這裡我們可以得出結論,在某些特殊情況下,即使關系模式符合 3NF 的要求,仍然存在着插入異常,修改異常與删除異常的問題,仍然不是 ”好“ 的設計。

造成此問題的原因:存在着主屬性對于碼的部分函數依賴與傳遞函數依賴。(在此例中就是存在主屬性【倉庫名】對于碼【(管理者,物品名)】的部分函數依賴。

解決辦法就是要在 3NF 的基礎上消除主屬性對于碼的部分與傳遞函數依賴。

倉庫(倉庫名,管理者)

庫存(倉庫名,物品名,數量)

這樣,之前的插入異常,修改異常與删除異常的問題就被解決了。

以上就是關于 BCNF 的解釋。

問:關于碼的定義,如果除K之外的所有屬性都完全函數依賴于K時才能稱K為碼,那麼在判斷2NF時又怎麼會存在非主屬性對碼的部分函數依賴這種情況?

答 :在“碼”的定義中,除 K 之外的所有屬性應該看成是一個集合 U(也就是一個整體),也就是說,隻有 K 能夠完全函數決定 U 中的每一個屬性,那麼 K 才是碼。如果 K 隻是能夠完全函數決定 U 中的一部分屬性,而不能完全函數決定另外一部分屬性,那麼 K 不是碼。

比如有關系模式 R (Sno, Sname, Cno, Cname, Sdept, Sloc, Grade),其中函數依賴集為 F= {Sno → Sname, Sno → Sdept, Sdept → Sloc,Sno → Sloc, Cno → Cname, (Sno, Cno) → Grade }

那麼 R 中的碼隻能是 (Sno, Cno),Sno 或 Cno 并不能完全函數決定除 Sno / Cno 之外的所有其他屬性(其實就是不能決定 Grade ),是以單獨的 Sno 與 Cno 并不能作為碼。

是以可得到主屬性:Sno, Cno

非主屬性:Sname, Cname, Sdept, Sloc, Grade

R 中存在非主屬性 Cname 對于碼 (Sno, Cno) 的部分函數依賴 (Cno → Cname) 。(還有很多别的例子就不一一列舉了)。是以 R 不符合 2NF 的要求。

4. 小結

搬運工覺得這個講解對于初步學習的人比較好。

資料庫範式那些事

總結:

1NF: 字段是最小的的單元不可再分

2NF:滿足1NF,表中的字段必須完全依賴于全部主鍵而非部分主鍵 (一般我們都會做到)

3NF:滿足2NF,非主鍵外的所有字段必須互不依賴4NF:滿足3NF,消除表中的多值依賴

搬運自知乎如何解釋關系資料庫的第一第二第三範式?

摘選劉慰、胡永浩的回答

文章目錄

  • 什麼是”範式(NF)”
  • 1. 第一範式(1NF)
  • 2. 第二範式(2NF)
    • 2.1 函數依賴
      • 2.1.1完全函數依賴
      • 2.1.2 部分函數依賴
    • 2.2 碼
    • 2.3 非主屬性
  • 3. 第三範式(3NF)
  • 4. 小結

什麼是”範式(NF)”

按照教材中的定義,範式是“符合某一種級别的關系模式的集合,表示一個關系内部各屬性之間的聯系的合理化程度”。很晦澀吧?實際上你可以把它粗略地了解為一張資料表的表結構所符合的某種設計标準的級别。就像家裡裝修買建材,最環保的是E0級,其次是E1級,還有E2級等等。資料庫範式也分為1NF,2NF,3NF,BCNF,4NF,5NF。一般在我們設計關系型資料庫的時候,最多考慮到BCNF就夠。符合高一級範式的設計,必定符合低一級範式,例如符合2NF的關系模式,必定符合1NF。

接下來就對每一級範式進行一下解釋。

1. 第一範式(1NF)

符合1NF的關系(你可以了解為資料表。“關系模式”和“關系”的差別,類似于面向對象程式設計中”類“與”對象“的差別。”關系“是”關系模式“的一個執行個體,你可以把”關系”了解為一張帶資料的表,而“關系模式”是這張資料表的表結構。1NF的定義為:符合1NF的關系中的每個屬性都不可再分。

表1

所示的情況,就不符合1NF的要求。

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

表1

實際上,1NF是所有關系型資料庫的最基本要求,你在關系型資料庫管理系統(RDBMS),例如SQL Server,Oracle,MySQL中建立資料表的時候,如果資料表的設計不符合這個最基本的要求,那麼操作一定是不能成功的。也就是說,隻要在RDBMS中已經存在的資料表,一定是符合1NF的。如果我們要在RDBMS中表現表中的資料,就得設計為

表2

的形式:

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

表2

但是僅僅符合1NF的設計,仍然會存在資料備援過大,插入異常,删除異常,修改異常的問題,例如對于

表3

中的設計:

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

表3

  1. 每一名學生的學号、姓名、系名、系主任這些資料重複多次。每個系與對應的系主任的資料也重複多次——資料備援過大
  2. 假如學校建立了一個系,但是暫時還沒有招收任何學生(比如3月份就建立了,但要等到8月份才招生),那麼是無法将系名與系主任的資料單獨地添加到資料表中去的 (注1)——插入異常
  • 注1:根據三種關系完整性限制中實體完整性的要求,關系中的碼(注2)所包含的任意一個屬性都不能為空,所有屬性的組合也不能重複。為了滿足此要求,圖中的表,隻能将學号與課名的組合作為碼,否則就無法唯一地區分每一條記錄。
  • 注2:碼:關系中的某個屬性或者某幾個屬性的組合,用于區分每個元組(可以把“元組”了解為一張表中的每條記錄,也就是每一行)。
  1. 假如将某個系中所有學生相關的記錄都删除,那麼所有系與系主任的資料也就随之消失了(一個系所有學生都沒有了,并不表示這個系就沒有了)。——删除異常
  2. 假如李小明轉系到法律系,那麼為了保證資料庫中資料的一緻性,需要修改三條記錄中系與系主任的資料。——修改異常。

正因為僅符合1NF的資料庫設計存在着這樣那樣的問題,我們需要提高設計标準,去掉導緻上述四種問題的因素,使其符合更高一級的範式(2NF),這就是所謂的“規範化”。

2. 第二範式(2NF)

在關系理論中的嚴格定義我這裡就不多介紹了(因為涉及到的鋪墊比較多),隻需要了解2NF對1NF進行了哪些改進即可。其改進是,2NF在1NF的基礎之上,消除了非主屬性對于碼的部分函數依賴。接下來對這句話中涉及到的四個概念——“函數依賴”、“碼”、“非主屬性”、與“部分函數依賴”進行一下解釋。

2.1 函數依賴

我們可以這麼了解(但并不是特别嚴格的定義):若在一張表中,在屬性(或屬性組)X的值确定的情況下,必定能确定屬性Y的值,那麼就可以說Y函數依賴于X,寫作 X → Y。也就是說,在資料表中,不存在任意兩條記錄,它們在X屬性(或屬性組)上的值相同,而在Y屬性上的值不同。這也就是“函數依賴”名字的由來,類似于函數關系 y = f(x),在x的值确定的情況下,y的值一定是确定的。

例如,對于表3中的資料,找不到任何一條記錄,它們的學号相同而對應的姓名不同。是以我們可以說姓名函數依賴于學号,寫作 學号 → 姓名。但是反過來,因為可能出現同名的學生,是以有可能不同的兩條學生記錄,它們在姓名上的值相同,但對應的學号不同,是以我們不能說學号函數依賴于姓名。表中其他的函數依賴關系還有如:

系名 → 系主任學号 → 系主任

(學号,課名) → 分數

但以下函數依賴關系則不成立:

學号 → 課名

學号 → 分數

課名 → 系主任

(學号,課名) → 姓名

從“函數依賴”這個概念展開,還會有三個概念:

2.1.1完全函數依賴

在一張表中,若 X → Y,且對于 X 的任何一個真子集(假如屬性組 X 包含超過一個屬性的話),X ’ → Y 不成立,那麼我們稱 Y 對于 X 完全函數依賴,記作 X F→ Y。(那個F應該寫在箭頭的正上方,沒辦法打出來……,正确的寫法如圖1)

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

圖1

例如: 學号 F→ 姓名 (學号,課名) F→ 分數 (注:因為同一個的學号對應的分數不确定,同一個課名對應的分數也不确定)

2.1.2 部分函數依賴

假如 Y 函數依賴于 X,但同時 Y 并不完全函數依賴于 X,那麼我們就稱 Y 部分函數依賴于 X,記作 X P→ Y,如圖2。

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

圖2

例如:(學号,課名) P→ 姓名 傳遞函數依賴假如 Z 函數依賴于 Y,且 Y 函數依賴于 X (感謝 @百達 指出的錯誤,這裡改為:『Y 不包含于 X,且 X 不函數依賴于 Y』這個前提),那麼我們就稱 Z 傳遞函數依賴于 X ,記作 X T→ Z,如圖3。

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

圖3

2.2 碼

設 K 為某表中的一個屬性或屬性組,若除 K 之外的所有屬性都完全函數依賴于 K(這個“完全”不要漏了),那麼我們稱 K 為候選碼,簡稱為碼。在實際中我們通常可以了解為:假如當 K 确定的情況下,該表除 K 之外的所有屬性的值也就随之确定,那麼 K 就是碼。一張表中可以有超過一個碼。(實際應用中為了友善,通常選擇其中的一個碼作為主碼) 例如:對于表3,(學号、課名)這個屬性組就是碼。該表中有且僅有這一個碼。(假設所有課沒有重名的情況)

2.3 非主屬性

包含在任何一個碼中的屬性成為主屬性。

例如:

對于表3,主屬性就有兩個,學号 與 課名。

終于可以回過來看2NF了。首先,我們需要判斷,表3是否符合2NF的要求?根據2NF的定義,判斷的依據實際上就是看資料表中是否存在非主屬性對于碼的部分函數依賴。若存在,則資料表最高隻符合1NF的要求,若不存在,則符合2NF的要求。判斷的方法是:

第一步:找出資料表中所有的碼。

第二步:根據第一步所得到的碼,找出所有的主屬性。

第三步:資料表中,除去所有的主屬性,剩下的就都是非主屬性了。

第四步:檢視是否存在非主屬性對碼的部分函數依賴。

對于表3,根據前面所說的四步,我們可以這麼做:

第一步:

  1. 檢視所有每一單個屬性,當它的值确定了,是否剩下的所有屬性值都能确定。
  2. 檢視所有包含有兩個屬性的屬性組,當它的值确定了,是否剩下的所有屬性值都能确定。
  3. ……
  4. 檢視所有包含了六個屬性,也就是所有屬性的屬性組,當它的值确定了,是否剩下的所有屬性值都能确定。

看起來很麻煩是吧,但是這裡有一個訣竅,就是假如A是碼,那麼所有包含了A的屬性組,如(A,B)、(A,C)、(A,B,C)等等,都不是碼了(因為作為碼的要求裡有一個“完全函數依賴”)。

圖4表示了表中所有的函數依賴關系:

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

圖4

這一步完成以後,可以得到,表3的碼隻有一個,就是 (學号、課名) 。

第二步:主屬性有兩個:學号 與 課名

第三步:非主屬性有四個:姓名、系名、系主任、分數

第四步:

對于(學号,課名) → 姓名,有 學号 → 姓名,存在非主屬性 姓名 對碼(學号,課名)的部分函數依賴。

對于(學号,課名) → 系名,有 學号 → 系名,存在非主屬性 系名 對碼(學号,課名)的部分函數依賴。

對于(學号,課名) → 系主任,有 學号 → 系主任,存在非主屬性 對碼(學号,課名)的部分函數依賴。

是以表3存在非主屬性對于碼的部分函數依賴,最高隻符合1NF的要求,不符合2NF的要求。

為了讓表3符合2NF的要求,我們必須消除這些部分函數依賴,隻有一個辦法,就是将大資料表拆分成兩個或者更多個更小的資料表,在拆分的過程中,要達到更高一級範式的要求,這個過程叫做”模式分解“。模式分解的方法不是唯一的,以下是其中一種方法:

選課(學号,課名,分數)

學生(學号,姓名,系名,系主任)

我們先來判斷以下,選課表與學生表,是否符合了2NF的要求?

對于選課表,其碼是(學号,課名),主屬性是學号和課名,非主屬性是分數,學号确定,并不能唯一确定分數,課名确定,也不能唯一确定分數,是以不存在非主屬性分數對于碼 (學号,課名)的部分函數依賴,是以此表符合2NF的要求。

對于學生表,其碼是學号,主屬性是學号,非主屬性是姓名、系名和系主任,因為碼隻有一個屬性,是以不可能存在非主屬性對于碼 的部分函數依賴,是以此表符合2NF的要求。

圖5表示了模式分解以後的新的函數依賴關系

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

圖5

表4表示了模式分解以後新的資料

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

表4

(這裡還涉及到一個如何進行模式分解才是正确的知識點,先不介紹了)

現在我們來看一下,進行同樣的操作,是否還存在着之前的那些問題?

  1. 李小明轉系到法律系

    隻需要修改一次李小明對應的系的值即可。——有改進

  2. 資料備援是否減少了?

    學生的姓名、系名與系主任,不再像之前一樣重複那麼多次了。——有改進

  3. 删除某個系中所有的學生記錄

    該系的資訊仍然全部丢失。——無改進

  4. 插入一個尚無學生的新系的資訊。

    因為學生表的碼是學号,不能為空,是以此操作不被允許。——無改進

是以說,僅僅符合2NF的要求,很多情況下還是不夠的,而出現問題的原因,在于仍然存在非主屬性系主任對于碼學号的傳遞函數依賴。為了能進一步解決這些問題,我們還需要将符合2NF要求的資料表改進為符合3NF的要求。

3. 第三範式(3NF)

3NF在2NF的基礎之上,消除了非主屬性對于碼的傳遞函數依賴。也就是說, 如果存在非主屬性對于碼的傳遞函數依賴,則不符合3NF的要求。

接下來我們看看表4中的設計,是否符合3NF的要求。

對于選課表,主碼為(學号,課名),主屬性為學号和課名,非主屬性隻有一個,為分數,不可能存在傳遞函數依賴,是以選課表的設計,符合3NF的要求。

對于學生表,主碼為學号,主屬性為學号,非主屬性為姓名、系名和系主任。因為 學号 → 系名,同時 系名 → 系主任,是以存在非主屬性系主任對于碼學号的傳遞函數依賴,是以學生表的設計,不符合3NF的要求。

為了讓資料表設計達到3NF,我們必須進一步進行模式分解為以下形式:

選課(學号,課名,分數)

學生(學号,姓名,系名)

系(系名,系主任)

對于選課表,符合3NF的要求,之前已經分析過了。

對于學生表,碼為學号,主屬性為學号,非主屬性為系名,不可能存在非主屬性對于碼的傳遞函數依賴,是以符合3NF的要求。

對于系表,碼為系名,主屬性為系名,非主屬性為系主任,不可能存在非主屬性對于碼的傳遞函數依賴(至少要有三個屬性才可能存在傳遞函數依賴關系),是以符合3NF的要求。。

新的函數依賴關系如圖6

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

圖6

新的資料表如表5

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

表5

現在我們來看一下,進行同樣的操作,是否還存在着之前的那些問題?

  1. 删除某個系中所有的學生記錄

    該系的資訊不會丢失。——有改進

  2. 插入一個尚無學生的新系的資訊。

    因為系表與學生表目前是獨立的兩張表,是以不影響。——有改進

  3. 資料備援更加少了。——有改進

結論

由此可見,符合3NF要求的資料庫設計,基本上解決了資料備援過大,插入異常,修改異常,删除異常的問題。當然,在實際中,往往為了性能上或者應對擴充的需要,經常 做到2NF或者1NF,但是作為資料庫設計人員,至少應該知道,3NF的要求是怎樣的。

==============時隔半年,終于決定把這個坑填上,來晚了 ===========

BCNF範式

要了解 BCNF 範式,那麼先看這樣一個問題:

若:

某公司有若幹個倉庫;每個倉庫隻能有一名管理者,一名管理者隻能在一個倉庫中工作;

一個倉庫中可以存放多種物品,一種物品也可以存放在不同的倉庫中。每種物品在每個倉庫中都有對應的數量。

那麼關系模式 倉庫(倉庫名,管理者,物品名,數量) 屬于哪一級範式?

答:已知函數依賴集:倉庫名 → 管理者,管理者 → 倉庫名,(倉庫名,物品名)→ 數量

碼:(管理者,物品名),(倉庫名,物品名)

主屬性:倉庫名、管理者、物品名非主屬性:數量

∵ 不存在非主屬性對碼的部分函數依賴和傳遞函數依賴。

∴ 此關系模式屬于3NF。

基于此關系模式的關系(具體的資料)可能如圖所示:

詳解第一範式、第二範式、第三範式、BCNF範式詳解第一範式、第二範式、第三範式、BCNF範式(轉載自WencoChen)什麼是”範式(NF)”1. 第一範式(1NF)2. 第二範式(2NF)3. 第三範式(3NF)4. 小結

好,既然此關系模式已經屬于了 3NF,那麼這個關系模式是否存在問題呢?我們來看以下幾種操作:

先新增加一個倉庫,但尚未存放任何物品,是否可以為該倉庫指派管理者?——不可以,因為物品名也是主屬性,根據實體完整性的要求,主屬性不能為空。

某倉庫被清空後,需要删除所有與這個倉庫相關的物品存放記錄,會帶來什麼問題?——倉庫本身與管理者的資訊也被随之删除了。

如果某倉庫更換了管理者,會帶來什麼問題?——這個倉庫有幾條物品存放記錄,就要修改多少次管理者資訊。

從這裡我們可以得出結論,在某些特殊情況下,即使關系模式符合 3NF 的要求,仍然存在着插入異常,修改異常與删除異常的問題,仍然不是 ”好“ 的設計。

造成此問題的原因:存在着主屬性對于碼的部分函數依賴與傳遞函數依賴。(在此例中就是存在主屬性【倉庫名】對于碼【(管理者,物品名)】的部分函數依賴。

解決辦法就是要在 3NF 的基礎上消除主屬性對于碼的部分與傳遞函數依賴。

倉庫(倉庫名,管理者)

庫存(倉庫名,物品名,數量)

這樣,之前的插入異常,修改異常與删除異常的問題就被解決了。

以上就是關于 BCNF 的解釋。

問:關于碼的定義,如果除K之外的所有屬性都完全函數依賴于K時才能稱K為碼,那麼在判斷2NF時又怎麼會存在非主屬性對碼的部分函數依賴這種情況?

答 :在“碼”的定義中,除 K 之外的所有屬性應該看成是一個集合 U(也就是一個整體),也就是說,隻有 K 能夠完全函數決定 U 中的每一個屬性,那麼 K 才是碼。如果 K 隻是能夠完全函數決定 U 中的一部分屬性,而不能完全函數決定另外一部分屬性,那麼 K 不是碼。

比如有關系模式 R (Sno, Sname, Cno, Cname, Sdept, Sloc, Grade),其中函數依賴集為 F= {Sno → Sname, Sno → Sdept, Sdept → Sloc,Sno → Sloc, Cno → Cname, (Sno, Cno) → Grade }

那麼 R 中的碼隻能是 (Sno, Cno),Sno 或 Cno 并不能完全函數決定除 Sno / Cno 之外的所有其他屬性(其實就是不能決定 Grade ),是以單獨的 Sno 與 Cno 并不能作為碼。

是以可得到主屬性:Sno, Cno

非主屬性:Sname, Cname, Sdept, Sloc, Grade

R 中存在非主屬性 Cname 對于碼 (Sno, Cno) 的部分函數依賴 (Cno → Cname) 。(還有很多别的例子就不一一列舉了)。是以 R 不符合 2NF 的要求。

4. 小結

搬運工覺得這個講解對于初步學習的人比較好。

資料庫範式那些事

總結:

1NF: 字段是最小的的單元不可再分

2NF:滿足1NF,表中的字段必須完全依賴于全部主鍵而非部分主鍵 (一般我們都會做到)

3NF:滿足2NF,非主鍵外的所有字段必須互不依賴4NF:滿足3NF,消除表中的多值依賴

搬運自知乎如何解釋關系資料庫的第一第二第三範式?

摘選劉慰、胡永浩的回答