Oracle的练习与优化
1.查询工资大于1200的员工姓名和工资
select ename,sal from emp where sal>1200;
2.查询员工号为7900的员工的姓名和部门号
select ename,deptno from emp where empno=7900;
3.选择工资不在2000到3000的员工的姓名和工资
select ename,sal from emp where sal not between 2000 and 3000;
4.选择雇用时间在1981-02-01到1982-05-01之间的员工姓名,job
和雇用时间
select ename,job,hiredate from emp
where hiredate between to_date('1981-02-01','yyyy-MM-dd') and to_date('1982-05-01','yyyy-MM-dd');
5.选择在20或40号部门工作的员工姓名和部门号
select ename,deptno from emp where deptno in(20,40);
6.选择在1981年雇用的员工的姓名和雇用时间
select ename,hiredate from emp where extract(year from hiredate)=1981;
7.选择公司中没有管理者的员工姓名及job
select ename,job from emp where mgr is null;
8.选择公司中有奖金的员工姓名,工资和奖金级别
select ename,sal,comm from emp where nvl(comm,0)!=0;
9.选择员工姓名的第三个字母是a的员工姓名
select ename from emp where ename like '__A%';
10.选择姓名中有字母a和e的员工姓名
select ename from emp where ename like '%A%' and ename like '%E%';
11.显示系统时间
select sysdate from dual;
12.查询员工号,姓名,工资,以及工资提高百分之20%后的结果
select empno,ename,sal,(sal*1.2) as 提高后的工资 from emp;
13.将员工的姓名按首字母排序,并写出姓名的长度(length)
select ename,length(ename) from emp order by ename;
14.查询各员工的姓名,并显示出各员工在公司入职的月份数
select ename,extract(month from hiredate) from emp;
15.查询员工的姓名,以及在公司入职的月份数(worked_month),并按月份数降序排列
select ename,extract(month from hiredate) from emp order by extract(month from hiredate) desc;
16.查询公司员工工资的最大值,最小值,平均值,总和
select max(sal),min(sal),avg(sal),sum(sal) from emp;
17.查询各工种(job)的员工工资的最大值,最小值,平均值,总和
select job,max(sal),min(sal),avg(sal),sum(sal) from emp group by job;
18.选择各个工种(job)的员工人数
select job,count(empno) from emp group by job;
19.查询员工最高工资和最低工资的差距(DIFFERENCE)
select max(sal)-min(sal) from emp;
20.查询各个管理者手下员工的最低工资,其中最低工资不能低于1500,没有管理者的员工不计算在内
--分析
--查询员工
select * from emp;
select mgr,min(sal) from emp group by mgr having mgr is not null and min(sal)>=1500;
21.查询所有部门的名字,工作地点,员工数量和工资平均值.
select * from dept left outer join emp on dept.deptno =emp.deptno;
select dept.dname,dept.loc,count(emp.empno),avg(emp.sal) from dept left outer join emp on dept.deptno =emp.deptno group by dname,loc;
22. 查询和scott相同部门的员工姓名和雇用日期
select deptno from emp where emp.ename='SCOTT';
select ename,hiredate from emp where deptno =(select deptno from emp where emp.ename='SCOTT');
--等同
select emp.ename,emp.hiredate from emp,(select deptno from emp where emp.ename='SCOTT') tmp where emp.deptno=tmp.deptno;
23. 查询工资比公司平均工资高的员工的员工号,姓名和工资。
select avg(sal) from emp;
select empno,ename,sal from emp;
select empno,ename,sal from emp where sal>(select avg(sal) from emp);
24. 查询各部门中工资比本部门平均工资高的员工的员工号, 姓名和工资
select deptno,avg(sal) from emp group by deptno;
select empno,ename,sal from emp;
--连表查询
select empno,ename,sal, tmp.vagsal,emp.deptno from emp,(select deptno,avg(sal) as vagsal from emp group by deptno) tmp
where emp.deptno=tmp.deptno and emp.sal>tmp.vagsal;
25. 查询和姓名中包含字母u的员工在相同部门的员工的员工号和姓名
select ename,deptno from emp where ename like '%U%';
select empno,ename,deptno from emp;
--连接表
select emp.empno,emp.ename,emp.deptno from emp,(select deptno from emp where ename like '%U%') tmp
where emp.deptno=tmp.deptno;
26. 查询管理者是King的员工姓名和工资
--子查询
select empno from emp where ename='KING';
--这种写法的前提,名字不能相同
select ename,sal,mgr from emp where mgr=(select empno from emp where ename='KING');
27. 使用PL/SQL实现9*9的乘法口诀表
set serveroutput on;
begin
for i in 1..9
loop
for j in 1..i
loop
--不换行使用put
dbms_output.put(i ||'*'||j||'='|| (i*j)||' ');
end loop;
--换行
dbms_output.new_line();
end loop;
end;
优化
1、 查两张以上表时,把记录少的放在右边
2、 WHERE子句中的连接顺序
ORACLE采用自上而下的顺序解析WHERE子句,根据这个原则,那些可以过滤掉最大数量记录的条件应写在WHERE子句最后。
例如:查询员工的编号,姓名,工资,部门名
如果emp.sal>1500能过滤掉半数记录的话,
select emp.empno,emp.ename,emp.sal,dept.dname
from emp,dept
where (emp.deptno = dept.deptno) and (emp.sal > 1500)
.......
3、 SELECT子句中避免使用*号
ORACLE在解析的过程中,会将*依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间
4、 避免对大表进行无条件或无索引的的扫描
5、 清空表时用TRUNCATE替代DELETE
6、 尽量多使用COMMIT;因为COMMIT会释放回滚点
7、 用索引提高查询效率,善用索引
避免在索引列上使用NOT;因为Oracle服务器遇到NOT后,他就会停止目前的工作,转而执行全表扫描。
避免在索引列上使用计算;WHERE子句中,如果索引列是函数的一部分,优化器将不使用索引而使用全表扫描,这样会变得慢
例如,SAL列上有索引,
低效:
SELECT EMPNO,ENAME
FROM EMP
WHERE SAL*12 > 24000;
高效:
SELECT EMPNO,ENAME
FROM EMP
WHERE SAL > 24000/12;
8、 字符串型,能用=号,不用like;=号表示精确比较,like表示模糊比较
9、 用 >= 替代 >
低效:
SELECT * FROM EMP WHERE DEPTNO > 3
首先定位到DEPTNO=3的记录并且扫描到第一个DEPT大于3的记录
高效:
SELECT * FROM EMP WHERE DEPTNO >= 4
直接跳到第一个DEPT等于4的记录
10、 用IN替代OR
select * from emp where sal = 1500 or sal = 3000 or sal = 800;
select * from emp where sal in (1500,3000,800);
11、 用exists代替in;not exists代替 not in
not in 字句将执行一个内部的排序和合并,任何情况下,not in是最低效的,子查询中全表扫描;表连接比exists更高效
12、 用UNION-ALL 替换UNION
当SQL语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 然后在输出最终结果前进行排序. 如果用UNION ALL替代UNION, 这样排序就不是必要了. 效率会因此得到提高。
13、 避免使用耗费资源的操作
带有DISTINCT,UNION,MINUS,INTERSECT的SQL语句会启动SQL引擎 执行耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序. 通常, 带有UNION, MINUS , INTERSECT的SQL语句都可以用其他方式重写。
最后;同样的操作有些时候可以在程序上处理的就程序上处理,毕竟在内存中的执行速度比在硬盘上执行要高非常多。