Oracle DQL精髓:从基础到高级实战

说明:Oracle 和 MySQL SQL 语法存在不少差异,本篇聚焦 Oracle 特有的写法、规则与工具,适合运维、数据库入门学习。

1.1 DQL

DQL (Data Query Language):数据查询语言,使用 SQL 语句实现对数据表的查询。 SQL:Structured Query Language,结构化查询语言。 Oracle 的 DQL 核心就是 SELECT 语句,语法结构完整,支持简单单表查询、多表关联、分组统计、排序、分析查询等各类业务场景。

1.1.1 基本语法结构

Oracle DQL 标准语法:

复制代码
SELECT [DISTINCT] 列名1, 列名2, ... | *
FROM 表名
[WHERE 条件]
[GROUP BY 列名]
[HAVING 分组后筛选条件]
[ORDER BY 列名 [ASC|DESC] [NULLS FIRST | NULLS LAST]];
  • SELECT 子句:指定需要查询的列、表达式;* 代表查询全部列
  • FROM 子句:指定数据来源表
  • WHERE:行过滤,分组之前筛选原始数据
  • GROUP BY:按照指定字段分组,配合聚合函数统计
  • HAVING:对分组统计之后的结果再次过滤(可以使用聚合函数)
  • ORDER BY:结果集排序,Oracle 独有 NULLS FIRST / NULLS LAST 控制空值排在最前或最后

关键字说明:

  1. DISTINCT:去除结果集中重复行

  2. 虚拟表 DUAL:Oracle 特有,用于简单计算、函数测试,没有实际业务数据

    -- Oracle 特有,测试计算
    SELECT 1+3 FROM DUAL;

WHERE 支持条件:

  • 比较运算符:=, >, <, >=, <=, !=, <>
  • 范围:BETWEEN ... AND ...
  • 集合:IN(值1,值2,...)
  • 模糊匹配:LIKE,% 匹配任意多个字符,_ 匹配单个字符
  • 空值判断:IS NULL / IS NOT NULL,不能使用 = NULL
  • 逻辑运算符:AND, OR, NOT,优先级:NOT > AND > OR

ORDER BY 排序:

  • ASC:升序,默认
  • DESC:降序
  • 多列排序:先按第一列排序,第一列相同再按第二列
  • NULLS FIRST:空值放最前面;NULLS LAST:空值放最后(MySQL 没有这个写法)

1.1.2 SELECT 的基础使用

1.1.2.1 SELECT 语句的功能

基础格式:

复制代码
SELECT *|{[DISTINCT] column [alias],...}
FROM table;
  • SELECT:指定展示哪些列,* 代表所有列
  • FROM:指定数据来自哪张表

示例:

复制代码
-- 查询employees表所有列
SELECT * FROM employees;

-- 查询指定字段:员工编号、名字
SELECT employee_id,first_name FROM employees;
1.1.2.2 编写 SQL 语句的注意事项
  1. SQL 语句不区分大小写
  2. 可以单行书写,也可以拆分为多行
  3. 关键字不能缩写、不能跨行拆分
  4. 推荐一个子句单独一行,增加可读性,适当缩进
  5. 结束符:
    • SQL Developer:单条语句分号可省略;批量执行多条脚本必须加分号 ;
    • SQL*Plus:每条 SQL 必须以分号 ; 结尾

工具小区别:

  • SQL*Plus:Oracle 原生命令行工具,执行 SQL、PL/SQL、管理脚本
  • SQL Developer:图形化 IDE,开发、调试、管理一体,可视化更强

列头对齐规则:

  • SQL Developer:字符标题默认左对齐,标题默认大写
  • SQL*Plus:字符、日期列标题左对齐;数字列标题右对齐,标题默认大写

1.1.3 SELECT 语句中算术表达式和 NULL 值

1.1.3.1 算术表达式

支持数字、日期类型做四则运算,和数学运算优先级一致,括号可以改变优先级。

复制代码
-- DUAL测试运算
SELECT 99*99 FROM DUAL;
SELECT (1+2)*3 FROM DUAL;

-- 表内字段运算:底薪+300
SELECT last_name, salary, salary + 300 FROM employees;

-- 不加括号:先乘后加
SELECT last_name, salary, 12*salary+100 FROM employees;
-- 加括号:先算加薪再乘以12
SELECT last_name, salary, 12*(salary+100) FROM employees;
1.1.3.2 NULL 空值

空值含义:未知、未分配、不适用的值。 ⚠️ NULL 不等于 0,也不等于空格。

