ER 圖與三階正規化 — HKDSE ICT 免費筆記
數據庫設計題目出現在 每一份 HKDSE ICT Paper 2 — 有時是 ER 圖繪畫(從情景描述繪圖),有時是正規化問題(找出違規並修正)。這份速查表涵蓋選修部的核心:ER 模型設計、關聯式鍵值,以及正規化階梯至 3NF。
如果你能找出以下所有正規化違規,並能從文字題繪畫 ER 圖,你已經為數據庫選修部做好準備。
本主題涵蓋範圍(2A 選修部 + 必修部重疊)
數據庫選修部(2A)建基於必修部的數據庫基礎。在必修部,你學習什麼是數據庫和基本 SQL。在選修部,你學習如何正確設計數據庫 — 先做 ER 模型設計,再做正規化以消除冗餘。
選修部專屬主題:ER 圖(Chen 符號)、關係基數(1:1、1:M、M:N)、參與度、正規化至 3NF、函數依賴。
必修部重疊:主鍵、外鍵、基本表格概念同時出現在必修部和選修部。選修部更深入探討為什麼鍵值重要,以及如何選擇它們。
ER 模型設計
**實體關係圖(ER 圖)**是數據庫的藍圖。你先繪製 ER 圖,然後才建立表格。將其視為地圖,顯示你需要什麼數據,以及事物如何連接。
核心組件
| 組件 | 符號 | 含義 |
|---|---|---|
| 實體(Entity) | 長方形 | 一個物件或事物(Student、Course、Teacher) |
| 屬性(Attribute) | 橢圓 | 實體的屬性(Name、Age、StudentID) |
| 關係(Relationship) | 菱形 | 實體如何連接(enrolls in、teaches) |
屬性類型(考試出現時)
- 簡單屬性(橢圓):原子性、不可分割(Name、Age)
- 複合屬性(大橢圓帶連接小橢圓):由多部分組成(Address → Street、City、Postcode)
- 多重值屬性(雙橢圓):可有多個值(Phone numbers)
- 衍生屬性(虛線橢圓):從其他屬性計算而來(Age 由 DateOfBirth 計算)
關係基數(Chen 符號)
1:1(一對一):A 的一個實體關聯 B 的一個實體。
範例:Person ↔ Passport。每人有一本護照;每本護照屬於一人。
Person ─────── Passport
1:1
1:M(一對多):A 的一個實體關聯 B 的多個實體。
範例:Teacher → Students。一位老師教導多個學生;每個學生有一位老師。
Teacher ─────── Student
1:M
M:N(多對多):A 的多個實體關聯 B 的多個實體。
範例:Student ↔ Course。每個學生修讀多個科目;每個科目有多個學生。
Student ─────── Course
M:N
關鍵模式:M:N 關係無法直接儲存在關聯式數據庫中。你必須將它們轉換為連接表(intersection relation)。下文詳述。
參與度
完全參與(雙線):每個實體必須參與該關係。
範例:在 Employee ──<dep>── Dependent,每個 Dependent 必須關聯到一個 Employee。受養人不能獨立存在。
Employee ═══════ Dependent
(total)
部分參與(單線):參與是可選的。
範例:在 Teacher ──<teaches>── Subject,老師可能未教授任何科目(新聘)。科目可能未分配老師。
Teacher ────── Subject
(partial)
將 M:N 轉換為連接表
當你的 ER 圖有 M:N 關係時,你建立一個連接表(intersection relation),包含兩個外鍵。
範例:Student ↔ Course(M:N)轉換為:
Student(StudentID PK, Name, Age)
Course(CourseID PK, CourseName, Credits)
Enrollment(StudentID FK, CourseID FK, PRIMARY KEY(StudentID, CourseID), Grade)
Enrollment 表記錄哪個學生修讀哪個科目,並可儲存關係專屬數據(Grade、Semester)。
關聯式數據庫的鍵值
鍵值是表格如何連接,以及行如何保持唯一。
鍵值類型(附範例)
| 鍵值類型 | 定義 | 範例 |
|---|---|---|
| 超鍵(Superkey) | 任何能唯一識別行的屬性集 | {StudentID}、{StudentID, Name}、{HKID, Email} |
| 候選鍵(Candidate key) | 最小超鍵(無子集也是鍵) | {StudentID}、{HKID}(兩者皆最小) |
| 主鍵(Primary key) | 你選擇的候選鍵 | StudentID(因簡潔而選) |
| 交替鍵(Alternate key) | 未被選為主鍵的候選鍵 | HKID(有效但未被選) |
| 外鍵(Foreign key) | 參照另一表的主鍵 | ClassID in Student → Class(ClassID) |
| 複合鍵(Composite key) | 多個屬性共同組成鍵 | (StudentID, CourseID) in Enrollment |
學生—科目綱要範例
以下是展示所有鍵值類型的經典範例:
Student(StudentID PK, HKID, Name, Age, ClassID FK)
Course(CourseID PK, CourseName, Credits, TeacherID FK)
Enrollment(StudentID FK, CourseID FK, Grade, PRIMARY KEY(StudentID, CourseID))
鍵值分析:
StudentID是 Student 的主鍵;HKID是候選鍵(唯一但未被選)CourseID是 Course 的主鍵(StudentID, CourseID)是 Enrollment 的複合主鍵ClassIDin Student 是外鍵,參照 ClassTeacherIDin Course 是外鍵,參照 Teacher
為什麼 Enrollment 用複合主鍵?:每個學生只能修讀每個科目一次。(StudentID, CourseID) 唯一識別每個選課記錄。
正規化階梯:1NF → 2NF → 3NF
正規化消除冗餘(重複儲存相同數據)和異常(更新、插入、刪除問題)。你逐步轉換表格,直到每個表格滿足嚴格定義。
定義
第一正規式(1NF):每個屬性包含**原子性(不可分割)**值。無重複組、無多重值儲存格。
第二正規式(2NF):在 1NF + 無部分依賴(非鍵屬性必須依賴複合主鍵的所有部分,而非僅部分)。
第三正規式(3NF):在 2NF + 無傳遞依賴(非鍵屬性必須直接依賴主鍵,非透過其他非鍵屬性)。
連續範例:學生科目選課
讓我們從一個設計不良的表格開始,逐步修正。
正規化前(違反 1NF、2NF 和 3NF):
StudentCourses(StudentID, StudentName, Class, CourseID, CourseName, Credits, Teacher, TeacherRoom)
樣本數據:
| StudentID | StudentName | Class | CourseID | CourseName | Credits | Teacher | TeacherRoom |
|---|---|---|---|---|---|---|---|
| 001 | Alice | 5A | CS101 | Comp Studies | 5 | Mr. Lee | R101 |
| 001 | Alice | 5A | MATH201 | Algebra | 5 | Ms. Chan | R205 |
| 002 | Bob | 5B | CS101 | Comp Studies | 5 | Mr. Lee | R101 |
| 003 | Carol | 5A | PHYS301 | Physics | 5 | Mr. Wang | R310 |
有什麼問題:
- StudentName 和 Class 對每個學生修讀的科目重複 → 冗餘
- CourseName、Credits、Teacher、TeacherRoom 在修讀同一科目的學生間重複 → 更多冗餘
- 若李老師更換教室,必須更新所有包含他科目的行 → 更新異常
- 若刪除 CS101 的最後一個學生,我們會失去科目資訊 → 刪除異常
階段 1:1NF(修正原子值)
我們的表格已符合 1NF(每個儲存格儲存一個值)。但讓我們展示一個違規:
1NF 違規範例:
StudentCourses(StudentID, StudentName, Courses)
其中 Courses 包含「CS101, MATH201, PHYS301」 — 非原子值。
修正至 1NF:拆分為獨立行:
StudentCourses(StudentID, StudentName, CourseID)
現在各科目為獨立行。我們的原始表格已在 1NF。
階段 2:2NF(修正部分依賴)
定義:無非鍵屬性僅依賴複合主鍵的部分。
我們的主鍵是 (StudentID, CourseID)。檢查依賴:
StudentName僅依賴StudentID(部分依賴!)Class僅依賴StudentID(部分依賴!)CourseName僅依賴CourseID(部分依賴!)Credits僅依賴CourseID(部分依賴!)Teacher僅依賴CourseID(部分依賴!)TeacherRoom僅依賴CourseID(部分依賴!)
除 (StudentID, CourseID) 外,所有屬性都有部分依賴 → 違反 2NF。
修正至 2NF:拆分為三個表格(分離學生數據、科目數據、選課):
Student(StudentID PK, StudentName, Class)
Course(CourseID PK, CourseName, Credits, Teacher, TeacherRoom)
Enrollment(StudentID FK, CourseID FK, PRIMARY KEY(StudentID, CourseID))
2NF 後的樣本數據:
Student:
| StudentID | StudentName | Class |
|-----------|-------------|-------|
| 001 | Alice | 5A |
| 002 | Bob | 5B |
| 003 | Carol | 5A |
Course:
| CourseID | CourseName | Credits | Teacher | TeacherRoom |
|----------|--------------|---------|----------|-------------|
| CS101 | Comp Studies | 5 | Mr. Lee | R101 |
| MATH201 | Algebra | 5 | Ms. Chan | R205 |
| PHYS301 | Physics | 5 | Mr. Wang | R310 |
Enrollment:
| StudentID | CourseID |
|-----------|----------|
| 001 | CS101 |
| 001 | MATH201 |
| 002 | CS101 |
| 003 | PHYS301 |
改進:學生資訊現在儲存一次;科目資訊儲存一次。但我們仍有問題…
階段 3:3NF(修正傳遞依賴)
定義:無非鍵屬性依賴另一非鍵屬性。
檢查 Course 表:
主鍵是 CourseID。依賴:
CourseName依賴CourseID✓(直接依賴主鍵)Credits依賴CourseID✓(直接依賴主鍵)Teacher依賴CourseID✓(直接依賴主鍵)TeacherRoom依賴Teacher→ 傳遞依賴!違反 3NF
為何是傳遞?:TeacherRoom 依賴 Teacher,而非直接依賴 CourseID。若科目更換老師,教室可能也會改變。
修正至 3NF:將 Course 拆分為兩個表格:
Course(CourseID PK, CourseName, Credits, TeacherID FK)
Teacher(TeacherID PK, TeacherName, TeacherRoom)
等等 — 若我們想在 Enrollment 儲存成績,也要修正它。讓我們重做完整的 3NF 綱要:
Student(StudentID PK, StudentName, ClassID FK)
Class(ClassID PK, ClassName)
Course(CourseID PK, CourseName, Credits, TeacherID FK)
Teacher(TeacherID PK, TeacherName, TeacherRoom)
Enrollment(StudentID FK, CourseID FK, Grade, PRIMARY KEY(StudentID, CourseID))
3NF 後的樣本數據:
Student:
| StudentID | StudentName | ClassID |
|-----------|-------------|---------|
| 001 | Alice | 5A |
| 002 | Bob | 5B |
| 003 | Carol | 5A |
Class:
| ClassID | ClassName |
|---------|-----------|
| 5A | 5A |
| 5B | 5B |
Course:
| CourseID | CourseName | Credits | TeacherID |
|----------|--------------|---------|------------|
| CS101 | Comp Studies | 5 | T001 |
| MATH201 | Algebra | 5 | T002 |
| PHYS301 | Physics | 5 | T003 |
Teacher:
| TeacherID | TeacherName | TeacherRoom |
|-----------|-------------|-------------|
| T001 | Mr. Lee | R101 |
| T002 | Ms. Chan | R205 |
| T003 | Mr. Wang | R310 |
Enrollment:
| StudentID | CourseID | Grade |
|-----------|----------|-------|
| 001 | CS101 | A |
| 001 | MATH201 | B |
| 002 | CS101 | C |
| 003 | PHYS301 | A |
優點:
- 零冗餘:每個事實儲存一次
- 無更新異常:更改李老師的教室只需更新一行
- 無插入異常:可在分配科目前新增老師
- 無刪除異常:刪除 CS101 的所有學生不會失去科目資訊
試題常見模式(歷屆試題出現)
模式 1:從情景描述繪製 ER 圖
題目風格:「為學校系統繪製 ER 圖,包含學生、老師和科目。學生修讀多個科目;老師教授多個科目。」
方法:
- 識別實體(名詞):Student、Teacher、Course
- 識別關係(動詞):enrolls in(Student-Course,M:N)、teaches(Teacher-Course,1:M)
- 決定基數:一位老師教授多個科目;一個學生修讀多個科目
- 加入屬性:StudentID(主鍵)、Name;CourseID(主鍵)、CourseName;TeacherID(主鍵)、Name
- 顯示參與度:學生能否在無科目下存在?(部分)科目能否在無學生下存在?(部分)
答案草圖:
Student ─────── Enrollment ─────── Course
M:N M:N
Teacher ─────── Course
1:M
模式 2:找出正規化違規
題目風格:「此表格在 1NF 但非 2NF。解釋原因並修正。」
OrderItem(OrderID, ProductID, ProductName, Quantity, UnitPrice)
分析:
- 主鍵是
(OrderID, ProductID) ProductName僅依賴ProductID(部分依賴)UnitPrice僅依賴ProductID(部分依賴)- 違反 2NF
修正:
OrderItem(OrderID FK, ProductID FK, Quantity, PRIMARY KEY(OrderID, ProductID))
Product(ProductID PK, ProductName, UnitPrice)
模式 3:轉換至 3NF
題目風格:「將此表格轉換為 3NF。解釋每個步驟。」
StudentReport(StudentID, Name, Class, Teacher, Room, Subject, Grade)
方法:
- 檢查 1NF:所有值是否為原子性?是。
- 檢查 2NF:主鍵 =
(StudentID, Subject)。Name是否依賴兩者?否 → 部分依賴。拆分:Student(StudentID PK, Name, Class) Report(StudentID FK, Subject FK, Grade, Teacher, Room) - 檢查 3NF:在
Report,Room依賴Teacher(傳遞)。拆分:Teacher(TeacherID PK, TeacherName, Room) Subject(SubjectID PK, SubjectName) Report(StudentID FK, SubjectID FK, TeacherID FK, Grade)
自我檢測題
測試自己。答案在下方可折疊區域。
- ER 圖:為圖書館系統繪製 ER 圖,包含 Books、Members 和 Loans。會員可借閱多本書;書籍可被多個會員在不同時間借閱。顯示基數和參與度。
- 正規化:此表格在 1NF 但違反 2NF。解釋原因並轉換為 2NF:
Enrollment(StudentID, StudentName, CourseID, CourseName, Grade) - 傳遞依賴:此表格在 2NF 但違反 3NF。解釋原因並轉換為 3NF:
Product(ProductID, ProductName, SupplierName, SupplierCity, Price) - 綱要設計:將以下情景轉換為 3NF 綱要:「學校有由 StudentID 識別的學生。每個學生有姓名和屬於一個班別。每個班別有 ClassCode 和一位班主任。學生修讀科目;每個科目有 SubjectCode 並由一位老師教授。老師由 TeacherID 識別,有姓名和辦公室。」
點擊查看答案
-
ER 圖(圖書館):
- 實體:Book(BookID 主鍵、Title、Author)、Member(MemberID 主鍵、Name、Address)、Loan(LoanID 主鍵、LoanDate、ReturnDate)
- 關係:Member 借閱 Book(M:N)、Loan 連接 Member 和 Book
- 基數:一個會員可借閱多本書(一本書可被多個會員在不同時間借閱)→ M:N
- 參與度:部分(會員可在未借書下存在;書籍可在未被借閱下存在)
- 圖草圖:
Member ─────── Loan ─────── Book M:N M:N
-
2NF 轉換:
- 主鍵是
(StudentID, CourseID) StudentName僅依賴StudentID(部分依賴)CourseName僅依賴CourseID(部分依賴)- 違反 2NF,因為非鍵屬性依賴複合主鍵的部分
- 修正至 2NF:
Student(StudentID PK, StudentName) Course(CourseID PK, CourseName) Enrollment(StudentID FK, CourseID FK, Grade, PRIMARY KEY(StudentID, CourseID))
- 主鍵是
-
3NF 轉換:
- 主鍵是
ProductID(單一屬性,故無部分依賴 — 已在 2NF) SupplierCity依賴SupplierName(傳遞依賴:ProductID → SupplierName → SupplierCity)- 違反 3NF,因為非鍵屬性依賴另一非鍵屬性
- 修正至 3NF:
Product(ProductID PK, ProductName, SupplierID FK, Price) Supplier(SupplierID PK, SupplierName, SupplierCity)
- 主鍵是
-
3NF 綱要(學校情景):
Student(StudentID PK, StudentName, ClassID FK) Class(ClassID PK, ClassCode, TeacherID FK) Teacher(TeacherID PK, TeacherName, OfficeRoom) Subject(SubjectID PK, SubjectCode, TeacherID FK) Enrollment(StudentID FK, SubjectID FK, Grade, PRIMARY KEY(StudentID, SubjectID))外鍵:
Student.ClassID → Class.ClassID、Class.TeacherID → Teacher.TeacherID、Subject.TeacherID → Teacher.TeacherID、Enrollment.StudentID → Student.StudentID、Enrollment.SubjectID → Subject.SubjectID
想要完整筆記和更多練習?
這是我們 HKDSE ICT 數據庫選修部筆記的樣本。完整套覆蓋從頭繪製 ER 圖、歷屆試題所有正規化模式,以及進階 SQL 連接查詢。
探索我們的完整 HKDSE ICT 筆記 — 為復習而結構化,為應考日而優化。
需要個人回饋?預約試堂 — 我們會審閱你的 ER 圖、修正你的正規化邏輯,並為你建立針對性學習計劃。