1、课程名称:SQL 语句
多表查询、分组统计、子查询、数据表的更新操作、事务处理、查询练习
2、知识点
2.1、上次课程的主要知识点
1、 基本的 SQL 查询语句结构:
SELECT {若干字段 若干别名| *}
FROM 表名称
[WHERE 多个查询条件] [ORDER BY 排序条件 {ASC | DESC}]
2、 函数:substr、to_char、to_date、nvl、decode
2.2、本次预计讲解的知识点
1、 多表查询的作用及笛卡尔积的产生
2、 分组函数的使用及分组统计的应用
3、 子查询的作用,并结合多表查询、子查询,完成各种复杂的查询案例
4、 使用 SQL 语句进行数据的增加、修改、删除操作
5、 Oracle 中的事务处理及死锁
3、具体内容
3.1、多表查询
3.1.1、基本语法
可以同时查询一张以上的表,那么就称为多表查询。
但是在多表查询之前首先必须处理一个问题:
例如:现在求出雇员表中的总记录数(14 条记录)
SELECT COUNT(*) FROM emp ;
例如:现在求出部门表的总记录数(4 条记录)
SELECT COUNT(*) FROM dept ;
所谓的多表查询就是直接在 FROM 语句之后加入若干张表,下面将 emp 和 dept 表进行多表查询
SELECT * FROM emp,dept ;
以上确实完成了两张表的联合查询,但是查询出来的结果是 56 条记录。
部门表的记录总数 * 雇员表的记录总数 = 56 条记录。那么这样的结果在数据库中就称为笛卡尔积。
对于这样的结果明显不是最终查询者需要返回的结果,应该想办法去掉笛卡尔积。所以如果要使用
多表查询,则必须按照以下的语句形式进行编写:
SELECT 字段
FROM 表 1,表 2
WHERE 将两张表的关联字段进行比较,去掉笛卡尔积
以 emp 和 dept 表为例
1、 雇员表结构:
No. 字段名称 字段类型 字段作用
1 EMPNO NUMBER(4) 表示的是雇员编号,长度为四位的整数
2 ENAME VARCHAR2(10) 雇员的姓名,使用字符串表示,字符串的长度最大为 10
3 JOB VARCHAR2(9) 工作,字符串表示,最大长度为 9
4 MGR NUMBER(4) 雇员的直接上级领导编号
5 HIREDATE DATE 雇佣日期
6 SAL NUMBER(7,2) 工资,工资长度一共是 7 位,其中整数占 5 位,小数占 2 位
7 COMM NUMBER(7,2) 奖金(佣金)
8 DEPTNO NUMBER(2) 部门编号
2、 部门表结构:
No. 字段名称 字段类型 字段作用
1 DEPTNO NUMBER(2) 部门编号
2 DNAME VARCHAR2(14) 部门名称
3 LOC VARCHAR2(13) 部门位置
两张表中都存在 deptno 字段,一般在数据库建表的时候都会把关联字段的名称统一。
例如:使用关联字段消除掉之前多表查询的迪卡尔积。
SELECT * FROM emp,dept WHERE emp.deptno=dept.deptno ;
但是如果一直按照以上的格式编写的话,对于表名称太长的情况时,如果在访问字段前还是使用表
名称的形式,会很麻烦。所以一般可以为一张表起一个别名。修改以上的范例:
SELECT *
FROM emp e,dept d
WHERE e.deptno=d.deptno ;
例如:要求查询出雇员的编号、雇员的姓名、工资、部门的名称及位置
SELECT e.empno,e.ename,e.sal,d.dname,d.loc
FROM emp e,dept d
WHERE e.deptno=d.deptno ;
例如:要求查询出每个雇员的姓名、工作、雇员工资、领导姓名、领导工资
· 如果要找到领导信息,则肯定需要 emp 表
· 如果要找到雇员信息,则肯定需要 emp 表
· 消除笛卡尔积的条件:雇员的管理者的编号 = 雇员中的雇员编号
SELECT e.ename 雇员姓名,e.job 雇员工作,e.sal 雇员工资,m.ename 领导姓名,m.sal 领导工资
FROM emp e,emp m
WHERE e.mgr=m.empno ;
可以发现,本次查询是本表关联本表,那么这样的查询称为自身关联查询。
例如:要求查询出每个雇员的姓名、工作、雇员工资、部门名称、领导姓名、领导工资
· 如果要找到领导信息,则肯定需要 emp 表
· 如果要找到雇员信息,则肯定需要 emp 表
· 如果要找到部门信息,则肯定需要 dept 表
SELECT e.ename 雇员姓名,e.job 雇员工作,e.sal 雇员工资,m.ename 领导姓名,m.sal 领导工资,d.dname 部门名称
FROM emp e,emp m,dept d
WHERE e.mgr=m.empno AND e.deptno=d.deptno;
注意:在以上的查询中性能如何?
例如:求出以上三张表的笛卡尔积的数量
SELECT COUNT(*) FROM emp e,emp m,dept d ;
可以发现以上的查询产生了 784 条的记录。
思考:
现在要求查询出每个雇员的姓名、工资、部门名称,雇员的工资及在公司的工资等级、领导的姓名、
领导的工资及工资在公司的工资等级。
· salgrade:工资等级表
No.
字段名称 字段类型 字段作用
1 GRADE NUMBER
等级编号
2 LOSAL NUMBER
此等级的最低工资
3 HISAL NUMBER
此等级的最高工资
|- 通过 sal 指定 losal 和 hisal 的范围来去除笛卡尔积
· 部门表
· 领导表:emp
SELECT e.ename,e.sal,d.dname,e.sal,s.grade,m.ename,m.sal,sm.grade
FROM emp e,dept d,emp m,salgrade s,salgrade sm
WHERE e.sal BETWEEN s.losal AND s.hisal AND e.deptno=d.deptno AND m.sal BETWEEN sm.losal AND sm.hisal AND
e.mgr=m.empno ;