数据库与 SQL:练习题及解析

免费的数据库与 SQL选择练习题,附提示和解析,分三个难度:关键术语与事实, 概念应用, 案例与分析。

免费练习题简单

哪种约束确保某列永远不能留空(NULL)?

下一题 →
免费练习数据库与 SQL立即练习数据库与 SQL每天 5 道免费题目,无需绑定银行卡。

练习内容

  1. 简单关键术语与事实
  2. 中等概念应用
  3. 困难案例与分析

从零开始学习数据库与 SQL

1什么是关系数据库

关系数据库把数据存储在表中。表看起来像电子表格:每一行是一条记录,每一列是一种属性。

一家商店可能有一张表 customers,列为 id、name 和 city,还有一张表 orders,列为 id、customer_id 和 total。

主键是唯一标识每一行的一列或一组列。它永远不能重复,也永远不能为空。这里就是每张表的 id。

外键是引用另一张表主键的列。在 orders 中,customer_id 说明是哪位客户下了订单。

表就是这样关联的:一位客户可以有许多订单,但每个订单只属于一位客户。这是一对多关系。

SQL(结构化查询语言)是你用来创建表、修改数据以及对数据提问的语言。

自测 什么是主键?
  1. 使搜索更快的索引
  2. 唯一标识每一行的一列或一组列
  3. 引用另一张表中某一行的列
  4. 每张表的第一列

答案: 唯一标识每一行的一列或一组列. 主键是唯一的且从不为 NULL,所以它恰好选出一行。引用另一张表的列是外键。

2用 SELECT 读取数据

大多数题目都涉及 SELECT 语句。它由子句构成,书写顺序总是这样:

SELECT … FROM … WHERE … GROUP BY … HAVING … ORDER BY …
  • SELECT 列出你想要的列。DISTINCT 去掉重复的行。
  • FROM 指明表,或连接在一起的几张表。
  • WHERE 只保留满足条件的行,例如 WHERE total > 20。
  • GROUP BY 把值相同的行归为一组,这样你就可以按组计数或求和。
  • HAVING 只保留满足条件的组。它可以使用聚合函数,而 WHERE 不可以。
  • ORDER BY 对结果排序,默认升序;加 DESC 则最高的在前。

聚合函数把许多行汇总成一个值:COUNT、SUM、AVG、MIN 和 MAX。

数据库并不按你书写的顺序运行这些子句。它先运行 FROM,然后是 WHERE、GROUP BY、HAVING、SELECT,最后是 ORDER BY。

其他语句改变数据:INSERT 添加行,UPDATE 修改行,DELETE 删除行。CREATE、ALTER 和 DROP 改变表本身。

自测 你只想要订单数多于 5 个的客户。哪个子句对 COUNT(*) > 5 进行过滤?
  1. DISTINCT
  2. HAVING
  3. ORDER BY
  4. WHERE

答案: HAVING. 计数只有在行被分组之后才存在,而 HAVING 过滤的是组。WHERE 在分组之前运行,所以它不能使用 COUNT 之类的聚合函数。

3连接、规范化和事务

连接(join)使用条件把两张表的行组合起来,通常是外键 = 主键:

FROM customers c JOIN orders o ON o.customer_id = c.id
  • INNER JOIN(或 JOIN)只保留在两张表中都有匹配的行。
  • LEFT JOIN 保留左表的每一行。没有匹配的地方,右表的列为 NULL。
  • NULL 表示值缺失或未知。用 IS NULL 来检验,永远不要用 = NULL。

规范化拆分表,使每个事实只存储一次。这避免了在多处更新同一个事实。

  • 1NF:每个单元格只含一个原子值,没有重复的组。
  • 2NF:满足 1NF,并且每个非键列都依赖于整个键,而不是复合键的一部分。
  • 3NF:满足 2NF,并且没有非键列依赖于另一个非键列。

