歡迎來到選修單元 A:資料庫!
嗨,未來的電腦科學家們!這個單元非常關鍵,因為資料庫是現代世界的隱形引擎。每當你登入社交媒體、查看成績或在網上購物時,你其實都在與複雜的資料庫系統進行互動。
在本章中,我們將跨越簡單的試算表,學習如何高效且安全地建構、管理並查詢海量且互相關聯的資料。如果聽到正規化 (normalization) 之類的術語覺得很頭痛,別擔心,我們會用淺顯易懂的生活例子將其拆解!
1. 資料管理基礎
1.1 資料 (Data) 與資訊 (Information)
首先,讓我們釐清這兩個經常被混用的術語:
- 資料 (Data): 原始、未經處理的事實與數字(例如:1987、Smith、$500.00)。 \n
- 資訊 (Information): 經過處理、組織並結構化後,具有意義的資料(例如:Smith 先生,1987 年出生,本月收入為 $500.00)。
1.2 資料庫方案與平面檔案 (Flat Files)
在專用資料庫系統出現之前,人們使用平面檔案(如簡單的文字檔或基礎試算表)來儲存資料。
平面檔案的局限性(為什麼我們需要資料庫):
- 資料冗餘 (Data Redundancy): 同一份資訊(如客戶地址)被儲存了多次,浪費空間。
- 資料不一致 (Data Inconsistency): 如果地址被儲存了 10 次,但其中 3 次更新錯誤,資料就會變得不可靠。
- 資料依賴性 (Data Dependence): 資料結構與存取它的應用程式緊密連結,導致更新非常困難。
- 安全性有限: 很難控管誰能看到特定的欄位或記錄。
現代的資料庫管理系統 (DBMS) 通過集中化資料、控制存取權限並定義不同資料間的明確關係,解決了這些問題。
快速複習:重點摘要 1
DBMS 實現了可控、一致且結構化的儲存,擺脫了平面檔案冗餘所帶來的困擾。
2. 關聯式資料庫結構 (RDBMS)
你將要學習的最常見資料庫類型是關聯式資料庫管理系統 (RDBMS)。該系統將資料組織成多個資料表(稱為關聯),並通過共用的鍵值將其連結起來。
2.1 核心資料庫術語
想像一個單一的試算表(即資料表 Table),其中行和列有特定的稱呼:
- 資料表 (Table/Relation): 由相關資料組成的集合,按行和列進行組織。(例如:STUDENTS 資料表)
- 欄位 (Field/Attribute): 資料表中的「列」,定義了特定的資料項目。(例如:Student_ID, Name, Date_of_Birth)
- 記錄 (Record/Tuple): 資料表中的「行」,代表一組完整且相關的資料。(例如:某位特定學生的所有資料)
2.2 理解鍵值 (Keys)
鍵值對於強制執行結構和連結資料表至關重要。它們是能夠唯一識別記錄或建立關係的屬性(欄位)。
a) 主鍵 (Primary Key, PK)
一個(或一組)能唯一識別資料表中每一筆記錄的欄位。
- 規則: PK 不能為空(實體完整性 Entity Integrity)且必須是唯一的。
- 類比:你的專屬學生證號碼。
b) 外鍵 (Foreign Key, FK)
資料表中的一個欄位,指向另一個資料表的主鍵。這就是建立關係的方式。
- 類比:學生清單(在 STUDENTS 資料表中)包含一個 "Course_ID"。這個 Course_ID 就是外鍵,連結回 COURSES 資料表中唯一的 Course_ID 主鍵。
- 你知道嗎? 外鍵在它自己的資料表中不需要是唯一的,因為許多學生可以選修同一門課程。
c) 複合鍵 (Composite Key)
由兩個或多個欄位組成的聯合主鍵。當單一欄位不足以提供唯一性時就會用到。
- 範例:在追蹤註冊情況的資料表中,可能需要 (Student_ID + Course_ID) 的組合來唯一識別一筆註冊紀錄。
3. 資料完整性與一致性
3.1 資料完整性 (Data Integrity)
資料完整性指的是資料庫中資料的準確性、完整性和一致性。一個健康的資料庫需要高水平的完整性。
- 實體完整性 (Entity Integrity): 確保每一筆記錄都有唯一的識別碼(主鍵不能為 NULL)。
- 域完整性 (Domain Integrity): 確保輸入到欄位的資料符合可接受的邊界(例如:年齡必須 > 0)。
3.2 參照完整性 (Referential Integrity, RI)
這是 RDBMS 中最重要的概念之一。參照完整性確保了資料表之間的關係始終保持一致。
- 規則: 任何外鍵的值,要麼必須與參照資料表中的主鍵值相符,要麼必須為 NULL。
- 常見錯誤: 當「主要」資料表中的記錄仍有外鍵參照時,直接刪除該記錄。這會產生「懸空參照」或「孤兒記錄」。
範例: 如果你從 COURSES 資料表中刪除了 'CS101' 課程,但 STUDENTS 資料表中還有 50 位學生將 'CS101' 列為他們的課程,你就違反了參照完整性。
4. 資料庫設計:正規化 (Normalization)
正規化是一套系統化的流程,用於組織資料表和欄位,以最大限度地減少冗餘和依賴。它使資料庫設計更高效、更易於維護且更可靠。
如果一開始覺得很複雜,別擔心。把正規化想像成整理一個凌亂、擁擠的檔案櫃,讓所有東西都存放在正確且專門的地方。
4.1 正規化形式 (Normal Forms, NF)
4.1.1 第一正規化 (1NF)
要求: 消除重複群組(儲存格內的清單),並確保資料是原子性 (atomic) 的。
- 原子性資料: 每一欄必須只包含一個值,且該值不可再細分(例如:姓名應拆分為「姓」和「名」欄位)。
- 目標: 每一行與每一列的交叉點只包含一個不可分割的值。
如果你有一個儲存格列出了「課程 A, 課程 B, 課程 C」,這就不符合 1NF。你必須將這些拆分到不同的記錄或另一個連接表 (junction table) 中。
4.1.2 第二正規化 (2NF)
要求: 必須先符合 1NF,且所有非主鍵屬性必須完全依賴於整個主鍵。
- 這僅在你有複合鍵時才適用。
- 目標: 確保你沒有在該資料表中儲存僅與複合鍵「部分」相關的資料。如果有,請將其移至單獨的資料表中。
步驟範例:
1. 資料表:ORDERS (OrderID, ProductID, Product_Name, Product_Price)
2. 主鍵為 (OrderID + ProductID)。
3. 注意:Product_Name 和 Product_Price 僅依賴於 ProductID,而非整個主鍵。
4. 解決方案: 建立一個獨立的 PRODUCTS 資料表 (ProductID, Product_Name, Product_Price) 並連結回 ORDERS 表。現在 ORDERS 表就符合 2NF 了。
4.1.3 第三正規化 (3NF)
要求: 必須先符合 2NF,且消除遞移依賴 (transitive dependencies)。
- 遞移依賴: 一個非主鍵屬性決定了另一個非主鍵屬性 (A -> B -> C,但 A 是主鍵)。資料並不直接依賴於主鍵,而是依賴於另一個非主鍵欄位。
- 目標: 確保所有欄位僅依賴於主鍵,與其他無關。
範例:
1. 資料表:EMPLOYEES (Employee_ID, Employee_Name, Department_ID, Department_Manager)
2. Employee_ID 是主鍵。
3. Department_Manager 依賴於 Department_ID,而非 Employee_ID。這就是遞移依賴。
4. 解決方案: 建立一個獨立的 DEPARTMENTS 資料表 (Department_ID, Department_Manager) 並連結回去。現在 EMPLOYEES 表就符合 3NF 了。
記憶口訣 (3NF): 每個非主鍵屬性必須提供關於鍵的資訊,且是完整的主鍵,除了主鍵之外什麼都沒有。
快速複習:正規化
我們進行正規化至 3NF,目的是防止冗餘、最小化更新/刪除異常,並確保資料一致性。
5. 資料庫查詢:結構化查詢語言 (SQL)
SQL (Structured Query Language) 是與關聯式資料庫進行互動和管理的標準語言。對於檢索、插入、修改和刪除資料至關重要。
5.1 資料操作語言 (DML)
DML 指令用於處理資料表內儲存的資料。
a) SELECT (檢索資料)
用於從一個或多個資料表中檢索記錄。這是最常見的指令。
語法結構:
SELECT [欄位] FROM [資料表] WHERE [條件] ORDER BY [欄位]
範例 1 (基本檢索): 檢索所有學生姓名。
SELECT Name FROM Students;
範例 2 (條件檢索): 檢索年齡大於 18 歲的學生姓名。
SELECT Name FROM Students WHERE Age > 18;
b) INSERT (新增資料)
用於向資料表中新增記錄(行)。
語法結構:
INSERT INTO [資料表] (欄位1, 欄位2, ...) VALUES (值1, 值2, ...);
範例:
INSERT INTO Courses (Course_ID, Title) VALUES ('CSHL', 'HL Computer Science');
c) UPDATE (修改現有資料)
用於變更資料表中現有記錄的值。使用 WHERE 子句時請務必小心!
語法結構:
UPDATE [資料表] SET [欄位] = [新值] WHERE [條件];
範例: 將 'CSHL' 課程名稱改為 'Advanced Comp Sci'。
UPDATE Courses SET Title = 'Advanced Comp Sci' WHERE Course_ID = 'CSHL';
d) DELETE (移除資料)
用於從資料表中移除記錄(行)。
語法結構:
DELETE FROM [資料表] WHERE [條件];
範例: 移除 ID 為 999 的學生。
DELETE FROM Students WHERE Student_ID = 999;
常見錯誤: 在 UPDATE 或 DELETE 指令中忘記寫 WHERE 子句。如果忘記,操作將會影響資料表中的每一筆記錄!
5.2 資料表連結 (Joining Tables)
使用 RDBMS 的主要原因是能夠利用外鍵連結(Join)多個資料表的資料。
INNER JOIN 會結合兩張資料表中,在特定欄位(通常是 PK/FK 對)有相符值的記錄。
範例: 檢索學生姓名以及他們所選修的課程名稱。
SELECT S.Name, C.Title
FROM Students S
INNER JOIN Courses C ON S.Course_ID = C.Course_ID;
6. 資料庫安全性與存取權限
資料庫通常儲存敏感資訊(個人資料、財務記錄)。安全性至關重要,包括物理和邏輯兩方面的防禦措施。
6.1 邏輯安全措施
- 使用者認證: 要求唯一的使用者名稱和強密碼來存取資料庫系統。
- 存取權限 (Permissions): 定義特定使用者或使用者群組可以執行哪些操作(例如:Jane 只能
SELECT資料;Bob 可以INSERT和UPDATE)。這通常由 SQL 的GRANT和REVOKE指令控制。 - 檢視表 (Views): View 是基於 SQL 查詢結果的虛擬資料表。它允許你限制使用者能看到的欄位和行,而無需給予底層資料表的完整存取權。(例如:老師的 View 只顯示學生姓名和分數,隱藏地址和病歷。)
- 加密: 將敏感資料(如密碼)以加密格式儲存,這樣即使資料庫被駭,資料也無法讀取。
6.2 物理措施與災難恢復
- 備份 (Backups): 定期將整個資料庫複製到安全的異地位置,以便在系統故障或毀損時進行恢復。
- 交易記錄 (Transaction Logs): 記錄對資料庫執行的每一項操作。如果發生當機,這些記錄允許資料庫回滾未完成的交易或還原最近的變更。
- 冗餘 (Redundancy): 使用重複的硬體(如 RAID 系統),確保單一組件故障不會導致資料遺失或系統停機。
你現在已經掌握了關聯式資料庫的結構與核心原則,這是幾乎所有現代大型應用程式的基礎!請記住,良好的資料庫設計(正規化)是建立可靠、高效系統的關鍵。繼續練習那些 SQL 查詢語法吧!