复制代码
-- 查看包含空值字段的数据(提成commission_pct很多员工为空)
SELECT last_name, job_id, salary, commission_pct FROM employees;

重点规则:任何数字和 NULL 做算术运算,结果一定是 NULL

复制代码
-- 提成字段为NULL时,整行计算结果为NULL
SELECT last_name, 12*salary*commission_pct FROM employees;

后续可以用 NVL() 函数处理 Oracle 空值,避免计算结果为空。

1.1.4 列别名

作用:给查询出来的列重命名,适合计算字段美化展示。 语法:列名后直接写别名,或者加 AS; 如果别名包含空格、特殊字符、需要区分大小写,必须使用双引号包裹(Oracle 单引号是字符串,双引号用来标记标识符,这点和 MySQL 不一样!)

复制代码
-- AS简写,简单别名,不需要引号
SELECT last_name AS name, commission_pct comm FROM employees;

-- 别名带空格,大小写敏感,使用双引号
SELECT last_name "Name" , salary*12 "Annual Salary" FROM employees;

踩坑提醒:Oracle 单引号 ' ' 代表字符串字面量,双引号 " " 用来标记列名、表名别名。

1.1.5 串联运算符,文字字符串,替代引号运算符和 DISTINCT 关键字

1.1.5.1 连接符 ||

Oracle 使用 || 做字符串拼接(MySQL 使用 CONCAT() 函数),把多个字段、文本拼接成一列返回。

复制代码
-- 姓名:岗位
SELECT last_name||' : '||job_id AS "Employees" FROM employees;

-- 直接拼接姓名和岗位,中间无分隔
SELECT last_name || job_id AS "Employee Details" FROM employees;
1.1.5.2 文字字符串

字面常量:字符、数字、日期,字符和日期必须放在单引号里面,每行都会拼接这个文本。

复制代码
SELECT last_name ||' is a '||job_id AS "Employee Details" FROM employees;
1.1.5.3 替代引号运算符 q'[]'

场景:字符串内部包含大量单引号,正常写法需要转义,非常麻烦。 q'[ 内容 ]' 自定义边界符,中括号里面的内容直接原样写,不需要转义单引号。

复制代码
-- 原生写法,需要转义,可读性差
SELECT '''HELLO WORLD''' FROM DUAL;

-- q'[]' 替代引号,里面的单引号不用转义
SELECT department_name || q'[ Department's Manager Id: ]' || manager_id AS "Department and Manager"
FROM departments;

分隔符可以换:q'{}'、q'()' 都可以,成对即可。

1.1.5.4 DISTINCT 去重

默认查询会返回全部行,包含重复;加上 DISTINCT 对整行组合去重。

复制代码
-- 不去重,会重复出现部门编号
SELECT department_id FROM employees;

-- 去重,每个部门编号只出现一次
SELECT DISTINCT department_id FROM employees;
1.1.5.5 查看表结构 DESCRIBE

DESC / DESCRIBE 查看表字段、类型、是否为空,SQL*Plus / SQL Developer 命令行可用,不是标准 SQL,是客户端命令。

复制代码
-- 简写
DESC employees;
-- 全写,效果一致
DESCRIBE employees;
相关推荐
分布式存储与RustFS1 小时前
CI 老被 Docker Hub 的 429 卡住,自建 Registry 把镜像搬进内网
运维·docker·开源·镜像仓库·对象存储·ci·rustfs
Ruiery1 小时前
Linux 6.6内核内存管理深度解析(十七):vmalloc — 内核要“虚拟连续“就够:物理页逐个凑,页表来连
linux·运维·服务器
pt10431 小时前
Cisco设备网络安全系列-19:网络安全事件驱动与调整
运维·网络
m0_639906941 小时前
MySQL 锁机制详解|表锁、行锁、意向锁,死锁成因与解决方案
数据库·mysql
sxgzzn1 小时前
如何利用无人机提升光伏巡检效率?
运维·重构·无人机·开关柜局放在线监测·光伏运维管理系统
进击的荆棘1 小时前
MySQL——在ubuntu环境下安装MySQL
数据库·mysql·ubuntu
R²AIN SUITE2 小时前
企业智能体平台私有化部署需要什么服务器?CPU、内存、显卡与项目管理集成的7个评估项
运维·服务器
hey you~2 小时前
云呼叫中心坐席自动分配实战:ACD 策略、Redis+Lua 实现与排查清单
数据库·redis·lua·云呼叫中心·acd·坐席分配·坐席状态机
刚入门的大一新生2 小时前
Linux-线程封装
linux·运维·服务器