事务把若干语句组合成一个单元。COMMIT 使它永久生效,ROLLBACK 撤销它。事务遵循 ACID:原子性(要么全做要么全不做)、一致性、隔离性和持久性。

自测 一位客户没有下过任何订单。在 customers LEFT JOIN orders 中,这位客户会怎样?
  1. 查询失败并报错
  2. 表中每有一个订单,这位客户就出现一次
  3. 这位客户不出现在结果中
  4. 这位客户出现一次,订单列为 NULL

答案: 这位客户出现一次,订单列为 NULL. LEFT JOIN 保留左表的每一行,并用 NULL 填充缺失的右侧。把这位客户排除在外是 INNER JOIN 的做法。

4分步方法

要写一个查询,或判断一个给定的查询返回什么:

  1. 找出存放数据的表,以及它们如何通过键关联。
  2. 写出带连接的 FROM。当没有匹配的行也必须保留时,选择 LEFT JOIN。
  3. 对单行的条件添加 WHERE。
  4. 如果题目说“每个”或“针对每一个”,添加 GROUP BY 和聚合函数。
  5. 对聚合结果的条件添加 HAVING,如果顺序重要,再加 ORDER BY。
  6. 在一个小例子上检验结果:按数据库运行的顺序,列出每个子句之后的行。

对于理论题,先说出概念(键、连接类型、范式、ACID 属性),然后选与其定义相符的选项。

5例题讲解

跟着每一步走。打开下一步之前,先试着预测它。

例题讲解

表 customers 有行 (1, Ana)、(2, Ben) 和 (3, Cas)。表 orders 有行 (id, customer_id) = (10, 1)、(11, 1)、(12, 2) 和 (13, 1)。这个查询返回什么?SELECT c.name, COUNT(o.id) FROM customers c LEFT JOIN orders o ON o.customer_id = c.id GROUP BY c.name

1

运行 FROM 和连接

每位客户与带有其 id 的订单配对。Ana 匹配订单 10、11 和 13。Ben 匹配订单 12。

Cas 没有订单。因为是 LEFT JOIN,Cas 留在结果中,o.id 为 NULL。

2

列出连接后的行

  • Ana, 10
  • Ana, 11
  • Ana, 13
  • Ben, 12
  • Cas, NULL

一共 5 行。

3

按 name 分组

GROUP BY c.name 形成三个组:Ana 有 3 行,Ben 有 1 行,Cas 有 1 行。

4

按组计数

COUNT(o.id) 只统计不为 NULL 的值。Ana 得 3,Ben 得 1。

Cas 有一行,但它的 o.id 是 NULL,所以 Cas 得 0。

5

检验答案

Ana、Ben 和 Cas 合计有 3 + 1 + 0 = 4 个订单,与 orders 的行数相同。如果改用 COUNT(*),Cas 会错误地得到 1,因为 COUNT(*) 统计的是这一行本身。

答案

Ana 3,Ben 1,Cas 0。

6常见错误

  • 在 WHERE 中使用聚合函数。对 COUNT、SUM 或 AVG 的条件应放在 HAVING 中。
  • 写成 = NULL。任何与 NULL 的比较结果都是未知;要用 IS NULL 或 IS NOT NULL。
  • 在没有匹配的行也必须保留时使用 INNER JOIN。应使用 LEFT JOIN。
  • 忘了连接条件。没有 ON,每一行会与每一行配对(交叉连接)。
  • 选择既不在 GROUP BY 中,也不在聚合函数内的列。
  • 混淆 DELETE(删除行)和 DROP TABLE(删除整张表)。
  • 运行不带 WHERE 的 UPDATE 或 DELETE。它会改变表中的每一行。
自测 一张表有 10 行,列 col 在每一行都是 NULL。SELECT COUNT(col) 返回什么?
  1. 0
  2. 10
  3. 1
  4. NULL

