PL/SQL的高级查询(一)

2014-11-24 08:34:02 ? 作者: ? 浏览: 16

1 With子句

1.1 学习目标

掌握with子句用法,并且了解with子句能够提高查询效率的原因。
1.2 With子句要点

1. with子句的返回结果存到用户的临时表空间中,只做一次查询,反复使用,提高效率。
2. 如果定义了with子句,而在查询中不使用,那么会报ora-32035 错误:未引用在with子句中定义的查询名。
3. 前面的with子句定义的查询在后面的with子句中可以使用。但是一个with子句内部不能
嵌套with子句。
4. 当一个查询块名字和一个表名或其他的对象相同时,解析器从内向外搜索,优先使用子查询块名字。
5. with查询的结果列有别名,引用的时候必须使用别名或*。
6. with有可能影响执行计划。
1.3 with子句语法

With alias_name as (select1), --as和select中的括号都不能省略
alias_name2 as (select2),--后面的没有with,逗号分割,同一个主查询同级别地方,with子
查询只能定义一次

alias_namen as (select n) –与下面的实际查询之间没有逗号
Select ….
1.4 with使用例子:

1. 最简单的使用方法:
如查询部门名称包含“A”的所有员工信息
--with clause
with a as
(select deptno from dept where dname like '%A%')
select * from emp where deptno in (select * from a);
with a as
(select deptno from dept where dname like '%A%'),--a结果集
a2 as(select * from a where deptno>20)--a1结果集直接从a中筛选
select * from emp where deptno in (select * from a2);
2. 多层同级只能用一个with,并且后面的结果集可以使用前面的结果集:
查询部门名称包含“A”并且部门编号大于20的所有员工信息
with a as
(select deptno from dept where dname like '%A%'),--a结果集
a2 as(select * from a where deptno>20)--a1结果集直接从a中筛选
select * from emp where deptno in (select * from a2);
3. 不同级查询可以使用多个with:
查询部门名称包含“A”并且部门编号大于20的所有员工信息的另外一种实现方式如下
with a as
(select deptno from dept where dname like '%A%')--a结果集
select * from emp where deptno in (--括号内层作为子查询,为第二级
with a2 as(select * from a where deptno>20)--a1结果集直接从a中筛选
select * from a2
);
1.5 使用场景

那什么情况下能使用到with子句呢?以下我就举几个简单的例子,简单的说明以下:
1. 我想测试一句sql,而我不想专门建立一个测试表:
我想测试成绩大于90的学生,我不想建立学生表,可以用到with子句
with stu as(
select '张娜' sname,99 score from dual union
select '王杰' ,35 from dual union
select '宋丽' ,85 from dual union
select '陈晓' ,73 from dual union
select '李元' ,100 from dual
)--with 组成一个临时的结果集,存放在用户的临时表空间
select * from stu where score>90
2. 当一个sql重复用到某个相同的结果集作为子查询:
--查询销售部工资>1500或者销售部工资小于1000的员工
select * from emp where deptno=(select deptno from dept where dname ='SALES') and sal >1500
union all
select * from emp where deptno=(select deptno from dept where dname ='SALES') and sal <1000
--以上sql select deptno from dept where dname ='SALES'需要执行两次,影响效率
--可以使用with优化一下
with salno as(select deptno from dept where dname ='SALES')
select * from emp where deptno=(select * from salno) and sal >1500
union all
select * from emp where deptno=(select * from salno) and sal <1000
2 集合操作

2.1 学习目标

掌握union,union all,minus,intersect的使用,能够描述集合运算,了解内部运行原理。
2.2 要点

Union all 效率一般比union高。Union all内部不做排序工作,也不做剔除
重复行工作,而union则做这个工作。所以当数据量比较大的时候,能用union all的时候尽量用union all。除了union all 默认不做排序和剔除重复行的操作外,
union,minus,intersect都默认按第1个查询结果的第1列进行升序排列,并且
不包含重复行。
2.3 语法

(select resource 1)
Union/union all/minus/intersect
(select resource 2)
Union/union all/minus/intersect
(select resource 3)
……….
其中查询结果集的各个字段的类型能够互相兼容,并且总的结果集字段名与第一个结果集相同。
2.4 使用案例

数据准备:
create table t1 as select rownum rn from dual connect by rownum<7;
create table t2 as select rownum+3 rn from dual connect by rownum<7;
1. 查询t1和t2表的所有记录,不去除重复。
2. 查询t1和t2表的所有记录,去除重复。
3. 查询t1和t2表都存在的记录
4. 查询t1表存在,t2表不存在的记录
5. 排序操作:
6. 除了union all其他的全部会在总的结果集中剔除重复,例如:
insert into t1 values(1);
commit;
现在t1表中有两条相同的记录,其rn的值为1。
在进行集合运算时重复的记录被剔除:
2.5 使用场景

当要对多个结果集进行集合操作时,可是使用集合操作。
3 case与decode

3.1 学习目标

会使用case表达式和decode函数,理解各个参数和返回值的含义。
3.2 要点

Case表达式:
1. When后面的表达式类型应该全部保持一致,返回值类型也必须保持一致,或者能够进行隐式转换。
2. case 表达式 when 值,如果值是null,就算表达式也是null,结果也是返回false。也就是case 后面的表达式如果值为null,不会与when null 匹配,只会与else 匹配。
Decode函数的使用方法与case when相似,但是decode只能用等号匹配。
3.3 语法

Case表达式第一种:
case exp when comexp then returnval

-->

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: