# 结构化查询语言（SQL）

> CIE A-Level 计算机科学 · 9618
> 来源: https://www.owlsprep.com/zh/study/cie-9618-u8-structured-query-language/

本模块涵盖CIE 9618要求的所有核心SQL概念，包括数据定义（DDL）、数据操作（DML）、过滤、聚合和连接多个关系表，适用于考试风格题型。

**先修:** [关系数据库概念（实体、键、关系）](https://www.owlsprep.com/zh/study/cie-9618-u8-relational-database-concepts/)

## 学习目标

- 编写有效的SQL查询从关系表中检索数据
- 使用DDL命令创建和修改数据库表结构
- 应用过滤、排序和聚合汇总数据
- 连接多个相关表提取关联信息

## 核心SQL概念与DDL命令

在A-Level中，SQL分为两个核心子集：用于创建和修改数据库结构的数据定义语言（DDL），以及用于访问和更改存储数据的数据操作语言（DML）。

**数据定义语言（DDL）** — SQL的子集，用于定义和修改数据库对象（如表、约束和模式）的结构。

*例:* 常用DDL命令：`CREATE`、`ALTER`、`DROP`

**例题:** 为`Customer`表编写SQL `CREATE TABLE`语句，要求包含：`customer_id`（整数，主键）、`customer_name`（可变长度字符串100，非空）、`email`（可变长度字符串100）、`loyalty_points`（整数，默认值0）

1. 以命令关键字和表名开头：
2. $$CREATE TABLE Customer ($$
3. 添加每个列定义以及所需约束：
4. $$customer_id INT PRIMARY KEY,
customer_name VARCHAR(100) NOT NULL,
email VARCHAR(100),
loyalty_points INT DEFAULT 0$$
5. 用正确语法结束语句：
6. $$);$$

> **考试提示:** CIE考官要求正确的语法，包括语句末尾的分号。关键字大写可以提高清晰度，避免混淆。

## DML：基础SELECT查询与过滤

数据操作语言（DML）用于与存储在表中的数据交互。最常用的DML命令是`SELECT`，它从一个或多个表中检索符合给定条件的数据。

**SELECT语句** — 用于从表中检索符合用户定义条件的指定数据的核心SQL命令。

**例题:** 从`Customer`表中检索`loyalty_points > 100`的`customer_name`和`loyalty_points`，并按`loyalty_points`降序排序

1. 在`SELECT`后列出要检索的列：
2. $$SELECT customer_name, loyalty_points$$
3. 在`FROM`后指定源表：
4. $$FROM Customer$$
5. 用`WHERE`添加过滤条件：
6. $$WHERE loyalty_points > 100$$
7. 添加排序并结束语句：
8. $$ORDER BY loyalty_points DESC;$$

> **tip**
>
> 仅当问题明确要求所有列时才使用`SELECT *`。考官更偏好显式选择列，这种方式更清晰，也避免返回不必要的数据。

## 聚合与分组

聚合函数对行组计算汇总统计信息，而不是返回单个记录。`GROUP BY`子句在应用聚合之前将行拆分为逻辑组。

**聚合函数** — 对多个行执行计算并返回单个汇总值的函数。常见示例包括`COUNT()`、`SUM()`、`AVG()`、`MAX()`和`MIN()`。

**例题:** 对于通过`customer_id`与`Customer`表关联的`Order`表，找出每个客户的总订单数和总订单价值，仅显示总价值大于\$1000的客户

1. 选择分组键和所需的聚合函数：
2. $$SELECT customer_id, COUNT(order_id) AS total_orders, SUM(order_value) AS total_spend$$
3. 指定源表：
4. $$FROM Order$$
5. 按`customer_id`对行分组，以计算每个客户的聚合值：
6. $$GROUP BY customer_id$$
7. 用`HAVING`过滤聚合后的分组：
8. $$HAVING SUM(order_value) > 1000;$$

**考试命令词**

考试一直会考`WHERE`和`HAVING`的区别：

- **WHERE** — 在分组/聚合之前过滤单个行 *(分组前过滤2024年之后下的订单)*

- **HAVING** — 聚合完成后过滤整个分组 *(分组后过滤总消费超过\$1000的分组)*

## 连接多个表

大多数实际查询都需要来自多个通过主键和外键关联的表的数据。`JOIN`操作基于共享的关联列组合两个或多个表中的行。

**内连接（INNER JOIN）** — 最常用的连接类型，仅返回两个连接表中都存在匹配值的行。

**例题:** 编写查询获取2024年所有订单的客户姓名和订单日期。表结构：`Customer(customer_id, customer_name)`，`Order(order_id, customer_id, order_date)`

1. 指定所需列，为清晰起见加上表名前缀：
2. $$SELECT Customer.customer_name, Order.order_date$$
3. 声明连接类型和表：
4. $$FROM Customer INNER JOIN Order$$
5. 添加连接条件来关联键：
6. $$ON Customer.customer_id = Order.customer_id$$
7. 过滤2024年的订单并结束语句：
8. $$WHERE Order.order_date BETWEEN '2024-01-01' AND '2024-12-31';$$

> **warning**
>
> 连接时必须包含`ON`子句。省略它会产生两个表所有行的笛卡尔积，这几乎总是错误的。

## 常见错误

- **错误做法:** 对行级过滤使用`HAVING`而非`WHERE`
  - 原因: `HAVING`仅在聚合后过滤，因此这会产生错误结果并失分
  - 正确做法: 分组前对单个行过滤使用`WHERE`，仅对聚合后的分组过滤使用`HAVING`
- **错误做法:** 忘记将非聚合列添加到`GROUP BY`中
  - 原因: SQL要求`SELECT`中所有非聚合列都必须出现在`GROUP BY`中，这是常见的语法错误，会被考官判错
  - 正确做法: 将`SELECT`子句中所有非聚合列列在`GROUP BY`子句中
- **错误做法:** 连接表时省略`ON`子句
  - 原因: 没有`ON`，SQL会返回两个表所有行的组合，这几乎永远不是问题要求的结果
  - 正确做法: 始终添加`ON`子句，将一个表的主键关联到另一个表的外键
- **错误做法:** 对可变长度文本字段使用`CHAR(n)`
  - 原因: `CHAR`是固定长度的，会添加不必要的尾部填充。CIE要求对可变长度文本使用`VARCHAR`
  - 正确做法: 对最大长度为n的可变长度文本字段使用`VARCHAR(n)`
- **错误做法:** 在`SELECT`语句中按错误顺序书写子句
  - 原因: SQL要求子句遵循固定顺序，错误顺序会导致语法错误
  - 正确做法: 遵循以下顺序：`SELECT` → `FROM` → `JOIN/ON` → `WHERE` → `GROUP BY` → `HAVING` → `ORDER BY`

## 速查表

| 子句/命令 | 用途 | 示例 |
| --- | --- | --- |
| CREATE TABLE | 创建新表 | CREATE TABLE Customer (id INT PRIMARY KEY, name VARCHAR(100)); |
| SELECT ... FROM | 检索数据 | SELECT name FROM Customer; |
| WHERE | 过滤单个行 | WHERE points > 100 |
| GROUP BY | 对行分组以进行聚合 | GROUP BY customer_id |
| HAVING | 过滤分组结果 | HAVING SUM(value) > 1000 |
| INNER JOIN | 连接两个表 | INNER JOIN Order ON Customer.id = Order.customer_id |
| INSERT | 添加新记录 | INSERT INTO Customer (id, name) VALUES (1, 'Alice'); |
| UPDATE | 修改记录 | UPDATE Customer SET points = 200 WHERE id = 1; |
| DELETE | 删除记录 | DELETE FROM Customer WHERE id = 1; |

## 下一步

SQL是CIE A-Level计算机科学的核心技能，在试卷2的数据库单元中占大多数分值。掌握SQL语法和常见查询模式可以帮助你在该部分轻松得分，因为一旦你学会了核心规则，大多数SQL问题结构清晰且可预测。除了考试之外，SQL是软件开发、数据分析和信息系统中最实用、使用最广泛的技术技能之一，因此你在这里掌握的概念在你拿到证书后很长时间都仍然有用。接下来，你可以通过探索相关数据库概念来巩固你的知识。

- [规范化](https://www.owlsprep.com/zh/study/cie-9618-u8-normalisation/)
- [客户-服务器与分布式数据库](https://www.owlsprep.com/zh/study/cie-9618-u8-client-server-and-distributed-databases/)
- [事务与并发控制](https://www.owlsprep.com/zh/study/cie-9618-u8-transactions-and-concurrency-control/)

---

来自 [OwlsPrep](https://www.owlsprep.com) —— A-Level / IB / AP / IGCSE 免费学习指南，依据官方考纲编写。原页面：https://www.owlsprep.com/zh/study/cie-9618-u8-structured-query-language/
