现在的位置: 首页 > 综合 > 正文

Oracle 数据库笔记4

2018年05月18日 ⁄ 综合 ⁄ 共 8568字 ⁄ 字号 评论关闭

【oracle表基本查询 -介绍】
在我们讲解的过程中我们利用 scott 用户存在的几张表(emp, dept)为大家
演示如何使用 select 语句,select语句在软件编程中非常有用,希望大家
好好的掌握。

 

pl/sql清屏命令 -- clear
做销售的一半都有奖金~

set timing on; -- 打开显示操作时间的开关!就是用了多少时间。

疯狂复制法:
create table users(userid varchar2(20),

 username varchar2(30),
 userPss varchar2(20)
);
insert into users values ('a001', '单顺平sfaa','bestfight@yeah.net');
insert into users (userid, username, userpss) select * from users;
select count(*) from users;

 

查看表结构:desc dept;
查询所有列:select * from dept;(查询数据库切记动不动就用*)
查询指定列:select ename, sal, job, deptno from emp;
如何取消重复行:select distinct deptno, job from emp;

 

?查询SMITH的薪水【年底发双薪,故*13】,工作,所在部门。
 select sal*13, ename from emp;

 

 

取个别名儿让结果集好看一点
 select sal*13 "年工资", ename "雇员姓名" from emp;


另外,奖金不给算上是不合理的【不仅能运用乘法,还能用加法】
 select sal*13+comm*13 "年工资", ename from emp;
还是不够完美,突然发现 SMITH 年工资变为空了,为什么呢?先来看看这条语句的结果
 select sal*13+comm*13 "年工资", ename, comm from emp;
隆重推荐一个处理 null 值的 “nvl函数” -- 判断是否为空~
如果comm查出来的值为空值,则用0替代;如果comm不为空,则用comm本身的值~
 select sal*13+nvl(comm, 0)*13 "年工资", ename from emp;

 

【使用 where 子句】
?如何显示工资高于3000的员工
 select ename,sal from emp where sal>3000;

