oracle学习 select操作

在我们讲解的过程中我们利用 scott 用户存在的几张表(emp,dept)为大家演示如何使用 select 语句,select 语句在软件编
程中非常有用,希望大家好好的掌握。  
Oracle  笔记
7
emp 雇员表 
clerk   普员工 
salesman 销售 
manager   经理 
analyst 分析师 
president   总裁
mgr   上级的编号 
hiredate 入职时间 
sal 月工资 
comm 奖金 
deptno 部门
dept 部门表 
deptno 部门编号 
accounting 财务部 
research   研发部 
operations 业务部 
loc 部门所在地点
salgrade     工资级别 
grade       级别 
losal       最低工资 
hisal       最高工资
简单的查询语句 
 查看表结构 
DESC emp; 
 查询所有列 
SELECT * FROM dept; 
切忌动不动就用 select * 
SET TIMING ON; 打开显示操作时间的开关,在下面显示查询时间。 
CREATE TABLE users(userId VARCHAR2(10), uName VARCHAR2 (20), uPassw VARCHAR2(30)); 
INSERT INTO users VALUES('a0001', '啊啊啊啊', 'aaaaaaaaaaaaaaaaaaaaaaa'); 
--从自己复制,加大数据量 大概几万行就可以了   可以用来测试 sql 语句执行效率 
INSERT INTO users (userId,UNAME,UPASSW) SELECT * FROM users; 
SELECT COUNT (*) FROM users;统计行数
 查询指定列 
SELECT ename, sal, job, deptno FROM emp; 
 如何取消重复行 DISTINCT 
SELECT DISTINCT deptno, job FROM emp; 
?查询 SMITH 所在部门,工作,薪水 
SELECT deptno,job,sal FROM emp WHERE ename = 'SMITH'; 
注意:oracle 对内容的大小写是区分的,所以 ename='SMITH'和 ename='smith'是不同的  
Oracle  笔记
8
 使用算术表达式   nvl   null 
问题:如何显示每个雇员的年工资? 
SELECT sal*13+nvl(comm, 0)*13 "年薪" , ename, comm FROM emp; 
 使用列的别名 
SELECT ename "姓名", sal*12 AS "年收入" FROM emp; 
 如何处理 null 值 
使用 nvl 函数来处理 
 如何连接字符串(||) 
SELECT ename   || ' is a ' || job FROM emp; 
 使用 where 子句 
问题:如何显示工资高于 3000 的 员工? 
SELECT * FROM emp WHERE sal > 3000; 
问题:如何查找 1982.1.1 后入职的员工? 
SELECT ename,hiredate FROM emp WHERE hiredate >'1-1 月-1982'; 
问题:如何显示工资在 2000 到 3000 的员工? 
SELECT ename,sal FROM emp WHERE sal >=2000 AND sal <= 3000; 
 如何使用 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 为 7844, 7839,123,456 的雇员情况? 
SELECT * FROM emp WHERE empno in (7844, 7839,123,456); 
 使用 is null 的操作符 
问题:如何显示没有上级的雇员的情况? 
错误写法:select * from emp where mgr = ''; 
正确写法:SELECT * FROM emp WHERE mgr is null; 
6.oracle 表查询(2)
 使用逻辑操作符号 
问题:查询工资高于 500 或者是岗位为 MANAGER 的雇员,同时还要满足他们的姓名首字母为大写的 J? 
SELECT * FROM emp WHERE (sal >500 or job = 'MANAGER') and ename LIKE 'J%'; 
 使用 order by 字句     默认 asc 
问题:如何按照工资的从低到高的顺序显示雇员的信息? 
SELECT * FROM emp ORDER by sal; 
问题:按照部门号升序而雇员的工资降序排列 
SELECT * FROM emp ORDER by deptno, sal DESC; 
 使用列的别名排序 
问题:按年薪排序 
select ename, (sal+nvl(comm,0))*12 "年薪" from emp order by "年薪" asc; 
别名需要使用“”号圈中,英文不需要“”号  
Oracle  笔记
9
 分页查询 
等学了子查询再说吧。。。。。。。。 
Clear 清屏命令 
oracle 表复杂查询 
 说明 
