章节笔记:掌握 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)。实践是关键,所以试着为不同的情景编写你自己的查询吧。做得好!