?如何超找1982.1.1后入职的员工[【可以通过修改注册表修正时间问题】
 select ename,sal from emp where hiredate>'1-1月-1982';

?如何显示工资在2000到2500的员工情况【多个条件之间应该用and隔开】
 select ename,sal from emp where sal>=2000 and sal<=2500;

 

如何使用like操作符
%: 表示0到多个字符
_: 表示任意单个字符

?如何显示首字符为S的员工姓名和工资
 select ename, sal from emp where ename like 'S%';

?如何显示第三个字符为大写O的所有员工的姓名和工资
 select ename, sal from emp where ename like '__O%';

 

在 where 条件中使用 in
?如何显示empno为123,345,800,.. 的雇员情况
 select * from emp where empno in(7369,7499,7934,321);

 

使用is null 的操作符
?如何显示没有上级的雇员的情况
 select * from emp where mgr is null;

【使用逻辑操作符号】
?查询工资高于500或是岗位为MANGER的雇员,同时还要满足他们的姓名
首写字母为大写的J。
 select * from emp where (sal>500 or job='MANAGER') and ename like 'J%';

 

使用 order by 子句【默认按从低到高的顺序排列】
?如何按照工资的从低到高的顺序显示雇员的信息
 select * from emp order by sal;【升序】
 select * from emp order by sal asc;【升序】
 select * from emp order by sal desc;【降序】

 

?按照部门编号升序而雇员的工资降序排列【这个很有用】
 select * from emp order by deptno asc, sal desc;
 select * from emp order by deptno asc, hiredate desc;

 

使用列的别名排序【注意:别名需要使用双引号圈中】
 select ename, (sal+nvl(comm,0))*12 "年薪" from emp order by "年薪" asc;

 

【oracle表复杂查询】
说明:
在实际应用中经常需要执行复杂的数据统计,经常需要显示多张表的数据,
现在我们给大家介绍较为复杂的select语句。

 

数据分组-max,min,avg,sum,count

?如何显示所有员工中最高工资和最低工资
 select max(sal),min(sal) from emp;


 select ename,sal from emp where sal=max(sal); 【wrong!】
  ORA-00934: 此处不允许使用分组函数
 select ename,sal from emp where max(sal)=sal; 【wrong, too!】
  ORA-00934: 此处不允许使用分组函数
 select ename,sal from emp where sal=(select max(sal) from emp);
 select ename,max(sal) from emp; 
  ORA-00937: 非单组分组函数
【注意: 如果列里面有一个分组函数,其他都必须是分组函数!】

?显示所有员工的平均工资和工资总和
?计算共有多少员工
 select count(*) from emp;

 

扩展要求:
?请显示工资最高的员工的名字,工作岗位
 select ename,job from emp where sal=(select max(sal) from emp); 

?请显示工资高于平均工资的员工信息 
 select * from emp where sal>(select avg(sal) from emp);

 

【oracle表复杂查询】
group by 用于对查询的结果分组统计,having子句用于限制分组显示结果。

?如何显示每个部门的平均工资和最高工资【分组的字段必须出现!】
 select avg(sal),max(sal),deptno from emp group by deptno;

?显示每个部门的每种岗位的平均工资和最低工资
 select min(sal),avg(sal),max(sal),deptno,job from emp group by deptno,job;

?显示平均工资低于2000的部门号和他的平均工资
 select avg(sal),max(sal),deptno from emp group by deptno having avg(sal)>2000;

 

对数据分组的总结:
①分组函数只能出现在选择列表、having、order by子句中;
②如果在select语句中同时包含group by,having,order by 那么
 他们的顺序是 group by, having, order by
 【顺序很重要,不可能是先有having再有order by,因为首先分组了过后才
  可能对分组的结果进行筛选,筛选完之后还可以进行排序】
 select avg(sal),max(sal),deptno from emp group by deptno having avg(sal)>2000 order by avg(sal);

③在选择列中如果有列、表达式和分组函数,那么这些列和表达式
 必须有一个出现在group by子句中,否则就会出错。
如: select deptno,avg(sal),max(sal) from emp group by deptno having avg(sal)<2000;
这里deptno就一定要出现在group by 中

 

【oracle表复杂查询 -- 多表查询】

说明:
多表查询是指基于两个和两个以上的表或是视图的查询。在实际应用中,
查询单个表可能不能满足你的需求,(如显示sales部门位置和其员工的姓名),
这种情况下需要使用到(dept表和emp表)

?显示雇员名,雇员工资及所在部门的名字【笛卡尔集】
 select a1.ename,a1.sal,a2.dname from emp a1,dept a2;【产生笛卡尔集】
 select t1.ename,t1.sal,t2.dname from emp t1,dept t2 where t1.deptno=t2.deptno; 【取别名】
 select emp.ename,emp.sal,dept.dname from emp,dept where emp.deptno=dept.deptno; 【不取别名】

?如何显示部门号为10的部门名、员工名和工资
 select t2.dname,t1.ename,t1.sal,t2.deptno from emp t1,dept t2 where t1.deptno=t2.deptno and t1.deptno=10;

?显示各个员工的姓名,工资,及其工资的级别
 select t1.ename,t1.sal,t2.grade from emp t1,salgrade t2 where t1.sal between t2.losal and t2.hisal;

扩展要求【多表里面排序也是不成问题的~】:
?显示雇员名,雇员工资及所在部门的名字,并按部门排序。
 select t1.ename,t1.sal,t2.dname from emp t1,dept t2 where t1.deptno=t2.deptno order by t1.deptno;
 ---------------------------------------------------

注意:在数据库里面有一个特别重要的原则!
如果你是两张表联合查询,至少有一个条件才能排除笛卡尔集;
如果是三张表,则至少有两个条件才能排除笛卡尔集;
也就是说:多表查询的条件至少不能少于表的个数减1,否则必错。

 

自连接
自连接是指在同一张表的连接查询。
?显示某个员工的上级领导的姓名。
比如显示“FORD”的上级
 select worker.ename,boss.ename from emp worker,emp boss where worker.mgr=boss.empno and worker.ename='FORD';

 

【oracle表复杂查询 -- 子查询【一个select语句嵌套在另一个select语句中】】
什么是子查询:
子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。

1.单行子查询:单行子查询是指值返回一行数据的子查询语句。
请思考:如何显示与SMITH同一个部门的所有员工?
 ①首先得到SMITH所属的部门号(尽可能把优化条件放于此)
 select deptno from emp where ename='SMITH';

 ②显示与SIMTH同一个部门的所有员工
 select * from emp where deptno=(select deptno from emp where ename='SMITH');

 

2.多行子查询:多行子查询指返回多行数据的子查询【一般用关键字in】
请思考:如何查询和部门10的工作相同的雇员的名字、岗位、工作、部门号。
select distinct job from emp where deptno=10;

select * from emp where job in (select distinct job from emp where deptno=10);

 

3.在多行子查询中使用all 操作符
请思考:如何显示工资比部门30的所有员工的工资高的员工的 姓名、工资 和 部门号
 select ename,sal,deptno from emp where sal>all(select sal from emp where deptno=30);

 第二种方法:【这种方法效率较高】
 select max(sal) from emp where deptno=30;
 select * from emp where sal>(select max(sal) from emp where deptno=30);

 

4.在多行子查询中使用 any 操作符【只要比其中一个的工资高就行】
请思考:如何显示工资比部门30的任意一个员工的工资高的员工的姓名、工资
 和部门号
 select ename,sal,deptno from emp where sal>any(select sal from emp where deptno=30); 

 

5.多列子查询:单行子查询是指子查询只返回单列、单行数据,多行子查询
是指返回多行单列数据,都是针对单列而言的,而多列子查询则是指查询返回
多个列数据的子查询语句。
请思考:如何查询与smith的部门和岗位完全相同的所有雇员。
 select deptno,job from emp where ename='SMITH';
 【这两个列的顺序一定要是一致的】
 select * from emp where (deptno,job)=(select deptno,job from emp where ename='SMITH');

 

6.在from子句中使用子查询
请思考:如何显示高于自己部门平均工资的员工的信息
 解题思路:
 ①首先查询出各个部门的平均工资和部门号
 select deptno,avg(sal) mysal from emp group by deptno;

 ②把上面的查询看做是一张子表而存在
 select t1.ename,t1.sal,t1.deptno, t2.mysal from emp t1,(select deptno,avg(sal) mysal

  from emp group by deptno) t2 where t1.deptno=
  t2.deptno and t1.sal>t2.mysal;  
 
7.在from子句中使用子查询
这里需要说明的当在 from 子句中使用子查询时,该子查询会被作为
一个视图来对待,因此叫做内嵌视图,当在from子句中使用子查询时,
必须给子查询指定别名。建议不要用as【一般给列取别名儿的时候
喜欢用as,但给表取别名儿的时候不要加as,加了就过不去】

 

8.分页查询:按雇员的id号升序取出。【oracle分页一共有种方式】【内嵌视图】
 ①rownum 分页
 select * from emp;

 ②显示rownum[oracle分配的]
 select t1.*,rownum rn from (select * from emp) t1;

 【后接and rownum>=6的话不生效,用between..and也没有用~】
 【二分机制速度很好,就是理解起来比较难】
 select t1.*,rownum rn from (select * from emp) t1 where rownum<=10;

 【完成 -- 再做一次子查询】
 select * from (select t1.*,rownum rn from (select * from emp) t1 where rownum<=10) where rn>=6;

注意【当一个公式来记忆即可】:
a.指定查询列,只需要修改最里层的子查询;
 select * from (select t1.*,rownum rn from (select ename,sal

  from emp) t1 where rownum<=10) where rn>=6;

b.如何排序,也只需要修改最里层的子查询即可【order by 默认升序排】;
 select * from (select t1.*,rownum rn from (select ename,sal

  from emp order by sal) t1 where rownum<=10) where rn>=6;

c.如何更改分页参数,也只需要修改最里层的子查询即可;
 select * from (select t1.*,rownum rn from (select ename,sal

  from emp order by sal) t1 where rownum<=9) where rn>=4;

 

9.用查询结果创建新表【能够创建出一张新表,而且里面会有数据】
这个命令是一种快捷的建表方法。
 create table mytable (id,name,sal,job,deptno) as select empno,ename,sal,job,deptno from emp;
 create table myemp2 (id,ename,sal) as select empno,ename,sal from emp;

 

10.合并查询
有时在实际应用中,为了合并多个select语句的结果,可以使用集合操作符号
union, union all, intersect, minus

union该操作符用于取得两个结果集的并集。当使用该操作符时,会自动
去掉结果集中重复行。
 select ename,sal,job from emp where sal>2500 union select ename,sal,job from emp where job='MANAGER';

union all操作赋予union相似,但是他不会取消重复行,而且不会排序。
 select ename,sal,job from emp where sal>2500 union all select ename,sal,job from emp where  job='MANAGER';  

intersect使用该操作符用于取得两个结果集的交集
 select ename,sal,job from emp where sal>2500 intersect select ename,sal,job from emp where job='MANAGER';

minus使用该操作符用于取得两个结果集的差集,他只会显示存在第一个
集合中,而不存在第二个集合中的数据。
 select ename,sal,job from emp where sal>2500 minus select ename,sal,job from
emp where job='MANAGER';
-----------------------------------------------------------------
SQL>  select ename,sal,job from emp where sal>2500 minus
  2    select ename,sal,job from emp where job='MANAGER';
 
ENAME             SAL JOB
---------- ---------- ---------
FORD             3000 ANALYST
KING             5000 PRESIDENT
SCOTT            3000 ANALYST
 
SQL> select ename,sal,job from emp where sal>2500;
 
ENAME            SAL JOB
---------- --------- ---------
JONES        2975.00 MANAGER
BLAKE        2850.00 MANAGER
SCOTT        3000.00 ANALYST
KING         5000.00 PRESIDENT
FORD         3000.00 ANALYST
 
SQL> select ename,sal,job from emp where job='MANAGER'
  2  ;
 
ENAME            SAL JOB
---------- --------- ---------
JONES        2975.00 MANAGER
BLAKE        2850.00 MANAGER
CLARK        2450.00 MANAGER

【创建数据库两种方法】
①通过oracle提供的向导工具;dbca【数据库配置助手】
②可以用手工步骤直接创建。

 

【学生表科目分数按科目分组按分数降序取前三条查询【3者之间是有一定区别的】】
select * from(select subject,score,row_number() over(partition by subject order by score desc ) 成绩排名 from test) temp where temp.成绩排名<=3;

select * from(select subject,score,dense_rank() over(partition by subject order by score desc ) 成绩排名 from test) temp where temp.成绩排名<=3;

select * from(select subject,score,rank() over(partition by subject order by score desc ) 成绩排名 from test) temp where temp.成绩排名<=3;

抱歉!评论已关闭.