数据库一二三范式
?
?
原文知乎:https://www.zhihu.com/question/24696366
首先要明白”范式(NF)”是什么意思。按照教材中的定義,范式是“符合某一種級(jí)別的關(guān)系模式的集合,表示一個(gè)關(guān)系內(nèi)部各屬性之間的聯(lián)系的合理化程度”。很晦澀吧?實(shí)際上你可以把它粗略地理解為一張數(shù)據(jù)表的表結(jié)構(gòu)所符合的某種設(shè)計(jì)標(biāo)準(zhǔn)的級(jí)別。就像家里裝修買建材,最環(huán)保的是E0級(jí),其次是E1級(jí),還有E2級(jí)等等。數(shù)據(jù)庫范式也分為1NF,2NF,3NF,BCNF,4NF,5NF。一般在我們?cè)O(shè)計(jì)關(guān)系型數(shù)據(jù)庫的時(shí)候,最多考慮到BCNF就夠。符合高一級(jí)范式的設(shè)計(jì),必定符合低一級(jí)范式,例如符合2NF的關(guān)系模式,必定符合1NF。
接下來就對(duì)每一級(jí)范式進(jìn)行一下解釋,首先是第一范式(1NF)。符合1NF的關(guān)系(你可以理解為數(shù)據(jù)表?!瓣P(guān)系”和“關(guān)系模式”的區(qū)別,類似于面向?qū)ο蟪绦蛟O(shè)計(jì)中”類“與”對(duì)象“的區(qū)別。”關(guān)系“是”關(guān)系模式“的一個(gè)實(shí)例,你可以把”關(guān)系”理解為一張帶數(shù)據(jù)的表,而“關(guān)系模式”是這張數(shù)據(jù)表的表結(jié)構(gòu)。1NF的定義為:符合1NF的關(guān)系中的每個(gè)屬性都不可再分。表1所示的情況,就不符合1NF的要求。
表一
實(shí)際上,1NF是所有關(guān)系型數(shù)據(jù)庫的最基本要求,你在關(guān)系型數(shù)據(jù)庫管理系統(tǒng)(RDBMS),例如SQL Server,Oracle,MySQL中創(chuàng)建數(shù)據(jù)表的時(shí)候,如果數(shù)據(jù)表的設(shè)計(jì)不符合這個(gè)最基本的要求,那么操作一定是不能成功的。也就是說,只要在RDBMS中已經(jīng)存在的數(shù)據(jù)表,一定是符合1NF的。如果我們要在RDBMS中表現(xiàn)表中的數(shù)據(jù),就得設(shè)計(jì)為表2的形式: 表二 但是僅僅符合1NF的設(shè)計(jì),仍然會(huì)存在數(shù)據(jù)冗余過大,插入異常,刪除異常,修改異常的問題,例如對(duì)于表3中的設(shè)計(jì):表三
注1:根據(jù)三種關(guān)系完整性約束中實(shí)體完整性的要求,關(guān)系中的碼(注2)所包含的任意一個(gè)屬性都不能為空,所有屬性的組合也不能重復(fù)。為了滿足此要求,圖中的表,只能將學(xué)號(hào)與課名的組合作為碼,否則就無法唯一地區(qū)分每一條記錄。
注2:碼:關(guān)系中的某個(gè)屬性或者某幾個(gè)屬性的組合,用于區(qū)分每個(gè)元組(可以把“元組”理解為一張表中的每條記錄,也就是每一行)。
正因?yàn)閮H符合1NF的數(shù)據(jù)庫設(shè)計(jì)存在著這樣那樣的問題,我們需要提高設(shè)計(jì)標(biāo)準(zhǔn),去掉導(dǎo)致上述四種問題的因素,使其符合更高一級(jí)的范式(2NF),這就是所謂的“規(guī)范化”。
第二范式(2NF)在關(guān)系理論中的嚴(yán)格定義我這里就不多介紹了(因?yàn)樯婕暗降匿亯|比較多),只需要了解2NF對(duì)1NF進(jìn)行了哪些改進(jìn)即可。其改進(jìn)是,2NF在1NF的基礎(chǔ)之上,消除了非主屬性對(duì)于碼的部分函數(shù)依賴。接下來對(duì)這句話中涉及到的四個(gè)概念——“函數(shù)依賴”、“碼”、“非主屬性”、與“部分函數(shù)依賴”進(jìn)行一下解釋。
函數(shù)依賴
我們可以這么理解(但并不是特別嚴(yán)格的定義):若在一張表中,在屬性(或?qū)傩越M)X的值確定的情況下,必定能確定屬性Y的值,那么就可以說Y函數(shù)依賴于X,寫作 X → Y。也就是說,在數(shù)據(jù)表中,不存在任意兩條記錄,它們?cè)赬屬性(或?qū)傩越M)上的值相同,而在Y屬性上的值不同。這也就是“函數(shù)依賴”名字的由來,類似于函數(shù)關(guān)系 y = f(x),在x的值確定的情況下,y的值一定是確定的。
- 系名 → 系主任
- 學(xué)號(hào) → 系主任
- (學(xué)號(hào),課名) → 分?jǐn)?shù)
- 學(xué)號(hào) → 課名
- 學(xué)號(hào) → 分?jǐn)?shù)
- 課名 → 系主任
- (學(xué)號(hào),課名) → 姓名
完全函數(shù)依賴
在一張表中,若 X → Y,且對(duì)于 X 的任何一個(gè)真子集(假如屬性組 X 包含超過一個(gè)屬性的話),X ' → Y 不成立,那么我們稱 Y 對(duì)于 X 完全函數(shù)依賴,記作 X F→ Y。(正確的寫法如圖1)
圖1
例如:- 學(xué)號(hào) F→ 姓名
- (學(xué)號(hào),課名) F→ 分?jǐn)?shù) (注:因?yàn)橥粋€(gè)的學(xué)號(hào)對(duì)應(yīng)的分?jǐn)?shù)不確定,同一個(gè)課名對(duì)應(yīng)的分?jǐn)?shù)也不確定)
假如 Y 函數(shù)依賴于 X,但同時(shí) Y 并不完全函數(shù)依賴于 X,那么我們就稱 Y 部分函數(shù)依賴于 X,記作 X P→ Y,如圖2。
<img src="https://pic4.zhimg.com/10b52b39b18b8ea9fb17b46babf4d20f_b.jpg" data-rawwidth="99" data-rawheight="62" class="content_image" width="99">
圖2
例如:
- (學(xué)號(hào),課名) P→ 姓名
?
傳遞函數(shù)依賴
假如 Z 函數(shù)依賴于 Y,且 Y 函數(shù)依賴于 X (嚴(yán)格來說還有一個(gè)X 不包含于Y,且 Y 不函數(shù)依賴于Z的前提條件),那么我們就稱 Z 傳遞函數(shù)依賴于 X ,記作 X T→ Z,如圖3。
圖3
碼
設(shè) K 為某表中的一個(gè)屬性或?qū)傩越M,若除 K 之外的所有屬性都完全函數(shù)依賴于 K(這個(gè)“完全”不要漏了),那么我們稱 K 為候選碼,簡稱為碼。在實(shí)際中我們通??梢岳斫鉃?#xff1a;假如當(dāng) K 確定的情況下,該表除 K 之外的所有屬性的值也就隨之確定,那么 K 就是碼。一張表中可以有超過一個(gè)碼。(實(shí)際應(yīng)用中為了方便,通常選擇其中的一個(gè)碼作為主碼)
例如:
對(duì)于表3,(學(xué)號(hào)、課名)這個(gè)屬性組就是碼。該表中有且僅有這一個(gè)碼。(假設(shè)所有課沒有重名的情況)
非主屬性
包含在任何一個(gè)碼中的屬性成為主屬性。
例如:
對(duì)于表3,主屬性就有兩個(gè),學(xué)號(hào) 與 課名。
終于可以回過來看2NF了。首先,我們需要判斷,表3是否符合2NF的要求?根據(jù)2NF的定義,判斷的依據(jù)實(shí)際上就是看數(shù)據(jù)表中是否存在非主屬性對(duì)于碼的部分函數(shù)依賴。若存在,則數(shù)據(jù)表最高只符合1NF的要求,若不存在,則符合2NF的要求。判斷的方法是:
第一步:找出數(shù)據(jù)表中所有的碼。
第二步:根據(jù)第一步所得到的碼,找出所有的主屬性。
第三步:數(shù)據(jù)表中,除去所有的主屬性,剩下的就都是非主屬性了。
第四步:查看是否存在非主屬性對(duì)碼的部分函數(shù)依賴。
第一步:
看起來很麻煩是吧,但是這里有一個(gè)訣竅,就是假如A是碼,那么所有包含了A的屬性組,如(A,B)、(A,C)、(A,B,C)等等,都不是碼了(因?yàn)樽鳛榇a的要求里有一個(gè)“完全函數(shù)依賴”)。
圖4表示了表中所有的函數(shù)依賴關(guān)系:圖4
這一步完成以后,可以得到,表3的碼只有一個(gè),就是(學(xué)號(hào)、課名)。
第二步:
主屬性有兩個(gè):學(xué)號(hào) 與 課名
第三步:
非主屬性有四個(gè):姓名、系名、系主任、分?jǐn)?shù)
第四步:
對(duì)于(學(xué)號(hào),課名) → 姓名,有 學(xué)號(hào) → 姓名,存在非主屬性 姓名 對(duì)碼(學(xué)號(hào),課名)的部分函數(shù)依賴。
對(duì)于(學(xué)號(hào),課名) → 系名,有 學(xué)號(hào) → 系名,存在非主屬性 系名 對(duì)碼(學(xué)號(hào),課名)的部分函數(shù)依賴。
對(duì)于(學(xué)號(hào),課名) → 系主任,有 學(xué)號(hào) → 系主任,存在非主屬性 對(duì)碼(學(xué)號(hào),課名)的部分函數(shù)依賴。
所以表3存在非主屬性對(duì)于碼的部分函數(shù)依賴,最高只符合1NF的要求,不符合2NF的要求。
為了讓表3符合2NF的要求,我們必須消除這些部分函數(shù)依賴,只有一個(gè)辦法,就是將大數(shù)據(jù)表拆分成兩個(gè)或者更多個(gè)更小的數(shù)據(jù)表,在拆分的過程中,要達(dá)到更高一級(jí)范式的要求,這個(gè)過程叫做”模式分解“。模式分解的方法不是唯一的,以下是其中一種方法:
選課(學(xué)號(hào),課名,分?jǐn)?shù))
學(xué)生(學(xué)號(hào),姓名,系名,系主任)
我們先來判斷以下,選課表與學(xué)生表,是否符合了2NF的要求?
對(duì)于選課表,其碼是(學(xué)號(hào),課名),主屬性是學(xué)號(hào)和課名,非主屬性是分?jǐn)?shù),學(xué)號(hào)確定,并不能唯一確定分?jǐn)?shù),課名確定,也不能唯一確定分?jǐn)?shù),所以不存在非主屬性分?jǐn)?shù)對(duì)于碼 (學(xué)號(hào),課名)的部分函數(shù)依賴,所以此表符合2NF的要求。
對(duì)于學(xué)生表,其碼是學(xué)號(hào),主屬性是學(xué)號(hào),非主屬性是姓名、系名和系主任,因?yàn)榇a只有一個(gè)屬性,所以不可能存在非主屬性對(duì)于碼 的部分函數(shù)依賴,所以此表符合2NF的要求。
圖5表示了模式分解以后的新的函數(shù)依賴關(guān)系?
圖5
表4表示了模式分解以后新的數(shù)據(jù)
?
表4
(這里還涉及到一個(gè)如何進(jìn)行模式分解才是正確的知識(shí)點(diǎn),先不介紹了)
現(xiàn)在我們來看一下,進(jìn)行同樣的操作,是否還存在著之前的那些問題?只需要修改一次李小明對(duì)應(yīng)的系的值即可?!懈倪M(jìn)
學(xué)生的姓名、系名與系主任,不再像之前一樣重復(fù)那么多次了。——有改進(jìn)
該系的信息仍然全部丟失。——無改進(jìn)
因?yàn)閷W(xué)生表的碼是學(xué)號(hào),不能為空,所以此操作不被允許?!獰o改進(jìn)
所以說,僅僅符合2NF的要求,很多情況下還是不夠的,而出現(xiàn)問題的原因,在于仍然存在非主屬性系主任對(duì)于碼學(xué)號(hào)的傳遞函數(shù)依賴。為了能進(jìn)一步解決這些問題,我們還需要將符合2NF要求的數(shù)據(jù)表改進(jìn)為符合3NF的要求。
第三范式(3NF)
3NF在2NF的基礎(chǔ)之上,消除了非主屬性對(duì)于碼的傳遞函數(shù)依賴。也就是說, 如果存在非主屬性對(duì)于碼的傳遞函數(shù)依賴,則不符合3NF的要求。
接下來我們看看表4中的設(shè)計(jì),是否符合3NF的要求。
對(duì)于選課表,主碼為(學(xué)號(hào),課名),主屬性為學(xué)號(hào)和課名,非主屬性只有一個(gè),為分?jǐn)?shù),不可能存在傳遞函數(shù)依賴,所以選課表的設(shè)計(jì),符合3NF的要求。
對(duì)于學(xué)生表,主碼為學(xué)號(hào),主屬性為學(xué)號(hào),非主屬性為姓名、系名和系主任。因?yàn)?學(xué)號(hào) → 系名,同時(shí) 系名 → 系主任,所以存在非主屬性系主任對(duì)于碼學(xué)號(hào)的傳遞函數(shù)依賴,所以學(xué)生表的設(shè)計(jì),不符合3NF的要求。。
為了讓數(shù)據(jù)表設(shè)計(jì)達(dá)到3NF,我們必須進(jìn)一步進(jìn)行模式分解為以下形式:
選課(學(xué)號(hào),課名,分?jǐn)?shù))
學(xué)生(學(xué)號(hào),姓名,系名)
系(系名,系主任)
對(duì)于選課表,符合3NF的要求,之前已經(jīng)分析過了。
對(duì)于學(xué)生表,碼為學(xué)號(hào),主屬性為學(xué)號(hào),非主屬性為系名,不可能存在非主屬性對(duì)于碼的傳遞函數(shù)依賴,所以符合3NF的要求。
對(duì)于系表,碼為系名,主屬性為系名,非主屬性為系主任,不可能存在非主屬性對(duì)于碼的傳遞函數(shù)依賴(至少要有三個(gè)屬性才可能存在傳遞函數(shù)依賴關(guān)系),所以符合3NF的要求。。
新的函數(shù)依賴關(guān)系如圖6?
圖6
新的數(shù)據(jù)表如表5
?
圖5
現(xiàn)在我們來看一下,進(jìn)行同樣的操作,是否還存在著之前的那些問題?
該系的信息不會(huì)丟失?!懈倪M(jìn)
因?yàn)橄当砼c學(xué)生表目前是獨(dú)立的兩張表,所以不影響?!懈倪M(jìn)
結(jié)論
由此可見,符合3NF要求的數(shù)據(jù)庫設(shè)計(jì),基本上解決了數(shù)據(jù)冗余過大,插入異常,修改異常,刪除異常的問題。當(dāng)然,在實(shí)際中,往往為了性能上或者應(yīng)對(duì)擴(kuò)展的需要,經(jīng)常 做到2NF或者1NF,但是作為數(shù)據(jù)庫設(shè)計(jì)人員,至少應(yīng)該知道,3NF的要求是怎樣的。
要了解 BCNF 范式,那么先看這樣一個(gè)問題:
若:
那么關(guān)系模式 倉庫(倉庫名,管理員,物品名,數(shù)量) 屬于哪一級(jí)范式?
答:已知函數(shù)依賴集:倉庫名 → 管理員,管理員 → 倉庫名,(倉庫名,物品名)→ 數(shù)量
碼:(管理員,物品名),(倉庫名,物品名)
主屬性:倉庫名、管理員、物品名
非主屬性:數(shù)量
∵ 不存在非主屬性對(duì)碼的部分函數(shù)依賴和傳遞函數(shù)依賴。∴ 此關(guān)系模式屬于3NF。
從這里我們可以得出結(jié)論,在某些特殊情況下,即使關(guān)系模式符合 3NF 的要求,仍然存在著插入異常,修改異常與刪除異常的問題,仍然不是 ”好“ 的設(shè)計(jì)。
造成此問題的原因:存在著主屬性對(duì)于碼的部分函數(shù)依賴與傳遞函數(shù)依賴。(在此例中就是存在主屬性【倉庫名】對(duì)于碼【(管理員,物品名)】的部分函數(shù)依賴。
解決辦法就是要在 3NF 的基礎(chǔ)上消除主屬性對(duì)于碼的部分與傳遞函數(shù)依賴。
倉庫(倉庫名,管理員)
庫存(倉庫名,物品名,數(shù)量)
這樣,之前的插入異常,修改異常與刪除異常的問題就被解決了。
以上就是關(guān)于 BCNF 的解釋。
?
轉(zhuǎn)載于:https://www.cnblogs.com/hxphp/p/7001947.html
總結(jié)
- 上一篇: The working copy is
- 下一篇: Mysql定时执行任务实现方法