在实际应用中经常需要执行复杂的数据统计,经常需要显示多张表的数据,现在我们给大家介绍较为复杂的 select 语句 
数据分组 ——max,min, avg, sum, count 
问题:如何显示所有员工中最高工资和最低工资? 
SELECT MAX(sal),min(sal) FROM emp e; 
最高工资那个人是谁? 
错误写法:select ename, sal from emp where sal=max(sal); 
正确写法:select ename, sal from emp where sal=(select max(sal) from emp); 
注意:select ename, max(sal) from emp;这语句执行的时候会报错,说 ORA-00937:非单组分组函数。因为 max 是分组函数,
而 ename 不是分组函数....... 
但是 select min(sal), max(sal) from emp;这句是可以执行的。因为 min 和 max 都是分组函数,就是说:如果列里面有一个
分组函数,其它的都必须是分组函数,否则就出错。这是语法规定的 
问题:如何显示所有员工的平均工资和工资总和? 
问题:如何计算总共有多少员工问题:如何 
扩展要求: 
查询最高工资员工的名字,工作岗位 
SELECT ename, job, sal FROM emp e where sal = (SELECT MAX(sal) FROM emp); 
显示工资高于平均工资的员工信息 
SELECT * FROM emp e where sal > (SELECT AVG(sal) FROM emp); 
 group by 和 having 子句 
