章節筆記:掌握 SQL(結構化查詢語言)

各位同學好!歡迎來到資料庫的世界。試想想你身邊所有的資料:朋友的聯絡資料、學校的學生紀錄、網上購物網站上的商品等等。所有這些資訊是如何儲存、管理和檢索的?答案往往是一個資料庫,而我們用來與它「溝通」的語言就是 SQL

在這些筆記中,我們將學習如何使用 SQL 來提出問題、更改資訊,甚至建立資料庫的一部分。這就像學習一種秘密語言,它為你每天使用的許多應用程式和網站提供支援。剛開始時可能覺得有點難,但別擔心,我們會透過大量例子一步步地將它拆解!


什麼是 SQL?一個簡單的比喻

想像一下你學校的圖書館有一個超級有條理的數碼目錄。SQL 就是你用來要求圖書館管理員(資料庫管理系統,或稱 DBMS)在該目錄(資料庫)中尋找、新增或更新書籍資訊的特殊語言。

  • 查詢資料:「顯示所有 J.K. Rowling 撰寫的書籍。」
  • 新增資料:「將這本新書《資訊及通訊科技歷險記》新增到系統中。」
  • 更新資料:「將《哈利波特》的狀態從『可借閱』更改為『已借出』。」

SQL 有幾種主要的指令類型。我們可以把它們想像成不同類型的請求:

  • 資料查詢語言 (DQL):用於提出問題和獲取資料。(最常用!)
  • 資料操作語言 (DML):用於更改資料(新增、更新、刪除記錄)。
  • 資料定義語言 (DDL):用於建立和管理資料庫結構本身(建立或更改表格)。



第一部分:使用 SELECT 查詢資料 (DQL)

這是 SQL 中最重要且最常用的部分,它全部關於檢索資訊。其基本結構簡單易記。

我們將使用一個名為 Students 的範例表格作為例子:

Students 表格
StudentIDFirstNameLastNameClassScore
101ChanTai Man5A88
102LeeSiu Ming5B95
103WongKa Wai5A72
104NgMei Ling5C88
105CheungPui Sze5B65

基本 SELECT 語句

兩個必要的部分是 SELECT(你想要哪些欄位)和 FROM(從哪個表格中查找)。

獲取指定欄位:

查找所有學生的名字和姓氏。

SELECT FirstName, LastName FROM Students;

獲取所有欄位(使用萬用字元 *):

查找所有學生的所有資訊。

SELECT * FROM Students;

記憶提示:* 想像成一個萬用字元,意思是「所有」。

使用 DISTINCT 消除重複值:

如果你想查看不重複的唯一值,可以使用 DISTINCT 關鍵字。

列出學生表格中出現的所有不重複班級。

SELECT DISTINCT Class FROM Students;

使用 WHERE 過濾結果

如果你不想獲取所有記錄怎麼辦?WHERE 子句允許你設定條件來過濾結果。

查找 5A 班學生的名字。

SELECT FirstName, LastName FROM Students WHERE Class = '5A';

重要提示:文字值(如 '5A')通常放在單引號 ' ' 內。

WHERE 子句的運算子

