Oracle 中的多表查询详解
Oracle 中的多表查询详解
在实际业务系统中,数据往往存储在多个相关的表中,通过多表查询(Multi-Table Query)才能获得完整的信息。Oracle 支持多种多表查询方式,理解和掌握这些方法,是数据库开发的必备技能。
一、什么是多表查询?
多表查询是指在 SQL 中同时访问两个或两个以上的表,通过字段之间的逻辑关系,整合并返回符合条件的数据集合。
二、多表连接分类
Oracle 中多表查询通常采用 连接(JOIN) 的方式,可以分为以下几类:
| 类型 | 关键字 | 说明 |
|---|---|---|
| 内连接(Inner Join) | INNER JOIN | 只返回两个表中满足条件的匹配记录 |
| 左外连接 | LEFT JOIN | 返回左表所有记录,右表无匹配则为 NULL |
| 右外连接 | RIGHT JOIN | 返回右表所有记录,左表无匹配则为 NULL |
| 全外连接 | FULL JOIN | 返回两个表所有记录,无匹配则为 NULL |
| 自连接 | - | 同一张表内的连接,模拟父子结构、层级结构等 |
| 交叉连接(笛卡尔积) | CROSS JOIN | 所有行组合,极少使用 |
三、准备示例数据
我们以经典的两个表为例:emp(员工表)和 dept(部门表)。
emp 表(员工):
| empno | ename | job | sal | deptno |
|---|---|---|---|---|
| 7369 | SMITH | CLERK | 800 | 20 |
| 7499 | ALLEN | SALESMAN | 1600 | 30 |
dept 表(部门):
| deptno | dname | loc |
|---|---|---|
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
四、等值连接(最常用)
SELECT e.ename, d.dname
FROM emp e
JOIN dept d ON e.deptno = d.deptno;
说明:emp 表和 dept 表通过 deptno 字段进行匹配。
五、Oracle 特有语法:旧式连接写法
在早期 Oracle 中,外连接可以通过 (+) 运算符表示。
-- 左外连接:以 emp 为主表
SELECT e.ename, d.dname
FROM emp e, dept d
WHERE e.deptno = d.deptno(+);
等价于:
SELECT e.ename, d.dname
FROM emp e
LEFT JOIN dept d ON e.deptno = d.deptno;
建议:现代开发中使用 ANSI 标准 JOIN 更清晰、可维护性更好。
六、外连接示例
1. 左外连接(LEFT JOIN)
SELECT e.ename, d.dname
FROM emp e
LEFT JOIN dept d ON e.deptno = d.deptno;
说明:显示所有员工,即使员工没有对应部门也显示,部门信息为 NULL。
2. 右外连接(RIGHT JOIN)
SELECT e.ename, d.dname
FROM emp e
RIGHT JOIN dept d ON e.deptno = d.deptno;
说明:显示所有部门,即使没有员工也显示,员工信息为 NULL。
3. 全外连接(FULL JOIN)
SELECT e.ename, d.dname
FROM emp e
FULL JOIN dept d ON e.deptno = d.deptno;
说明:显示所有员工和所有部门,即使它们没有匹配项。
七、自连接(Self Join)
用于一个表内的关联查询,如查找员工的上级。
SELECT e1.ename AS employee, e2.ename AS manager
FROM emp e1
LEFT JOIN emp e2 ON e1.mgr = e2.empno;
八、交叉连接(CROSS JOIN)
会生成表之间所有行的组合(笛卡尔积),用于特定统计分析。
SELECT e.ename, d.dname
FROM emp e
CROSS JOIN dept d;
九、多表连接查询的组合应用
可以同时连接多个表:
SELECT e.ename, d.dname, l.city
FROM emp e
JOIN dept d ON e.deptno = d.deptno
JOIN location l ON d.loc = l.loc_code;
十、实战案例
案例 1:列出所有员工及其所属部门名和工作地点
SELECT e.ename, d.dname, d.loc
FROM emp e
JOIN dept d ON e.deptno = d.deptno;
案例 2:列出没有部门的员工
SELECT e.ename
FROM emp e
LEFT JOIN dept d ON e.deptno = d.deptno
WHERE d.deptno IS NULL;
十一、多表查询注意事项
| 注意事项 | 建议做法 |
|---|---|
| 明确指定表别名 | 避免字段冲突,写法简洁 |
| 避免笛卡尔积 | JOIN 时必须有 ON 条件 |
| 优先使用标准 SQL 语法(JOIN ...) | 替代 (+) 外连接写法 |
| WHERE 与 JOIN 的区别需明确 | JOIN 负责表连接,WHERE 控制结果过滤 |
| 多表连接时注意性能和索引使用 | 特别是在大数据量表连接时 |
十二、总结
| 类型 | 用法 | 说明 |
|---|---|---|
| 内连接 | INNER JOIN ... ON | 最常用,匹配两表中满足条件的记录 |
| 外连接 | LEFT / RIGHT / FULL JOIN | 包含无匹配记录(NULL)的行 |
| 自连接 | 同一张表自己连接 | 用于层级或关联结构查询 |
| 笛卡尔积 | CROSS JOIN | 全组合,慎用 |
附录:JOIN 类型对比图(简化版)
INNER JOIN → 交集
LEFT JOIN → 左表所有 + 匹配右表
RIGHT JOIN → 右表所有 + 匹配左表
FULL JOIN → 左右表并集
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 程序员小航
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果