答案: 0. COUNT(col) 只统计不为 NULL 的值,所以返回 0。COUNT(*) 统计行数,会返回 10。

7考试题是什么样的

  • 简单:关键术语和事实。SELECT、WHERE、ORDER BY 或 DELETE 的作用,主键和外键,NULL 的含义。
  • 中等:应用概念。适合某项任务的查询、WHERE 与 HAVING、内连接与外连接、范式、ACID。
  • 困难:案例与分析。子查询、隔离级别及其异常、BCNF、窗口函数、索引与查询性能、SQL 注入。

给出查询时,按 FROM、WHERE、GROUP BY、HAVING、SELECT、ORDER BY 的顺序在几行数据上跟踪它。大多数陷阱在三行之内就会显现。

在应用中一步一步地学在应用中一步一步地学

例题

例题 1简单

UNION 对两个 SELECT 查询的结果做什么?

  1. A按某个键把它们左右并排连接
  2. B只保留同时出现在两者中的行
  3. C把它们合并为一个结果并去除重复行
  4. D只保留出现在第一个查询中而不在第二个查询中的行
显示提示
  1. 两个查询必须有相同数量且类型兼容的列。
  2. 两个错误答案已被划掉。剩下的两个中有一个是正确的。
显示答案和解析

为什么是这个答案

UNION 把两个查询的行叠加起来并去除重复;UNION ALL 保留重复行。

答案

C · 把它们合并为一个结果并去除重复行
例题 2中等

当 WHERE 子句没有匹配任何行时,SELECT SUM(amount) FROM orders 返回什么?

  1. A报错
  2. B0
  3. CNULL
  4. D空字符串
显示提示
  1. 在这一点上 SUM 与 COUNT 不同。
  2. 两个错误答案已被划掉。剩下的两个中有一个是正确的。
显示答案和解析

为什么是这个答案

SUM、AVG、MIN 和 MAX 在空集上返回 NULL,而 COUNT 返回 0;COALESCE(SUM(amount), 0) 则会返回 0。

答案

C · NULL
例题 3困难

SELECT name, dept, AVG(salary) OVER (PARTITION BY dept) FROM emp 返回什么?

  1. A只返回工资高于本部门平均值的员工
  2. B每一行员工记录以及其所在部门的平均工资
  3. C报错,因为 name 不在 GROUP BY 中
  4. D每个部门一行及其平均工资
显示提示
  1. 窗口函数不会合并行。
  2. 两个错误答案已被划掉。剩下的两个中有一个是正确的。
显示答案和解析

为什么是这个答案

与 GROUP BY 不同,窗口函数保留每一行输入,并加上一个在其分区(这里是部门)上计算出的值。

答案

B · 每一行员工记录以及其所在部门的平均工资

问与答

什么是数据库与 SQL?

一家商店可能有一张表 customers,列为 id、name 和 city,还有一张表 orders,列为 id、customer_id 和 total。

表就是这样关联的:一位客户可以有许多订单,但每个订单只属于一位客户。这是一对多关系。

如何一步步学习数据库与 SQL?
  1. 什么是关系数据库
  2. 用 SELECT 读取数据
  3. 连接、规范化和事务
  4. 分步方法
  5. 例题讲解
  6. 常见错误
  7. 考试题是什么样的
数据库与 SQL练习包括哪些内容?
  • 简单: 关键术语与事实
  • 中等: 概念应用
  • 困难: 案例与分析

每道题有四个选项,只有一个正确。 卡住了?先打开一个小提示,需要时再查看完整解析。

练习方式

  • 每道题有四个选项,只有一个正确。
  • 卡住了?先打开一个小提示,需要时再查看完整解析。
  • 你的进度、错题和收藏的题目都会保留,方便考前复习。

包含此主题的课程

计算机科学中的更多主题

可打印练习卷

免费练习数据库与 SQL立即练习数据库与 SQL每天 5 道免费题目,无需绑定银行卡。