你可以使用不同的運算子來建立強大的篩選條件:

  • 比較運算子:
    • = (等於)
    • <> (不等於)
    • > (大於)
    • < (小於)
    • >= (大於或等於)
    • <= (小於或等於)
  • 邏輯運算子:
    • AND:兩個條件都必須為真。(例如:WHERE Class = '5A' AND Score > 80
    • OR:至少一個條件必須為真。(例如:WHERE Score < 70 OR Score > 90
    • NOT:反轉條件的結果。(例如:WHERE NOT Class = '5A'
  • 特殊運算子:
    • BETWEEN:檢查值是否在指定範圍內(包含兩端)。
      例子:WHERE Score BETWEEN 70 AND 90;(這等同於 Score >= 70 AND Score <= 90
    • IN:檢查值是否與列表中任何值匹配。
      例子:WHERE Class IN ('5A', '5C');(這是 Class = '5A' OR Class = '5C' 的簡寫)
    • LIKE:用於文字的模式匹配。它使用萬用字元:
      • %:代表零個、一個或多個字元。
      • _:代表一個單一字元。
      例子 1:查找姓氏以 'W' 開頭的學生。
      WHERE LastName LIKE 'W%';

      例子 2:查找名字是 'Siu' 後面剛好跟著四個字元的學生。
      WHERE FirstName LIKE 'Siu ____';
    • IS NULL / IS NOT NULL:檢查缺失或未定義的資料(切勿使用 = NULL)。
      例子:WHERE Score IS NOT NULL;

使用 ORDER BY 排序結果

ORDER BY 子句會對你的結果進行排序。預設情況下,它按升序排序(A-Z,1-100)。

  • ASC:升序(預設值)。
  • DESC:降序。

列出所有學生,按分數從高到低排序。

SELECT FirstName, LastName, Score FROM Students ORDER BY Score DESC;

快速回顧:DQL 黃金結構

對於標準查詢,子句必須遵循以下嚴格順序:

SELECT [DISTINCT] [欄位]
FROM [表格]
WHERE [條件]
ORDER BY [排序欄位];




第二部分:匯總及操作資料(選修內容)

現在我們將進入資料庫選修部分涵蓋的更進階主題。這正是 SQL 變得真正強大的地方!

聚合函數:全盤概覽

這些函數對一組行執行計算,並返回一個單一的匯總值。

  • COUNT():計算行數。
  • SUM():計算欄位中所有值的總和。
  • AVG():計算欄位中值的平均值。
  • MAX():查找欄位中的最高值。
  • MIN():查找欄位中的最低值。

總共有多少學生?

SELECT COUNT(*) FROM Students;

5A 班學生的平均分數是多少?

SELECT AVG(Score) FROM Students WHERE Class = '5A';

使用 GROUP BY 和 HAVING 分組資料

當你想獲取子群組而非整個表格的聚合統計資料時(例如每班的平均分數),請使用 GROUP BY

計算每班的平均分數:

SELECT Class, AVG(Score) FROM Students GROUP BY Class;

要根據聚合值過濾群組,請使用 HAVING 子句(WHERE 在分組前過濾個別記錄,而 HAVING 在分組後過濾匯總群組):

查找平均分數大於 80 的班級:

SELECT Class, AVG(Score) FROM Students GROUP BY Class HAVING AVG(Score) > 80;

字串函數:處理文字

SQL 有用於處理文字資料的函數:

  • LENGTH()LEN():獲取字串的字元數。
  • UCASE()UPPER():將文字轉換為大寫。
  • LCASE()LOWER():將文字轉換為小寫。

顯示所有學生姓氏的大寫形式。

SELECT UPPER(LastName) FROM Students;

使用 DML 更改資料

這些指令修改表格內部的資料。

注意! DML 的一個錯誤可能會永久性地更改或刪除你的資料。使用 WHERE 子句時務必小心!

INSERT INTO:新增資料

向表格新增一行(記錄)。

向表格新增一個學生。

INSERT INTO Students (StudentID, FirstName, LastName, Class, Score) VALUES (106, 'Lau', 'Kit Ying', '5C', 81);

UPDATE:修改現有資料

更改現有行中的資料。

常見錯誤:忘記 `WHERE` 子句將更新表格中的所有行!

Chan Tai Man(學生編號 101)重考了一次,現在他的分數是 91。

UPDATE Students SET Score = 91 WHERE StudentID = 101;

DELETE:刪除資料

從表格中刪除行。

常見錯誤:忘記 `WHERE` 子句將刪除表格中的所有行!

學生 Cheung Pui Sze(學生編號 105)已離校。

DELETE FROM Students WHERE StudentID = 105;

重點:DML 的安全使用

WHERE 子句是 UPDATEDELETE 的安全網。它告訴資料庫確切要更改或刪除哪條記錄。在執行指令前務必仔細檢查!




第三部分:使用連接及子查詢進行進階查詢(選修內容)

真實世界的資料庫為了提高效率,會將資料分散儲存於多個表格中。我們如何將它們組合起來呢?使用連接 (JOINs)

讓我們新增另一個表格:Courses

Courses 表格
CourseIDCourseNameTeacher
ICT資訊科技李先生
ENG英國語文戴維斯女士
MATH數學陳太太

前提知識:主鍵與外來鍵

為了連接表格,我們需要特殊的鍵。

  • 主鍵 (PK) 是表格中唯一識別每條記錄的欄位(例如 Students 表格中的 `StudentID`)。
  • 外來鍵 (FK) 是來自一個表格的主鍵,你將其放入另一個表格中以建立連接。

連接表格

連接 (JOIN) 根據表格之間相關的欄位將兩個或多個表格中的行組合起來。

等值連接(或稱內部連接 INNER JOIN)

這是最常見的連接類型。它只返回在兩個表格中都有匹配值的記錄。

讓我們想像我們有第三個表格 Enrollments,它連接 Students 和 Courses。

Enrollments 表格
StudentIDCourseID
101ICT
101ENG
102ICT
103MATH

顯示每個學生的名字以及他們報讀的課程名稱。

SELECT S.FirstName, C.CourseName
FROM Students S JOIN Enrollments E ON S.StudentID = E.StudentID
JOIN Courses C ON E.CourseID = C.CourseID;

解釋:
1. 我們使用別名(S 代表 StudentsE 代表 EnrollmentsC 代表 Courses)來縮短程式碼。
2. ON 關鍵字指定連接條件:`ON table1.column = table2.column`。

外部連接(左連接 LEFT JOIN 和右連接 RIGHT JOIN)

如果你想查看一個表格中的所有記錄,即使它們在另一個表格中沒有匹配項,該怎麼辦?

  • LEFT JOIN(左連接):返回左側表格(首先提到的表格)中的所有記錄,以及右側表格中匹配的記錄。如果沒有匹配項,右側結果為空值 (NULL)。
  • RIGHT JOIN(右連接):返回右側表格中的所有記錄。它與左連接相反。

列出所有學生及其所修讀的課程。即使沒有修讀任何課程的學生也應列出。

SELECT S.FirstName, E.CourseID
FROM Students S LEFT JOIN Enrollments E ON S.StudentID = E.StudentID;

這將顯示 Chan Tai Man(ICT 和 ENG)、Lee Siu Ming(ICT)和 Wong Ka Wai(MATH)及其課程,但 Ng Mei Ling 和 Cheung Pui Sze 也會被列出,其 `CourseID` 為空值 (NULL),因為他們在左側表格(Students)中,但在 Enrollments 表格中沒有匹配項。

子查詢(單層)

子查詢是嵌套在另一個查詢中的查詢。內部查詢的結果被外部查詢使用。

查找分數高於班級平均分的學生姓名。

SELECT FirstName, LastName
FROM Students
WHERE Score > (SELECT AVG(Score) FROM Students);

逐步解釋:
1. 內部查詢 (SELECT AVG(Score) FROM Students) 首先執行,並計算平均分數(例如 81.6)。
2. 然後外部查詢執行為:SELECT FirstName, LastName FROM Students WHERE Score > 81.6;

重點:組合資料

連接 (JOINs) 用於組合來自不同表格的欄位。子查詢 用於將一個查詢的結果作為另一個查詢的條件。




第四部分:檢視表和表格結構(選修內容)

使用 DDL 建立表格與完整性約束條件

要定義新表格並強制執行業務規則,我們可以使用 CREATE TABLE 語句以及欄位約束條件:

  • PRIMARY KEY:唯一識別每條記錄,防止出現重複值和 NULL 值。
  • FOREIGN KEY ... REFERENCES:強制執行與另一個表格的參照完整性。
  • NOT NULL:確保欄位不能包含 NULL 值。
  • UNIQUE:確保欄位中的所有值都是唯一的。
  • CHECK:對數值強制執行特定條件(例如:CHECK (Score >= 0 AND Score <= 100))。
  • DEFAULT:在沒有提供數值時指定預設值。

例子:定義帶有約束條件的 Students 表格。

CREATE TABLE Students (
  StudentID INT PRIMARY KEY,
  FirstName VARCHAR(50) NOT NULL,
  LastName VARCHAR(50) NOT NULL,
  Class VARCHAR(5),
  Score INT CHECK (Score >= 0 AND Score <= 100)
);

建立檢視表 (VIEW)

檢視表 (VIEW) 是基於 SQL 語句結果集的一個虛擬表格。它就像一個已儲存的查詢,你可以像操作真實表格一樣與它互動。檢視表對於以下方面很有用:

  • 簡化複雜的查詢。
  • 透過只顯示某些欄位或行來提供一層安全性。

建立一個只顯示 5A 班學生的檢視表。

CREATE VIEW Class5A_Students AS
SELECT StudentID, FirstName, LastName, Score
FROM Students
WHERE Class = '5A';

現在,你可以直接查詢這個檢視表:

SELECT * FROM Class5A_Students;

使用 DDL 修改表格結構

有時候你需要更改表格建立後的結構(即「模式」)。我們使用 ALTER TABLE 來實現這一點。

  • ADD Column:向表格新增一個欄位。
  • DROP COLUMN:移除一個欄位。
  • MODIFY COLUMNALTER COLUMN:更改欄位的資料類型。

向 Students 表格新增一個名為 'Email' 的新欄位。

ALTER TABLE Students ADD Email VARCHAR(255);

移除我們剛剛新增的 'Email' 欄位。

ALTER TABLE Students DROP COLUMN Email;

你知道嗎?

SQL 最初於 1970 年代初由 IBM 開發。它最初的名字是 SEQUEL(結構化英文查詢語言)。儘管它已有數十年的歷史,但它仍然是全球關聯式資料庫的標準語言!


最後總結

你已經學會了 SQL 的基礎知識!從使用 SELECT...FROM...WHERE 的簡單查詢,到使用 GROUP BY / HAVING 進行聚合分組,再到使用 CREATE TABLE 建立表格以及多表格連接 (JOINs)。實踐是關鍵,所以試著為不同的情景編寫你自己的查詢吧。做得好!