关系模型、SQL 与数据库基础
001 表中存在多个能唯一标识行的候选键时,选主键的合理原则是?
难度: 基础
- A. 选择最短、稳定且不随业务变化的候选键作为主键
- B. 表中第一个整数列天然就是主键
- C. 主键必须使用业务可见的自然键
- D. 主键列允许为 NULL,由应用保证不重复
查看答案与解析
正确答案A
正确原因: 主键参与聚簇与索引定位,短小稳定的键让索引更紧凑并减少后续迁移成本。
关键边界: 业务唯一性可以由 UNIQUE 约束承担,主键优先考虑稳定性与体积。
错误选项辨析: 第一个整数列不一定是候选键,自然键可能变化,PostgreSQL 主键列不允许 NULL。
002 关于 SQL 的执行顺序,下列说法正确的是?
难度: 基础
- A. 逻辑处理顺序与书写顺序不同,物理执行由优化器决定
- B. 数据库严格按 SQL 书写顺序执行
- C. ORDER BY 在 WHERE 之前处理
- D. SELECT 里定义的别名可以在 WHERE 中直接使用
查看答案与解析
正确答案A
正确原因: 逻辑顺序大致为 FROM、WHERE、GROUP BY、HAVING、SELECT、ORDER BY,且实际访问路径由优化器决定。
关键边界: WHERE 阶段尚未生成 SELECT 别名,因此不能引用;ORDER BY 在 SELECT 之后。
错误选项辨析: 书写顺序不等于执行顺序,WHERE 在前、别名在后,这三个说法都与逻辑顺序矛盾。
003 执行 WHERE col = NULL 时会发生什么?
难度: 基础
- A. col 为 NULL 的行会被匹配到
- B. 比较结果恒为 UNKNOWN,任何行都不会被选中
- C. NULL = NULL 结果为 TRUE,因此能查到空值行
- D. 查询会直接报语法错误
查看答案与解析
正确答案B
正确原因: PostgreSQL 采用三值逻辑,NULL 与任何值(包括 NULL)比较都返回 UNKNOWN,WHERE 只保留 TRUE。
关键边界: 判断空值必须用 IS NULL、IS NOT NULL,或用 IS NOT DISTINCT FROM 做 NULL 安全比较。
错误选项辨析: NULL 不会被等号匹配,NULL 不等于 NULL,该写法也不会报错。
004 过滤普通行与过滤聚合结果,分别应使用哪个子句?
难度: 基础
- A. 普通行用 HAVING,聚合结果用 WHERE
- B. 普通行用 WHERE,聚合结果用 HAVING
- C. 两者可以随意混用,语义相同
- D. HAVING 只能用于没有 GROUP BY 的查询
查看答案与解析
正确答案B
正确原因: WHERE 在分组前过滤行,HAVING 在分组聚合后过滤分组,作用阶段不同。
关键边界: 不依赖聚合的条件应尽量放入 WHERE,减少进入聚合的数据量。
错误选项辨析: 二者阶段不同不可互换,HAVING 依赖 GROUP BY 语义,三个错误选项都混淆了过滤阶段。
005 COUNT(*) 与 COUNT(column) 的区别是?
难度: 基础
- A. 两者在所有情况下结果完全相同
- B. COUNT(column) 一定比 COUNT(*) 更快
- C. COUNT(*) 统计行数,COUNT(column) 只统计该列非 NULL 的行
- D. COUNT(*) 会把 NULL 行计入该列的非空统计
查看答案与解析
正确答案C
正确原因: COUNT(*) 对每一行计数,COUNT(column) 忽略 NULL,因此空值会少计。
关键边界: 外连接或重复连接可能放大行数,计数前要确认结果基数。
错误选项辨析: 列含 NULL 时两者不同,COUNT(column) 不会更快,COUNT(*) 不统计具体列值。
006 关于 DISTINCT 的行为,正确的是?
难度: 基础
- A. 加上 DISTINCT 一定能让查询更快
- B. DISTINCT 只对第一列去重
- C. 对最终选择列表整体去重,通常需要排序或哈希等额外开销
- D. DISTINCT 会在 WHERE 之前执行
查看答案与解析
正确答案C
正确原因: DISTINCT 以整个结果行做去重,需要额外的排序或哈希运算。
关键边界: 重复行可能来自错误连接,不能总用 DISTINCT 掩盖问题。
错误选项辨析: DISTINCT 通常增加成本,对整行生效,且在 WHERE 过滤之后处理。
007 对分页查询 SELECT * FROM t ORDER BY created_at LIMIT 20,正确认识是?
难度: 基础
- A. 只要数据不变,每次查询顺序一定相同
- B. created_at 相同的行分页时不会漂移
- C. 分页查询可以完全省略 ORDER BY
- D. 没有 ORDER BY 时行序不受保证,分页还需加唯一键确保稳定
查看答案与解析
正确答案D
正确原因: 只有 ORDER BY 才承诺顺序,且排序键不唯一时同值行跨页可能漂移。
关键边界: 稳定分页应使用 created_at 与唯一 id 的组合排序。
错误选项辨析: 无排序不保证顺序,非唯一排序键无法防止漂移,省略 ORDER BY 无法稳定分页。
008 UNION 与 UNION ALL 的区别是?
难度: 基础
- A. UNION ALL 会自动去重,总是更安全
- B. UNION 比 UNION ALL 更快
- C. 两者结果永远完全相同
- D. UNION 去重,UNION ALL 保留全部行且通常更快
查看答案与解析
正确答案D
正确原因: UNION 需要去除重复行,UNION ALL 直接拼接,少一步去重开销。
关键边界: 是否去重由业务集合语义决定,不能只图快。
错误选项辨析: UNION ALL 不去重,UNION 更慢,两者在存在重复行时结果不同。
009 未加双引号的标识符(如表名、列名)在 PostgreSQL 中会怎样?
难度: 基础
- A. 统一折叠为小写,加双引号后才大小写敏感
- B. 统一转换为大写
- C. 原样保留书写时的大小写
- D. 大小写混合的标识符会直接报错
查看答案与解析
正确答案A
正确原因: 未加引号的标识符会被折叠成小写,这是 PostgreSQL 的标识符规则。
关键边界: 加双引号的标识符大小写敏感且区分空格,混用会显著增加维护成本。
错误选项辨析: PG 折叠为小写而非大写,不保留原样,也不会报错。
010 PostgreSQL 中关于事务与自动提交,正确的是?
难度: 基础
- A. 默认每个语句独立提交,显式 BEGIN 开启多语句事务
- B. 默认关闭自动提交,所有语句共享一个事务
- C. DDL 会隐式提交且无法回滚
- D. 事务必须显式指定隔离级别才能开始
查看答案与解析
正确答案A
正确原因: PG 默认 autocommit 开启,多条语句要用 BEGIN 或 START TRANSACTION 包裹。
关键边界: PG 的多数 DDL 可以参与事务并回滚,这与部分数据库不同。
错误选项辨析: 默认是自动提交,DDL 可回滚,事务默认使用当前隔离级别即可开始。
011 在 LEFT JOIN 中,把右表过滤条件写在 WHERE 而不是 ON 里,效果是?
难度: 进阶
- A. 结果完全相同,只是写法不同
- B. 会把左连接变成内连接,丢失不匹配的左表行
- C. 只会过滤右表行,左表行一定保留
- D. WHERE 条件会被优化器忽略
查看答案与解析
正确答案B
正确原因: ON 决定连接保留哪些行,WHERE 在连接完成后过滤结果,NULL 扩展行会被过滤掉。
关键边界: 需要保留左表全部行时,对右表的过滤必须放在 ON 中。
错误选项辨析: 两者结果不同,WHERE 会过滤掉左连接产生的 NULL 行,也不会被忽略。
012 子查询含 NULL 时,NOT IN (SELECT …) 的结果是?
难度: 进阶
- A. 返回所有不匹配的行,NULL 不影响
- B. 结果为空集(没有任何行满足),因为 NULL 参与比较得到 UNKNOWN
- C. 直接报错,必须改写为 NOT EXISTS
- D. 返回 NULL 行本身
查看答案与解析
正确答案B
正确原因: NOT IN 对每行做不等于比较,与 NULL 比较为 UNKNOWN,整行被过滤。
关键边界: 需要这种语义时改用 NOT EXISTS 或显式排除 NULL。
错误选项辨析: 结果为空而非正常返回,不报错,返回的也不是 NULL 行。
013 SELECT 列表中包含非聚合列时,PostgreSQL 的 GROUP BY 规则是?
难度: 进阶
- A. 任意列都可以不分组,数据库自动选择
- B. 只有主键列可以不分组
- C. 非聚合列必须全部出现在 GROUP BY 中,否则报错
- D. 非聚合列会自动取最大值
查看答案与解析
正确答案C
正确原因: PG 要求 SELECT 中的非聚合列都出现在 GROUP BY 中,否则返回错误。
关键边界: 若按主键分组,PG 支持函数依赖,可直接选择该表的其他列。
错误选项辨析: 列不会自动选择或取最大值,主键依赖是特例而非普遍规则。
014 大 OFFSET 分页性能差,更推荐的方案是?
难度: 进阶
- A. 把 OFFSET 改大让一次返回更多
- B. 去掉 ORDER BY 让查询更快
- C. 用 WHERE id > 上一页最后 id 的键集分页,扫描行数恒定
- D. 先全表加载到应用内存再切片
查看答案与解析
正确答案C
正确原因: 键集分页利用索引直接定位起点,避免扫描并丢弃大量已翻过的行。
关键边界: 键集分页要求排序键唯一且业务支持按游标翻页。
错误选项辨析: 改大 OFFSET 只会更慢,去排序无法稳定分页,全量加载不可扩展。
015 关于数据库视图,正确的是?
难度: 进阶
- A. 视图会复制一份数据快照,查询视图更快
- B. 视图创建后数据就固定不变
- C. 任何视图都可以直接 INSERT、UPDATE
- D. 视图保存查询定义而非数据,查询时按定义实时执行
查看答案与解析
正确答案D
正确原因: 视图本质是存储的查询,每次访问都基于当前表数据执行。
关键边界: 只有满足可更新视图条件的简单视图才支持写入。
错误选项辨析: 视图不存数据快照,数据随基表变化,写入有严格限制。
016 SELECT MAX(col) FROM 空表 的结果是?
难度: 基础
- A. 返回 0
- B. 返回空字符串
- C. 直接报错
- D. 返回 NULL,聚合函数对空输入返回 NULL(COUNT 除外)
查看答案与解析
正确答案D
正确原因: 除 COUNT 外,聚合函数对空集返回 NULL,MAX 也不例外。
关键边界: 需要把空集当作 0 时,可用 COALESCE(MAX(col), 0) 处理。
错误选项辨析: 返回 0 或空串都是错误预期,PG 不报错而是返回 NULL。
017 为什么推荐用参数化查询而不是字符串拼接 SQL?
难度: 实战
- A. 参数与 SQL 语句分离,从根上避免 SQL 注入
- B. 参数化查询一定比拼接更快
- C. 只有 PostgreSQL 支持参数化
- D. 参数化查询无法使用索引
查看答案与解析
正确答案A
正确原因: 参数以协议形式传递,不参与语句文本拼接,用户输入不会被解析成代码。
关键边界: 参数化不影响索引使用,占位符在优化器眼中是参数。
错误选项辨析: 参数化主要解决安全问题而非性能,多数数据库都支持,也不阻碍索引。
018 外键约束对写入性能的主要影响是?
难度: 实战
- A. 外键完全免费,没有任何开销
- B. 每次插入、更新或删除都要校验引用完整性并可能加锁
- C. 外键会禁用索引,只能全表扫描
- D. 外键只影响 SELECT,不影响写入
查看答案与解析
正确答案B
正确原因: 外键检查需要访问被引用表并加锁,父行删除时还会阻塞子表相关操作。
关键边界: 高并发导入等场景可评估延迟校验与批量加载顺序。
错误选项辨析: 外键有成本,不影响索引使用,对写入有明显影响。
019 在 PostgreSQL 中执行 DROP TABLE 之前开启了事务,之后 ROLLBACK,结果是?
难度: 进阶
- A. DDL 已隐式提交,表仍然被删除
- B. 报错并拒绝回滚
- C. 表被保留,PG 的多数 DDL 可以随事务回滚
- D. 只回滚数据,表结构保持删除状态
查看答案与解析
正确答案C
正确原因: PostgreSQL 的事务性 DDL 允许回滚表结构变更,这是与 MySQL 的显著差异。
关键边界: 并非所有操作都可回滚,例如部分并发建索引命令有限制。
错误选项辨析: DDL 不隐式提交,可以回滚,结构变更同样受事务保护。
020 在 WHERE 中引用 SELECT 列表里的别名(如 WHERE total > 10),结果是?
难度: 基础
- A. 正常执行,别名在 WHERE 中可用
- B. 数据库自动把别名当常量处理
- C. 会跳过过滤直接返回全部行
- D. 报错,因为 WHERE 阶段还没有生成 SELECT 别名
查看答案与解析
正确答案D
正确原因: 逻辑处理顺序中 WHERE 先于 SELECT,别名在该阶段不存在。
关键边界: 这类过滤应改用 HAVING(聚合场景)或把计算放入子查询。
错误选项辨析: 别名在 WHERE 不可用,不会当常量,也不会被静默跳过。