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

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

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


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

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

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

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

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



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

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

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

Students 表格

學生編號 | 名字 | 姓氏 | 班級 | 分數
101 | Chan | Tai Man | 5A | 88
102 | Lee | Siu Ming | 5B | 95
103 | Wong | Ka Wai | 5A | 72
104 | Ng | Mei Ling | 5C | 88
105 | Cheung | Pui Sze | 5B | 65

基本 SELECT 語句

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

獲取指定欄位:

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

SELECT FirstName, LastName FROM Students;

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

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

SELECT * 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 ____';

使用 ORDER BY 排序結果

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

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

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

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

快速回顧:DQL 黃金三劍客

對於大多數查詢,你會使用這個結構:

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

你不一定總是需要 `WHERE` 或 `ORDER BY`,但它們必須按這個順序出現!




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

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

聚合函數:全盤概覽

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

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

總共有多少學生?

SELECT COUNT(*) FROM Students;

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

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

字串函數:處理文字

SQL 有用於處理文字資料的函數。確切的名稱可能有所不同,但概念是相似的。

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

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

SELECT UCASE(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 表格

課程編號 | 課程名稱 | 教師
ICT | 資訊科技 | 李先生
ENG | 英文 | 戴維斯女士
MATH| 數學 | 陳太太

前提知識:主鍵與外來鍵

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

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

連接表格

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

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

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

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

Enrollments 表格

學生編號 | 課程編號
101 | ICT
101 | ENG
102 | ICT
103 | MATH

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

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 代表 StudentsC 代表 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 和 Lee Siu Ming 及其課程,但 Wong Ka Wai、Ng Mei Ling 等也會被列出,其 `CourseID` 為空值 (NULL),因為它們在左側表格(Students)中,但在 Enrollments 表格中沒有匹配項。

自然連接 (Natural Join)

NATURAL JOIN(自然連接)是一種等值連接,資料庫會根據具有相同名稱的欄位自動連接表格。它很方便,但如果表格有多個同名欄位,可能會產生不可預測的結果。

(在我們的例子中,為了使用它,我們需要將兩個表格中的欄位都重命名為 `StudentID`)。

SELECT FirstName, CourseID FROM Students NATURAL JOIN Enrollments;

子查詢(單層)

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

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

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

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

重點:組合資料

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




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

建立檢視表 (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);

(VARCHAR 是一種常用的可變長度文字資料類型)。

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

ALTER TABLE Students DROP COLUMN Email;

你知道嗎?

SQL 最初於 1970 年代初由 IBM 開發。它最初的名字是 SEQUEL(結構化英文查詢語言)。儘管它已有將近 50 年的歷史,但它仍然是全球科技職位中最受歡迎的技能之一!


最後總結

你已經學會了 SQL 的基礎知識!從簡單的 SELECT...FROM...WHERE 查詢到複雜的資料操作和多表格連接 (JOINs)。實踐是關鍵,所以試著為不同的情景編寫你自己的查詢吧。做得好!