项目开发中,分页存储过程是用的比较多的存储过程,SqlServer分页存储过程中经常要用到top,Oracle中则经常用到了RowNum。
以user表为例,表中有40条数据,有两个字段id和name,其中id自增,步长是1,id的值不一定连续。
查询表中第11到第20条数据。
先看SqlServer的几种写法:
第一种写法:
select top 10 *
from user
where id in
(
select top 20 id
from user
)
order by id desc
第二种写法:
select top 10 * from user
where id not in (
select top 10 id from user)
第三种写法:
select top 10 * from user where id>
(select max(id) from
(select top 10 id from user order by id) a)
第四种写法(只可在Sqlserver 2005中):
select * from (select Row_Number() over
(Order by id) as RowId ,* from user) U
where U.RowId between 10 and 20
比较:
四种方法中,后两种的写法要比前两种写法效率要高些,但第四种只能写在SqlServer 2005中。
再看Oracle实现分页查询的方法:
同样查询表中第11到第20条数据。
第一种写法:
select * from (
select rownum as rn,a.*
from select * from user) a
where rownum <=20)
where rn >11
第二种写法:
select * from (
select rownum as rn,a.*
from user a
where rownum >0)
where rn between 10 and 20
比较:
对比两种方法,绝大多数情况下,第一种查询效率要比第二种的效率高得多。
因为在CBO优化模式下,Oracle可以将外层的查询推到内层的查询,以提高内层查询的效率。
而Oracle只能将外层(第二层)的查询内推,无法将第三层查询条件推到最内层。
上述两个查询,第一个查询是两层查询,外层数据将查询条件推到内层一并执行查询,所以结果一旦超过rownum限制条件,查询就终止了;而第二个查询是三层查询,最外层数据无法推到最内层,数据需要层层传递过滤,效率自然不如的第一种。
这种分析不仅适用于单表查询,对于内层查询是复杂的多表查询也同样适用。
关于Oracle和Sqlserver实现分页查询,这里只是列出了几种执行效率较高的方法,其他的方法大家可以自行研究,如果大家有什么更好的方法,欢迎各位一起探讨。