A3.1–A3.2 資料庫基礎與設計
資料庫基礎與設計(Database fundamentals and design)說明關聯式資料庫的基本元素、如何用實體關聯圖規劃資料表之間的關係,以及如何用正規化消除資料重複。本頁合併 A3.1 資料庫基礎與 A3.2 資料庫設計。
什麼是資料庫與 DBMS?
資料庫(database) 是有組織、可以有效查詢與更新的資料集合。資料庫管理系統(Database Management System, DBMS),例如 MySQL、PostgreSQL、SQLite,負責儲存資料、處理查詢、控制存取權限、備份與還原、讓多人同時使用。
關聯式資料庫(relational database) 把資料存成多張 資料表(table),表與表之間用鍵(key)建立關聯。
| 名詞 | 意義 | 例子 |
|---|---|---|
| 資料表(table/relation) | 同一類實體的資料 | Student 表 |
| 記錄(record/row/tuple) | 一筆實體資料 | 一位學生 |
| 欄位(field/column/attribute) | 實體的一個屬性 | name、birthDate |
| 主鍵(primary key) | 唯一識別每筆記錄的欄位,不可重複、不可為空 | studentID |
| 外鍵(foreign key) | 參照另一張表主鍵的欄位,用來建立關聯 | Enrollment.studentID |
| 複合鍵(composite key) | 由兩個以上欄位組成的主鍵 | (studentID, courseID) |
什麼是 ACID?
交易(transaction)是一組必須「全部成功或全部不做」的操作,例如轉帳的「扣款」與「入帳」。DBMS 用 ACID 保證交易可靠:
- Atomicity(原子性):交易中的操作全部完成,或全部取消。
- Consistency(一致性):交易前後資料都符合規則(例如餘額不可為負)。
- Isolation(隔離性):同時進行的交易互不干擾。
- Durability(持久性):交易確認後,即使斷電資料也不會遺失。
如何畫實體關聯圖(ERD)?
實體關聯圖(Entity–Relationship Diagram, ERD)描述資料庫中有哪些實體、以及實體之間的關係:
- 一對一(1:1):一位學生對應一個學生證。
- 一對多(1:M):一位老師教多個班級。
- 多對多(M:N):一位學生修多門課、一門課有多位學生。多對多在關聯式資料庫中必須拆成 兩個一對多,中間加一張連結表(junction table)。
erDiagram
STUDENT ||--o{ ENROLLMENT : has
COURSE ||--o{ ENROLLMENT : includes
TEACHER ||--o{ COURSE : teaches
STUDENT {
int studentID PK
string name
int grade
}
COURSE {
string courseID PK
string title
int teacherID FK
}
ENROLLMENT {
int studentID FK
string courseID FK
string score
}
TEACHER {
int teacherID PK
string name
}
如何正規化資料表?
正規化(normalisation)是逐步拆分資料表、消除重複與異常(anomaly)的過程。未正規化的表格容易出現:
- 新增異常:還沒有學生修某門課,就無法記錄這門課。
- 修改異常:老師改名,要改很多列,漏改就不一致。
- 刪除異常:刪掉最後一位修課學生,連課程資訊一起消失。
第一到第三正規化
以下表為例(未正規化):
| studentID | name | courses | teacher |
|---|---|---|---|
| 1 | Amy | CS, Math | Mr. Lee, Ms. Wu |
- 第一正規化(1NF):每個欄位只放 單一值(atomic),沒有重複欄位群組,並有主鍵。→ 把
courses拆成每列一門課,主鍵為 (studentID,courseID)。 - 第二正規化(2NF):符合 1NF,且所有非鍵欄位 完全依賴整個主鍵,沒有部分依賴。→
name只依賴studentID,移到Student表;課程資訊移到Course表。 - 第三正規化(3NF):符合 2NF,且 沒有遞移依賴(非鍵欄位不依賴其他非鍵欄位)。→ 若
Course表有teacherID與teacherName,teacherName依賴teacherID而非課程,移到Teacher表。
一句話記:每個非鍵欄位都要依賴「the key, the whole key, and nothing but the key」。
正規化有缺點嗎?
正規化減少重複、維護容易,但表越多,查詢時需要越多 JOIN,可能變慢。資料倉儲等以讀取為主的系統,有時會刻意 反正規化(denormalisation) 換取查詢速度(見 A3.4)。
資料型別與資料完整性
設計資料表時,要為每個欄位選擇適當的資料型別(例如 INTEGER、VARCHAR(50)、DATE、BOOLEAN、DECIMAL(8,2)),並用限制條件保護 資料完整性(data integrity):
NOT NULL:欄位不可為空。UNIQUE:值不可重複,例如 email。CHECK:值須符合條件,例如grade BETWEEN 9 AND 12。- 參照完整性(referential integrity):外鍵必須指向實際存在的主鍵。
推薦影音
實體關聯圖 ERD 教學
簡述:Lucid Software 示範如何辨認實體、屬性與關係,以及用烏鴉腳記號(crow's foot)表示一對多與多對多,對應本頁 ERD 一節。
資料庫正規化 1NF 到 5NF
簡述:Decomplexify 用清楚的例子一步步拆解每個正規化等級,說明每一步解決了哪種異常。IB 要求到 3NF,4NF、5NF 可當延伸。
練習題
練習 1:辨認鍵
Borrow(memberID, bookID, borrowDate, returnDate) 記錄圖書館借書。一位會員可以在不同日期借同一本書。這張表的主鍵應該是什麼?哪些是外鍵?
參考答案
主鍵為複合鍵 (memberID, bookID, borrowDate),因為同一會員可能多次借同一本書。外鍵為 memberID(參照 Member)與 bookID(參照 Book)。
練習 2:處理多對多
一位醫師可以看多位病患,一位病患也可以看多位醫師。如何在關聯式資料庫中表示?
參考答案
建立 Doctor(doctorID, ...)、Patient(patientID, ...),再加連結表 Appointment(appointmentID, doctorID, patientID, dateTime),把多對多拆成兩個一對多。
練習 3:正規化到 3NF
將下表正規化到 3NF:Order(orderID, customerID, customerName, productID, productName, quantity),一張訂單可包含多個商品。
參考答案
Customer(customerID, customerName);Product(productID, productName);Orders(orderID, customerID);OrderLine(orderID, productID, quantity),主鍵為 (orderID, productID)。
練習 4:ACID
線上購票時,系統扣了使用者的錢,但在寫入座位資料前當機。ACID 的哪一項能避免使用者白付錢?
參考答案
原子性(Atomicity)。扣款與劃位屬於同一筆交易,未全部完成就整筆回滾(rollback),扣款會被取消。