歡迎來到關聯式資料庫的世界!
在本章中,我們將告別簡單的平檔案(flat files),深入探討關聯式資料庫(relational databases)。你可以把這想像成桌上一堆雜亂的文件,與一個井然有序、所有項目都互相連結的檔案櫃之間的區別。資料庫是現代應用程式的骨幹,從 Instagram 到你學校的成績系統,背後都少不了它。看完這些筆記後,你將學會如何整理數據,讓它變得高效、準確且易於檢索!
1. 什麼是關聯式資料庫?
簡單來說,關聯式資料庫是一種透過多個互相連結的表格來儲存數據的方法。我們不再使用一個笨重且巨大的表格(即平檔案),而是將數據拆分成更小、更合乎邏輯的表格。
比喻:想像一個音樂 App。與其建立一個包含歌曲名稱、歌手、歌手年齡以及每首曲目對應專輯的巨型表格,不如分別建立「歌手 (Artists)」、「專輯 (Albums)」和「歌曲 (Songs)」三個表格。它們透過特殊的 ID 數字來建立「關聯」。
你需要掌握的關鍵術語:
屬性 (Attribute): 這是表格中欄 (column) 或欄位 (field) 的專業術語。它代表資訊的特定類別。例如:「出生日期 (DateOfBirth)」或「姓氏 (Surname)」。
主鍵 (Primary Key): 這是表格中每一條記錄(列)的唯一識別碼。沒有任何兩列可以擁有相同的主鍵。例如:你在學校的「學生編號」。
複合主鍵 (Composite Primary Key): 有時,單一屬性不足以保證唯一性。複合主鍵會結合兩個或以上的屬性來建立唯一識別碼。例如:在「課室預訂 (Classroom Booking)」表格中,結合「課室編號 (RoomNumber)」和「時段 (Period)」就可以作為一個唯一鍵。
外鍵 (Foreign Key): 這是來自另一個表格的主鍵,出現在當前表格中以連結兩者。它就像是表格之間的「橋樑」。
快速重溫:
- 主鍵: 自身表格中的唯一識別 ID。
- 外鍵: 從其他表格引入並作為連結用的主鍵。
重點總結: 關聯式資料庫透過以鍵值連結的多個表格,減少數據重複並保持系統條理分明。
2. 資料庫設計與正規化
如果正規化 (normalisation) 這個詞聽起來很嚇人,不用擔心!這只是一個逐步「整理」資料庫的過程,目的是使其達到最高效率。我們這麼做是為了避免數據冗餘 (data redundancy)(重複儲存相同的內容)和數據不一致 (data inconsistency)(同時存在兩個不同的「真實版本」)。
正規化的三個層次
為了達到第三正規化 (3NF),我們需要遵循以下步驟:
第一正規化 (1NF)
如果一個表格中沒有重複的屬性群組,它就達到了 1NF。表格中的每個「儲存格」都必須僅包含一個數據。
第二正規化 (2NF)
如果一個表格已經達到 1NF,且所有非主鍵屬性都完全依賴於主鍵,它就達到了 2NF。這通常只在你使用複合主鍵時才需要考慮。你不應該在表格中儲存僅與主鍵的「一部分」相關的數據。
第三正規化 (3NF)
如果一個表格已經達到 2NF,且沒有傳遞依賴 (transitive dependencies),它就達到了 3NF。這句話用通俗的話來說就是:「所有屬性必須僅依賴於主鍵。」如果一個屬性依賴於另一個非主鍵屬性,那麼它就需要被移動到另一個獨立的表格中。
3NF 記憶口訣: 一個著名的記憶方式是,所有數據都必須依賴於:
「主鍵、完整主鍵,且除了主鍵別無其他」(The Key, the Whole Key, and Nothing But the Key)。
為什麼要進行正規化?
1. 節省空間: 不需要重複輸入相同的地址或名稱。
2. 數據完整性: 如果客戶更改了電話號碼,你只需要在一個地方更新,而不用更改五十次。
3. 搜尋更便捷: 對電腦而言,處理規模更小、結構更清晰的表格速度更快。
重點總結: 正規化 (1NF -> 2NF -> 3NF) 能清除混亂的重複數據,並確保每一份數據都儲存在最合理的邏輯位置。
3. 結構化查詢語言 (SQL)
SQL 是我們用來與資料庫「對話」的語言。你需要知道如何執行四項主要操作(CRUD:建立、讀取、更新、刪除)以及如何建立表格。
定義表格
要建立新表格,我們使用 CREATE TABLE。
範例:
CREATE TABLE Students (
StudentID INT PRIMARY KEY,
FirstName VARCHAR(20),
Surname VARCHAR(20)
);
管理數據
SELECT: 用於搜尋並顯示數據。
SELECT FirstName FROM Students WHERE Surname = 'Smith';
INSERT: 用於新增記錄。
INSERT INTO Students (StudentID, FirstName, Surname) VALUES (101, 'Ali', 'Khan');
UPDATE: 用於更改現有數據。
UPDATE Students SET Surname = 'Jones' WHERE StudentID = 101;
DELETE: 用於刪除記錄。
DELETE FROM Students WHERE StudentID = 101;
必須避免的常見錯誤: 使用 UPDATE 或 DELETE 時,永遠記得帶上你的 WHERE 子句!如果你忘了它,你可能會不小心刪除資料庫中的所有人,或是把所有人的名字都改成 'Jones'。
重點總結: SQL 是定義表格與操控內部數據的標準語言。
4. 用戶端-伺服器資料庫
在現實世界中,許多人(用戶端)會同時嘗試存取同一個資料庫(伺服器)。這可能會導致「交通堵塞」,我們稱為併發問題 (concurrency issues)。
問題:遺失更新 (Lost Updates)
想像一下,兩個人在同一毫秒嘗試預訂航班上的最後一個座位。如果系統不夠嚴謹,可能會同時讓兩人預訂成功,或者其中一人的預訂「覆蓋」了另一人的結果。這就是遺失更新。
解決方案:
為了確保數據安全(維持完整性),我們使用以下方法:
記錄鎖定 (Record Locks): 當某人正在編輯記錄時,資料庫會將其「鎖定」,直到該操作完成,否則其他人無法進行任何修改。這就像從圖書館借書一樣;在你還書之前,沒人能讀那本書。
序列化 (Serialisation): 確保交易(transactions)是一個接一個處理,而不是同時進行,這樣它們就不會互相干擾。
時間戳記排序 (Timestamp Ordering): 每項交易都會獲得一個「時間貼紙」。如果兩個人嘗試更改同一數據,擁有較早時間戳記的交易會先被處理。
承諾排序 (Commitment Ordering): 交易會根據其依賴關係以及它們「承諾」(最終確定)的時間進行排序,以確保它們不會發生衝突。
你知道嗎? 銀行每秒都在使用這些技術,以確保當你和朋友同時轉帳時,你的帳戶餘額不會意外翻倍(或者憑空消失!)。
重點總結: 併發存取可能會破壞數據。我們使用鎖定與排序技術來確保每一次更新都能正確處理,不會遺失數據。