博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Oracle] 分页查询
阅读量:4452 次
发布时间:2019-06-07

本文共 2895 字,大约阅读时间需要 9 分钟。

版权声明:本文为博主原创文章。未经博主同意不得转载。 https://blog.csdn.net/oscar999/article/details/18213613

有限结果集

在Oracle 中。 使用好 ROWNUM 这个栏位, 将会非常实用。

一般来说能够用它来做两件事情:

1.  运行top-N的查询。这和其它数据库的 LIMIT 语法的作用相似。(查找前N笔数据)

2. 运行分页查询, 特别是在Web 这种无状态的环境。

ROWNUM 是怎样工作的

ROWNUM 是一个在查询中的虚列(不是实际的列)。

ROWNUM 的值是相似于: 1,,2,,3,4,...,N。ROWNUM 的值不是永久的分配给某行。所用不能使用 ROWNUM=5 这种方式来找到某行。

另一个重要的概念是ROWNUM什么时间被赋值。

ROWNUM 在某个Query语句通过查询谓词阶段之后可是在查询做不论什么排序和汇总之前。

相同。ROWNUM的值仅仅有在分配之后才干增长。

像下面这种语句就得不到数据。

select *   from t  where ROWNUM > 1;
原因是: ROWNUM > 1对于第一行来说是不正确的。ROWNUM不能提前到2.  考虑使用下面方式:

select ..., ROWNUM  from t where 
group by
having
order by
;
能够看成是下面顺序进行处理:

1.  FROM/WHERE 子句先行

2.  ROWNUM 是从FROM/WHERE子句中分配和递增给每个输出行。

3. SELECT 被应用

4. GROUP BY 被应用

5. HAVING 被应用

6. ORDER BY 被应用

这就是为什么下面方式进行Query 来处理ROWNUM 是会有问题的了:

select *   from emp  where ROWNUM <= 5  order by sal desc;

这个语句会任意的找五笔数据,而不是薪资最高的五笔数据。

所以, 正确的做法应该是:

先排序, 然后再使用 rownum. 能够这样

select *  from  ( select *     from emp    order by sal desc )  where ROWNUM <= 5;

查询前 n 条数据

对与一张数据量非常大(百万级甚至很多其它) 且每个记录的内容都比較大的表来说, 获取前 10条或是100条数据的方式能够是:

1. Query 出全部数据, 取前 n 条  order by

2.  使用内部表的方式, 结合ROWNUM, 相似

SELECT * FROM ( your_query_here ) WHERE ROWNUM <= N.

除了从DB 中取的比較少的数据外,这两种方式在性能上差异非常大, 差在什么地方呢?

先来看一下第一种方式的运行过程

1.  全表扫描

2.  对全部数据依据字段排序

3. 假设排序的内存不够的话,从硬盘扩展

4. 结合扩展的暂时内存取出前 n 条数据

5. 释放暂时内存。

而另外一种方式的过程就要简单得多

1. 全表扫描

2. 排序区先取n 条数据,   n 条之后的数据每笔和这n 条进行比对, 满足条件的话就替换。

也就是说, 排序区始终仅仅有n 条数据。 也就不会从硬盘扩展。

笔者在实际开发的过程中, 在 2000万笔数据的状况下,

不使用ROWNUM 简直就无法使用了。  使用ROWNUM 的状况系统响应时间在 10s 内。

看样例

建立一个 EMPLOYEE 的表, 并插入一些数据

CREATE TABLE EMPLOYEE(  EMPID varchar2(10),  EMPNAME varchar2(10),  SALARY varchar2(60));insert into EMPLOYEE values('001','zhao','7300');insert into EMPLOYEE values('002','qian','7400');insert into EMPLOYEE values('003','sun','7500');insert into EMPLOYEE values('004','li','7200');insert into EMPLOYEE values('005','zhou','7100');insert into EMPLOYEE values('006','wu','7000');insert into EMPLOYEE values('007','zheng','6500');insert into EMPLOYEE values('008','wang','6000');insert into EMPLOYEE values('009','feng','6100');insert into EMPLOYEE values('010','chen','6200');insert into EMPLOYEE values('011','zhu','6300');insert into EMPLOYEE values('012','wei','6400');insert into EMPLOYEE values('013','jiang','6700');insert into EMPLOYEE values('014','shen','6600');insert into EMPLOYEE values('015','han','6800');insert into EMPLOYEE values('016','yang','6900');
能够自行插入 800 笔数据左右。

( 数据量较少可能看不出效果)

1. 如今想查看薪资最高的五笔数据。

1)使用 :

select * from EMPLOYEE where ROWNUM <= 5 order by SALARY desc;

得到 :

2) select * from EMPLOYEE  order by SALARY desc;

结果全然不相同。 验证了以上部分的描写叙述。

正确的写法能够是:

select * from(select * from EMPLOYEE  order by SALARY desc) where ROWNUM <= 5 ;

參考

http://www.oracle.com/technetwork/issue-archive/2006/06-sep/o56asktom-086197.html

转载于:https://www.cnblogs.com/mqxnongmin/p/10805653.html

你可能感兴趣的文章
USACO 3.1 Contact
查看>>
Office之什么是高内聚低耦合
查看>>
一些奇怪的问题求回答
查看>>
这些年踩过的坑
查看>>
iOS开发拓展篇——如何把项目托管到GitHub
查看>>
性能优化之数据库优化
查看>>
类的继承、菱形继承、派生、多态
查看>>
mysql约束
查看>>
javascript鼠标及键盘事件总结及案例
查看>>
mysql表之间的关系及级联操作
查看>>
mac 搭建virtualenv的那些坑
查看>>
多路复用IO模型
查看>>
并发、串行、并行及多道技术原理
查看>>
hashlib、pickle、hmac、logging模块使用
查看>>
javascript常用知识点总结
查看>>
2019秋招复习笔记--数据库基本操作
查看>>
2019秋招复习笔试--手写代码
查看>>
2019秋招复习笔记--智力题
查看>>
MySQL学习笔记
查看>>
2019秋招面试复习 项目重点提问
查看>>