group by 用于对查询的结果分组统计, 
having 子句用于限制分组显示结果。
问题:如何显示每个部门的平均工资和最高工资? 
SELECT AVG(sal), MAX(sal), deptno FROM emp GROUP by deptno; 
(注意:这里暗藏了一点,如果你要分组查询的话,分组的字段 deptno 一定要出现在查询的列表里面,否则会报错。因为分组
的字段都不出现的话,就没办法分组了) 
问题:显示每个部门的每种岗位的平均工资和最低工资? 
SELECT min(sal), AVG(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; 
 对数据分组的总结 
1 分组函数只能出现在选择列表、having、order by 子句中(不能出现在 where 中) 
2 如果在 select 语句中同时包含有 group by, having, order by 那么它们的顺序是 group by, having, order by 
3 在选择列中如果有列、表达式和分组函数,那么这些列和表达式必须有一个出现在 group by 子句中,否则就会出错。 
如 SELECT deptno, AVG(sal), MAX(sal) FROM emp GROUP by deptno HAVING AVG(sal) < 2000; 
这里 deptno 就一定要出现在 group by 中 
多表查询 
 说明 
多表查询是指基于两个和两个以上的表或是视图的查询。在实际应用中,查询单个表可能不能满足你的需求,(如显示 sales
部门位置和其员工的姓名),这种情况下需要使用到(dept 表和 emp 表)  
Oracle  笔记
10
问题:显示雇员名,雇员工资及所在部门的名字【笛卡尔集】? 
规定:多表查询的条件是 至少不能少于 表的个数-1 才能排除笛卡尔集 
(如果有 N 张表联合查询,必须得有 N-1 个条件,才能避免笛卡尔集合) 
SELECT e.ename, e.sal, d.dname FROM emp e, dept d WHERE e.deptno = d.deptno; 
问题:显示部门号为 10 的部门名、员工名和工资? 
SELECT d.dname, e.ename, e.sal FROM emp e, dept d WHERE e.deptno = d.deptno and e.deptno = 10; 
问题:显示各个员工的姓名,工资及工资的级别? 
先看 salgrade 的表结构和记录 
SQL>select * from salgrade; 
GRADE                 LOSAL                   HISAL 
-------------     -------------     ------------1                   700                     1200 
2                   1201                   1400 
3                   1401                   2000 
4                   2001                   3000 
5                   3001                   9999 
SELECT e.ename, e.sal, s.grade FROM emp e, salgrade s WHERE e.sal BETWEEN s.losal AND s.hisal; 
扩展要求: 
问题:显示雇员名,雇员工资及所在部门的名字,并按部门排序? 
SELECT e.ename, e.sal, d.dname FROM emp e, dept d WHERE e.deptno = d.deptno ORDER by e.deptno; 
(注意:如果用 group by,一定要把 e.deptno 放到查询列里面) 
 自连接 
自连接是指在同一张表的连接查询 
问题:显示某个员工的上级领导的姓名? 
比如显示员工‘FORD’的上级 
SELECT worker.ename, boss.ename FROM emp worker,emp boss WHERE worker.mgr = boss.empno AND worker.ename = 'FORD'; 
子查询 
 什么是子查询 
子查询是指嵌入在其他 sql 语句中的 select 语句,也叫嵌套查询。 
 单行子查询 
单行子查询是指只返回一行数据的子查询语句 
请思考:显示与 SMITH 同部门的所有员工? 
思路: 
1 查询出 SMITH 的部门号 
select deptno from emp WHERE ename = 'SMITH'; 
2 显示 
SELECT * FROM emp WHERE deptno = (select deptno from emp WHERE ename = 'SMITH'); 
数据库在执行 sql 是从左到右扫描的, 如果有括号的话,括号里面的先被优先执行。 
 多行子查询 
多行子查询指返回多行数据的子查询 
请思考:如何查询和部门 10 的工作相同的雇员的名字、岗位、工资、部门号 
SELECT DISTINCT job FROM emp WHERE deptno = 10; 
SELECT * FROM emp WHERE job IN (SELECT DISTINCT job FROM emp WHERE deptno = 10); 
(注意:不能用 job=..,因为等号=是一对一的) 
 在多行子查询中使用 all 操作符  
Oracle  笔记
11
问题:如何显示工资比部门 30 的所有员工的工资高的员工的姓名、工资和部门号? 
SELECT ename, sal, deptno FROM emp WHERE sal > all (SELECT sal FROM emp WHERE deptno = 30); 
扩展要求: 
大家想想还有没有别的查询方法。 
SELECT ename, sal, deptno FROM emp WHERE sal > (SELECT MAX(sal) FROM emp WHERE deptno = 30); 
执行效率上, 函数高得多 
 在多行子查询中使用 any 操作符 
问题:如何显示工资比部门 30 的任意一个员工的工资高的员工姓名、工资和部门号? 
SELECT ename, sal, deptno FROM emp WHERE sal > ANY (SELECT sal FROM emp WHERE deptno = 30); 
扩展要求: 
大家想想还有没有别的查询方法。 
SELECT ename, sal, deptno FROM emp WHERE sal > (SELECT min(sal) FROM emp WHERE deptno = 30); 
 多列子查询 
单行子查询是指子查询只返回单列、单行数据,多行子查询是指返回单列多行数据,都是针对单列而言的,而多列子查询是指
查询返回多个列数据的子查询语句。 
请思考如何查询与 SMITH 的部门和岗位完全相同的所有雇员。 
SELECT deptno, job FROM emp WHERE ename = 'SMITH'; 
SELECT * FROM emp WHERE (deptno, job) = (SELECT deptno, job FROM emp WHERE ename = 'SMITH'); 
 在 from 子句中使用子查询 
请思考:如何显示高于自己部门平均工资的员工的信息 
思路: 
1. 查出各个部门的平均工资和部门号 
SELECT deptno, AVG(sal) mysal FROM emp GROUP by deptno; 
2. 把上面的查询结果看做是一张子表 
SELECT e.ename, e.deptno, e.sal, ds.mysal FROM emp e, (SELECT deptno, AVG(sal) mysal FROM emp GROUP by deptno) ds 
WHERE e.deptno = ds.deptno AND e.sal > ds.mysal; 
如何衡量一个程序员的水平? 
网络处理能力, 数据库, 程序代码的优化程序的效率要很高 
小总结: 
在这里需要说明的当在 from 子句中使用子查询时,该子查询会被作为一个视图来对待,因此叫做内嵌视图,当在 from 子句中
使用子查询时,必须给子查询指定别名。 
注意:别名不能用 as,如:SELECT e.ename, e.deptno, e.sal, ds.mysal FROM emp e, (SELECT deptno, AVG(sal) mysal FROM 
emp GROUP by deptno) as ds WHERE e.deptno = ds.deptno AND e.sal > ds.mysal; 
在 ds 前不能加 as,否则会报错   (给表取别名的时候,不能加 as;但是给列取别名,是可以加 as 的) 
 分页查询 
按雇员的 id 号升序取出 
oracle 的分页一共有三种方式 
1.根据 rowid 来分
select * from t_xiaoxi where rowid in (select rid from (select rownum rn, rid from(select rowid rid, cid from 
t_xiaoxi order by cid desc) where rownum<10000) where rn>9980) order by cid desc; 
执行时间 0.03 秒 
2.按分析函数来分
select * from (select t.*, row_number() over(order by cid desc) rk from t_xiaoxi t) where rk<10000 and rk>9980; 
执行时间 1.01 秒 
3.按 rownum 来分  
Oracle  笔记
12
select * from (select t.*,rownum rn from(select * from t_xiaoxi order by cid desc)t where rownum<10000) where 
rn>9980; 
执行时间 0.1 秒 
其中 t_xiaoxi 为表名称,cid 为表的关键字段,取按 cid 降序排序后的第 9981-9999 条记录,t_xiaoxi 表有 70000 多条记录。  
个人感觉 1 的效率最好,3 次之,2 最差。 
//测试通过的分页查询 okokok 
select * from (select a1.*, rownum rn from(select ename,job from emp) a1 where rownum<=10)where rn>=5; 
下面最主要介绍第三种:按 rownum 来分 
1. rownum 分页
SELECT * FROM emp;       
2. 显示 rownum[oracle 分配的] 
SELECT e.*, ROWNUM rn FROM (SELECT * FROM emp) e; 
rn 相当于 Oracle 分配的行的 ID 号 
3.挑选出 6—10 条记录 
先查出 1-10 条记录 
SELECT e.*, ROWNUM rn FROM (SELECT * FROM emp) e WHERE ROWNUM <= 10; 
如果后面加上 rownum>=6 是不行的, 
4. 然后查出 6-10 条记录 
SELECT * FROM (SELECT e.*, ROWNUM rn FROM (SELECT * FROM emp) e WHERE ROWNUM <= 10) WHERE rn >= 6; 
5. 几个查询变化 
a. 指定查询列,只需要修改最里层的子查询 
只查询雇员的编号和工资 
SELECT * FROM (SELECT e.*, ROWNUM rn FROM (SELECT ename, sal FROM emp) e WHERE ROWNUM <= 10) WHERE rn >= 6; 
b. 排序查询,只需要修改最里层的子查询 
工资排序后查询 6-10 条数据 
SELECT * FROM (SELECT e.*, ROWNUM rn FROM (SELECT ename, sal FROM emp ORDER by sal) e WHERE ROWNUM <= 10) WHERE 
rn >= 6; 
 用查询结果创建新表 
这个命令是一种快捷的建表方式 
CREATE TABLE mytable (id, name, sal, job, deptno) as SELECT empno, ename, sal, job, deptno FROM emp; 
创建好之后,desc mytable;和 select * from mytable;看看结果如何? 
合并查询 
 合并查询 
有时在实际应用中,为了合并多个 select 语句的结果,可以使用集合操作符号 union,union all,intersect,minus 
多用于数据量比较大的数据局库,运行速度快。 
1). union 
该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中重复行。 
SELECT ename, sal, job FROM emp WHERE sal >2500 
UNION 
SELECT ename, sal, job FROM emp WHERE job = 'MANAGER'; 
2).union all 
该操作符与 union 相似,但是它不会取消重复行,而且不会排序。 
SELECT ename, sal, job FROM emp WHERE sal >2500 
UNION ALL 
SELECT ename, sal, job FROM emp WHERE job = 'MANAGER';  
Oracle  笔记
13
该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中重复行。 
3). intersect 
使用该操作符用于取得两个结果集的交集。 
SELECT ename, sal, job FROM emp WHERE sal >2500 
INTERSECT 
SELECT ename, sal, job FROM emp WHERE job = 'MANAGER'; 
4). minus 
使用改操作符用于取得两个结果集的差集,他只会显示存在第一个集合中,而不存在第二个集合中的数据。 
SELECT ename, sal, job FROM emp WHERE sal >2500 
MINUS 
SELECT ename, sal, job FROM emp WHERE job = 'MANAGER'; 
(MINUS 就是减法的意思) 
创建数据库有两种方法: 
1). 通过 oracle 提供的向导工具。√ 
database Configuration Assistant   【数据库配置助手】 
2).我们可以用手工步骤直接创建。 

你可能感兴趣的:(oracle学习)