知识库✳

教程与手册

全部教程
  1. 01Oracle 函数手册
  2. 02性能优化手册
  3. 03Linux Shell
  4. 04Oracle 学习与演练
  5. 05网络基础学习
  6. 06数据治理与管理
返回个人网站
甲Oracle 学习教程从 SQL 到 PL/SQL 与运维
首页课程目录搜索演练场
知识库

已完成 0 / 22 章

模块一 · 入门与准备

  • 01Oracle 数据库体系结构
  • 02环境安装与连接方式
  • 03SQL*Plus 与常用工具

模块二 · SQL 查询基础

  • 04SELECT 查询基础
  • 05过滤与排序
  • 06单行函数
  • 07多表连接
  • 08分组聚合与 HAVING
  • 09子查询

模块三 · 数据与对象

  • 10DML 与事务控制
  • 11表与数据类型
  • 12约束
  • 13索引与执行计划
  • 14视图、序列与同义词

模块四 · PL/SQL 编程

  • 15PL/SQL 块与变量
  • 16流程控制与游标
  • 17存储过程与函数
  • 18触发器
  • 19异常处理

模块五 · 运维与进阶

  • 20用户与权限管理
  • 21表空间与存储管理
  • 22备份与恢复
❖

Oracle 学习教程

返回个人网站知识库

示例代码基于 Oracle AI Database 26ai / 23ai,查询示例使用官方 HR 示例方案。

以 Next.js 16 · Tailwind CSS v4 · HeroUI v3 装帧

04
  1. 首页
  2. 课程目录
  3. SELECT 查询基础

第 4 章◆入门◆建议 35 分钟◆模块二 · SQL 查询基础

SELECT 查询基础

掌握查询语句的骨架、列别名、去重、表达式计算与 NULL 的正确处理。

学完这一章,你应该能

  • 写出规范的 SELECT 语句
  • 会用别名、去重和算术表达式
  • 理解 NULL 的语义并会用 NVL/COALESCE 处理

4.1语句骨架与书写规范

SQL 不区分关键字大小写,但为了可读性,通常关键字大写、对象名小写。语句的执行顺序和你书写的顺序并不一致,这一点在学聚合函数时非常关键。

  • 书写顺序:SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY
  • 实际执行顺序:FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
  • 因为 SELECT 在 WHERE 之后执行,所以 WHERE 里不能使用 SELECT 中定义的列别名
查询员工基本信息
SELECT employee_id,          -- 员工编号
       last_name,            -- 姓
       first_name,           -- 名
       hire_date,            -- 入职日期
       salary                -- 工资
FROM   employees
ORDER  BY hire_date DESC;
在你的专用沙箱里执行打开演练场

4.2别名、去重与表达式

别名与拼接
-- 别名有三种写法
SELECT last_name AS name, salary "月薪", salary * 12 AS "年薪"
FROM   employees;

-- 字符串拼接使用 ||,不是 +
SELECT last_name || ' 的年薪是 ' || (salary * 12) AS info
FROM   employees
WHERE  employee_id <= 105;
在你的专用沙箱里执行打开演练场
去重:DISTINCT 作用于整行组合
-- 错误理解:以为只对 job_id 去重
SELECT DISTINCT job_id, department_id FROM employees;

-- 上句等价于对 (job_id, department_id) 组合去重
SELECT job_id, department_id
FROM   employees
GROUP  BY job_id, department_id;
在你的专用沙箱里执行打开演练场

4.3NULL 是个陷阱

NULL 表示「未知」,不是 0 也不是空字符串。任何与 NULL 的算术运算结果都是 NULL,与 NULL 的比较结果也不是 TRUE/FALSE 而是 UNKNOWN。这是初学者最容易写出错误查询的地方。

  • NULL + 1 结果是 NULL,不是 1
  • 判断 NULL 必须用 IS NULL / IS NOT NULL,不能用 = NULL
  • NULL 参与排序时,Oracle 默认 NULL 最大(升序排在最后)
  • 聚合函数(SUM/AVG/COUNT(列))会忽略 NULL,但 COUNT(*) 不会
处理 NULL 的三种函数
SELECT employee_id,
       salary,
       commission_pct,
       -- NVL:两参数,为空则取第二个
       NVL(commission_pct, 0)                      AS nvl_demo,
       -- NVL2:非空取第二个,为空取第三个
       NVL2(commission_pct, '有提成', '无提成')      AS nvl2_demo,
       -- COALESCE:从左到右取第一个非空值,参数可变
       COALESCE(commission_pct, 0.1, 0)            AS coalesce_demo,
       -- 正确计算总收入:NULL 会污染整个表达式
       salary + salary * NVL(commission_pct, 0)    AS income
FROM   employees
WHERE  employee_id IN (100, 145, 149);
在你的专用沙箱里执行打开演练场

提示 看到「不该为空的地方算出来是空」,先检查表达式里有没有未处理的 NULL。这是实战中最高频的坑之一。

练习

3 题 · 先自己写,再展开对照

提示 回忆语句的实际执行顺序。

参考答案

因为 WHERE 在 SELECT 之前执行。

实际执行顺序:FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY。
WHERE 执行时别名还不存在,所以会报 ORA-00904。

唯一的例外是 ORDER BY——它在 SELECT 之后执行,所以可以引用别名。

自评要点

  • 说出 WHERE 早于 SELECT 执行
  • 知道 ORDER BY 是唯一例外

参考答案

NULL 会污染整个算术表达式:salary * commission_pct 在 commission_pct
为 NULL 时结果是 NULL,而不是 salary。

正确写法(先处理 NULL):
SELECT employee_id,
       salary + salary * NVL(commission_pct, 0) AS income
FROM   employees;

自评要点

  • 知道 NULL 参与算术运算结果仍是 NULL
  • 用 NVL / COALESCE 把 NULL 兜成 0

参考答案

去重的是 (job_id, department_id) 的组合,不是单独某一列。

如果要按单列去重,需要明确只选那一列(或改用 GROUP BY)。
想验证可以对比 SELECT COUNT(*) 与 SELECT COUNT(*) FROM (SELECT DISTINCT ...)。

自评要点

  • DISTINCT 作用于整行/整个列组合
  • 不是对第一列单独去重
← 上一章

SQL*Plus 与常用工具

下一章 →

过滤与排序