章节笔记:掌握 SQL(结构化查询语言)
同学们好!欢迎来到数据库的世界。试想想你身边所有的资料:朋友的联络资料、学校的学生记录、网上购物网站上的商品等等。所有这些资讯是如何储存、管理和检索的?答案往往是一个数据库,而我们用来与它“沟通”的语言就是 SQL。
在这些笔记中,我们将学习如何使用 SQL 来提出问题、更改资讯,甚至建立数据库的一部分。这就像学习一种秘密语言,它为你每天使用的许多应用程序和网站提供支持。刚开始时可能觉得有点难,但别担心,我们会通过大量例子一步步地将它拆解!
什么是 SQL?一个简单的比喻
想像一下你学校的图书馆有一个超级有条理的数字目录。SQL 就是你用来要求图书馆管理员(数据库管理系统,或称 DBMS)在该目录(数据库)中寻找、新增或更新书籍资讯的特殊语言。
- 查询资料:“显示所有 J.K. Rowling 撰写的书籍。”
- 新增资料:“将这本新书《资讯及通讯科技历险记》新增到系统中。”
- 更新资料:“将《哈利波特》的状态从‘可借阅’更改为‘已借出’。”
SQL 有几种指令类型。我们可以把它们想像成不同类型的请求:
- 资料查询语言 (DQL):用于提出问题和获取资料。(最常用!)
- 资料操作语言 (DML):用于更改资料(新增、更新、删除记录)。
- 资料定义语言 (DDL):用于建立和管理数据库结构本身(建立或更改表格)。
第一部分:使用 SELECT 查询资料 (DQL)
这是 SQL 中最重要且最常用的部分,它全部关于检索资讯。其基本结构简单易记。
我们将使用一个名为 Students 的示例表格作为例子:
Students 表格
| StudentID | FirstName | LastName | Class | Score |
|---|---|---|---|---|
| 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;
记忆提示:将 * 想像成一个通配符,意思是“所有”。
使用 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')
- AND:两个条件都必须为真。(例如:
- 特殊运算符:
- BETWEEN:检查值是否在指定范围内(包含两端)。
例子:WHERE Score BETWEEN 70 AND 90;(这等同于Score >= 70 AND Score <= 90) - IN:检查值是否与列表中任何值匹配。
例子:WHERE Class IN ('5A', '5C');(这是Class = '5A' OR Class = '5C'的简写) - LIKE:用于文本的模式匹配。它使用通配符:
%:代表零个、一个或多个字符。_:代表一个单一字符。
WHERE LastName LIKE 'W%';
例子 2:查找名字是 'Siu' 后面刚好跟着四个字符的学生。WHERE FirstName LIKE 'Siu ____'; - IS NULL / IS NOT NULL:检查缺失或未定义的资料(切勿使用
= NULL)。
例子:WHERE Score IS NOT NULL;
- BETWEEN:检查值是否在指定范围内(包含两端)。
使用 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 子句是 UPDATE 和 DELETE 的安全网。它告诉数据库确切要更改或删除哪条记录。在执行指令前务必仔细检查!
第三部分:使用连接及子查询进行进阶查询(选修内容)
真实世界的数据库为了提高效率,会将资料分散储存于多个表格中。我们如何将它们组合起来呢?使用连接 (JOINs)!
让我们新增另一个表格:Courses。
Courses 表格
| CourseID | CourseName | Teacher |
|---|---|---|
| ICT | 资讯科技 | 李先生 |
| ENG | 英国语文 | 戴维斯女士 |
| MATH | 数学 | 陈太太 |
前提知识:主键与外键
为了连接表格,我们需要特殊的键。
- 主键 (PK) 是表格中唯一识别每条记录的字段(例如 Students 表格中的 `StudentID`)。
- 外键 (FK) 是来自一个表格的主键,你将其放入另一个表格中以建立连接。
连接表格
连接 (JOIN) 根据表格之间相关的字段将两个或多个表格中的行组合起来。
等值连接(或称内部连接 INNER JOIN)
这是最常见的连接类型。它只返回在两个表格中都有匹配值的记录。
让我们想像我们有第三个表格 Enrollments,它连接 Students 和 Courses。
Enrollments 表格
| StudentID | CourseID |
|---|---|
| 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 代表 Students,E 代表 Enrollments,C 代表 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 COLUMN 或 ALTER 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)。实践是关键,所以试着为不同的情景编写你自己的查询吧。做得好!