[Oracle数据库] Oracle 多表查询
在 Oracle 数据库操作中,单表查询只能满足简单的数据获取需求,而实际业务往往需要从多个相关表中提取信息,这就需要用到多表查询。本文将全面讲解 Oracle 多表查询的核心知识,帮助初学者快速掌握相关技能。
一、多表查询的基本概念
多表查询是相对单表查询而言的,指的是通过关联字段(通常是外键关联)从多个数据表中联合查询数据的操作。
在实际的数据库设计中,数据表之间往往存在各种关联关系(如员工表和部门表通过部门编号关联),多表查询就是利用这些关联关系,将分散在不同表中的数据整合起来,以满足复杂的查询需求。
二、无条件多表查询:务必避免的 “坑”
1️⃣什么是无条件多表查询?
无条件多表查询是指在查询多个表时,不指定任何关联条件,此时数据库会将各表的记录以 **“笛卡尔积”** 的方式组合起来。
2️⃣笛卡尔积的含义
当连接查询中的两个表没有在where
子句中指定有效连接条件时,Oracle 会返回这两个表的笛卡尔积 —— 即把一个表的每一行与另一个表的每一行强制组合,产生大量冗余数据。
例如:
- scott.dept 表有 4 条记录,scott.emp 表有 14 条记录
- 它们的笛卡尔积会产生 4×14=56 条记录(其中大部分是无效数据)
3️⃣示例代码(不推荐使用)
sql
select emp.empno, emp.ename, emp.deptno, dept.dname, dept.loc from emp, dept;
4️⃣重要提醒
笛卡尔积会产生大量无效数据,浪费系统资源且无实际业务意义。在多表查询时,一定要通过where
子句提供正确的关联条件,避免出现笛卡尔积。
三、内连接:最常用的多表查询方式
内连接是多表查询中最常用的方式,它通过指定的条件筛选出多个表中满足关联条件的数据记录。内连接可分为等值连接和非等值连接。
1️⃣等值多表查询(核心)
- 定义:按照 “字段值相等” 的条件查询多个表中关联的数据。
- 要求:关联的字段需具有相同的属性(数据类型、宽度、取值范围一致)。
- 示例:查询所有员工及其对应的部门信息(只包含有对应部门的员工和有员工的部门)
sql
select emp.empno, emp.ename, emp.deptno, dept.dname, dept.loc from emp, dept where emp.deptno = dept.deptno; -- 关键:通过deptno关联两表
2️⃣非等值多表查询(较少用)
- 定义:按照 “字段值不相等” 的条件进行查询(实际业务中应用较少)。
- 示例(仅作语法演示,实际可能无意义):
sql
select emp.empno, emp.ename, emp.deptno, dept.dname, dept.loc from emp, dept where emp.deptno != dept.deptno and emp.deptno = 10; -- != 可替换为 <>
四、别名的进阶应用:将结果集当表用
在复杂查询中,可以将查询结果集视为一张临时表,并为其起别名,以便进一步处理。
示例:查询员工 'FORD' 的上级姓名
sql
select emp.ename, boss.ename
from emp, (select empno, ename from emp) boss -- 将子查询结果集命名为boss
where emp.mgr = boss.empno and emp.ename = 'FORD'; -- 通过mgr(上级编号)关联
这里的子查询(select empno, ename from emp)
被赋予别名boss
,相当于一张临时表,用于匹配员工的上级信息。
五、自连接:一张表当两张表用
自连接是一种特殊的多表查询,只使用一个实体表,但通过别名将其视为两张表,以查询表内记录之间的关联关系(如员工与上级的关系)。
示例:查询员工 'SMITH' 的上司名字
sql
select boss.ename as 上司姓名, emplyee.ename as 员工姓名
from my_emp boss, my_emp emplyee -- 同一表my_emp分别取别名boss和emplyee
where boss.empno = emplyee.mgr -- 关联条件:上司的编号=员工的上级编号
and emplyee.ename = 'SMITH'; -- 筛选条件:员工为'SMITH'
六、外连接:保留不满足条件的记录
内连接只返回满足关联条件的记录,而外连接会保留其中一个或两个表中不满足条件的记录,并在对应位置显示null
。外连接分为左外连接、右外连接和全外连接。
1️⃣左外连接
- 定义:以
left join
关键字左边的表为 “主表”,查询主表的所有记录,以及右表中满足关联条件的记录(右表不满足条件的字段显示null
)。 - 语法方式 1(推荐):
sql
select d.*, e.* from my_dept d left join my_emp e on d.deptno = e.deptno; -- on指定关联条件
- 语法方式 2(使用 + 符号):
sql
select d.*, e.* from my_dept d, my_emp e where d.deptno = e.deptno(+); -- (+)在右表,代表左表是主表
2️⃣右外连接
- 定义:以
right join
关键字右边的表为 “主表”,查询主表的所有记录,以及左表中满足关联条件的记录(左表不满足条件的字段显示null
)。 - 语法方式 1(推荐):
sql
select d.*, e.* from my_dept d right join my_emp e on d.deptno = e.deptno;
- 语法方式 2(使用 + 符号):
sql
select d.*, e.* from my_dept d, my_emp e where d.deptno(+) = e.deptno; -- (+)在左表,代表右表是主表
3️⃣全外连接
- 定义:同时保留两个表中不满足关联条件的记录,即返回左表和右表的所有记录,满足条件的正常关联,不满足的对应字段显示
null
。 - 注意:全外连接不支持 + 符号,只能用
full join
关键字。 - 示例:查询所有部门和所有员工的信息(包括无员工的部门和无部门的员工)
sql
select d.*, e.* from my_dept d full join my_emp e on d.deptno = e.deptno;
总结
Oracle 多表查询是数据库操作的核心技能之一,掌握以下要点能帮你快速上手:
- 避免无条件查询产生的笛卡尔积,务必添加关联条件;
- 内连接(等值连接)是基础,用于查询满足关联条件的数据;
- 别名和自连接可处理表内关联或复杂子查询场景;
- 外连接(左、右、全外连接)用于保留不满足条件的记录,需注意
join
关键字和+
符号的用法。