数据库原理学习笔记(二)数据库范式
范式可以理解成在設計數據表時的規范級別,常見的范式有
- 第一范式(1NF)
- 第二范式(2NF)
- 第三范式(3NF)
- BC范式(BCNF)
第一范式
要滿足第一范式,要求數據表的每個屬性無法再分,也就是需要滿足原子性。可以把“不可再分”理解成無法用一個單獨的值表示,比如說“系”這個屬性,平時常說的“計算機系”,“化學系”實際上指的是系名,而系的管理者被稱為系主任,所以對于“系”這個屬性,只能通過將它拆分成若干屬性的組合(系名,系主任,…)來表示。
所以如果數據表中某個屬性指的是類似上面的“系”這樣的屬性,就不滿足第一范式,解決辦法就是將這個可以再分的屬性繼續分解
CREATE TABLE student ( id INT NOT NULL AUTO_INCREMENT, /* 學號 */name VARCHAR(20) NOT NULL, /* 姓名 */faculty /* 系,應該用什么類型表示?它包括系名,系主任等若干子屬性 */... );可以看到,如果某個屬性可以繼續分解,那么是無法在創建數據表時表示它的,所以一般可以成功創建的數據表(前提是語義正確)都是符合第一范式的要求的
CREATE TABLE student ( student_id INT, student_name VARCHAR(20), faculty_name VARCHAR(20), faculty_boss VARCHAR(20), PRIMARY KEY (student_id) );第二范式
判斷一個數據表是否滿足第二范式,可以觀察是否存在非主屬性對于碼的部分函數依賴,方法是
- 找出數據表中所有的碼
- 根據第一步找出的碼,找出所有主屬性
- 在數據表中的所有屬性中去除主屬性,得到非主屬性
- 查看是否存在某個非主屬性對于碼的部分函數依賴
如果存在部分函數依賴,則這個數據表就不符合第二范式,解決方法就是模式分解,將違反第二范式的屬性單獨提出創建一個新表或者分解表使得該表的碼只包含一個屬性
對于部分函數依賴,碼至少要包含兩個屬性,所以上面的student表是滿足第二范式的,下面考慮另一個表student_course,它描述了學生的選課信息,包含
- 學生信息
- 課程名,課程成績
- 學生所在系信息
由于課程成績必須通過確定是哪個學生的哪門課來獲取,所以這個表的主碼(主鍵)是(student_id, course_name),現在來一步步分析這個表是否符合第二范式
分析student_course表
第一步,找出數據表中的所有的碼。由上面的分析可得這個表只有唯一的碼(student_id, course_name)
第二步,找出所有的主屬性。碼中的每個屬性都是主屬性,所以主屬性包括student_id和course_name
第三步,找出所有的非主屬性。除去主屬性的都是非主屬性,所以非主屬性包括student_name, course_score, faculty_name, faculty_boss
第四步,判斷非主屬性是否對于碼存在部分函數依賴
每個屬性之間的依賴關系
- student_id可以推導出student_name,所以student_name完全依賴于student_id
- student_id可以推導出faculty_name和faculty_boss,所以二者完全依賴于student_id
- (student_id, course_name)可以推導出course_score,所以course_score完全依賴于(student_id, course_name)
由上述三個關系可以分析出部分依賴關系
- 由于faculty_name完全函數依賴于student_id,所以faculty_name部分函數依賴于(student_id, course_name)
- 由于faculty_boss完全函數依賴于student_id,所以faculty_name部分函數依賴于(student_id, course_name)
- …
所以這個表不滿足第二范式,可以通過模式分解解決這一問題,比如將課程相關的信息提出去單獨作為一個表,這樣student_course表的碼就只剩一個屬性student_id了,自然不存在部分函數依賴
CREATE TABLE student ( student_id INT NOT NULL, student_name VARCHAR(20), faculty_name VARCHAR(20), faculty_boss VARCHAR(20) ,PRIMARY KEY (student_id) );CREATE TABLE course ( student_id INT NOT NULL, course_name VARCHAR(20), course_score INT, PRIMARY KEY(student_id, course_name) );第三范式
判斷一個數據表是否滿足第三范式,可以觀察是否存在非主屬性對于碼的傳遞函數依賴,解決方法也和第二范式相同,將導致不符合第三范式的那個屬性提出,單獨創建一個表
可以對上面的student和course表進行分析,判斷這兩個表是否滿足第三范式
分析course表
第一步,找出所有的碼。course的碼只有(student_id, course_name)
第二步,找出所有的主屬性。主屬性有student_id和course_name
第三步,找出所有的非主屬性。非主屬性有course_score
第四步,判斷是否存在非主屬性對于碼的傳遞函數依賴。因為傳遞函數依賴至少需要有兩個非主屬性,所以course表不存在對于碼的傳遞函數依賴
所以course表滿足第三范式
分析student表
第一步,找出所有的碼。student的碼只有(student_id)
第二步,找出所有的主屬性。主屬性為student_id
第三步,找出所有的非主屬性。非主屬性有student_name,faculty_name和faculty_boss
第四步,判斷是否存在非主屬性對于碼的傳遞函數依賴。從客觀事實的角度出發,如果知道系名,就可以知道系主任是誰,所以faculty_boss完全函數依賴于faculty_name。又因為faculty_name完全函數依賴于碼student_id,所以faculty_boss傳遞函數依賴于碼student_id
所以student表不滿足第三范式。
可以通過將系相關的信息提出去單獨創建一張表,比如
CREATE TABLE student ( student_id INT NOT NULL, student_name VARCHAR(20), faculty_name VARCHAR(20), PRIMARY KEY (student_id) );CREATE TABLE faculty ( faculty_name VARCHAR(20) NOT NULL, faculty_boss VARCHAR(20) NOT NULL, PRIMARY KEY (faculty_name) );BC范式
BC范式可以通過判斷是否存在主屬性對于碼的部分函數依賴。出現這種情況的原因通常是由于數據表中存在著多個碼。比如說(A,C)和(B,C)都是這個數據表的碼,同時B完全函數依賴于A,那么主屬性B就部分函數依賴于碼(A,C),可以通過繼續分解成兩個表分別是
- 表1,包含屬性A,B
- 表2,包含屬性A,C
解決
參考資料
解釋一下關系數據庫的第一第二第三范式? - 劉慰的回答 - 知乎 https://www.zhihu.com/question/24696366/answer/29189700
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的数据库原理学习笔记(二)数据库范式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库原理学习笔记(一)关系完整性以及数
- 下一篇: C++代码片段(五)tuple的实现