导语 :接触oracle有一段时间了,对于分页查询,伪列等概念并不是很透彻,因此一步步查询分析分页查询的意义,为什么要这么写,以此记录
标准的Oracle分页 查询 为三层嵌套,如下
select * from
( select A.*,rownum rn from
( select * from table) Arr
where rownum <=10
) where rn >0
两层不可以吗,一层直接查询呢,开始探究
1. 基础查询表数据
SELECT T.* FROM ONE_NEW T
查询结果如下:
图1
查询结果全部展示出来,但问题是这样没法对数据进行分页,这时候用到了伪列
2. 添加伪列查询
分页要用到伪列:
那么什么是Oracle的伪列呢?
在Oracle官方文档的Oracle Database SQL Language Reference 11g Release 2 (11.2) E41084-02找到了对伪劣的定义:A pseudocolumn behaves like a table column, but is not actually stored in the table. You can select from pseudocolumns, but you cannot insert, update, or delete their values. A pseudocolumn is also similar to a function without arguments . However, functions without arguments typically return the same value for every row in the result set, whereas pseudocolumns typically return a different value for each row.
大致的意思如下:
伪列的操作类似于表中的列,但是它并不存实际保存在表中。你可以对其进行查询操作,但是你却不能对其进行增加、修改或者是删除,一个伪列也类似于一个没有参数的函数。但是,没有参数的函数通常在结果集中为每一列返回相同的结果,伪列通常为每一列返回不同的值。
简单来说,伪列物理上并不存在,只是在查询时才构造出来
这里以 ROWNUM为例探究,添加伪列查询
SELECT ROWNUM,T.* FROM ONE_NEW T
查询结果:
图2
可以看到,添加伪列后查询结果确实是多了一列,从上到下自动排列,那这样能做到分页吗?
把数据以1-8行为一页查询
首先,以ROWNUM=1进行查询
SELECT ROWNUM,T.* FROM ONE_NEW T WHERE ROWNUM=1
图3
以ROWNUM>1进行查询
SELECT ROWNUM,T.* FROM ONE_NEW T WHERE ROWNUM>1
图4
以ROWNUM=8进行查询
SELECT ROWNUM,T.* FROM ONE_NEW T WHERE ROWNUM=8
图5
以ROWNUM>8进行查询
SELECT ROWNUM,T.* FROM ONE_NEW T WHERE ROWNUM>8
图6
以ROWNUM<=8进行查询
SELECT ROWNUM,T.* FROM ONE_NEW T WHERE ROWNUM<=8
图7
因为ROWNUM由1开始的,所以只能查到ROWNUM=1时的数据, 当查ROWNUM<=8时,也查询到数据,相当于
SELECT ROWNUM,T.* FROM ONE_NEW T WHERE ROWNUM>=1 AND ROWNUM<=8
然后我们对此表按照 one_name排序
SELECT ROWNUM ,T.* FROM ONE_NEW T ORDER BY T.ONE_NAME
图8
对比图2可以看出,ROWNUM和每一行对应,排序无法改变容ROWNUM的值,这在查询过程中就已经确定好了
那这样能分页吗,之前查询的都是从第一行开始 ,如果我们要查询第二行到第六行的数据呢
SELECT ROWNUM,T.* FROM ONE_NEW T WHERE ROWNUM>=2 AND ROWNUM<=6
图9
结果为空,说明这种查询方式是错误的,换下一种!
3. 伪列作为表中的一列来查询
以上无法查出数据,因为将ROWNUM作为伪列来查的,现在把伪列当作一列来查询
这里给ROWNUM 起别名RN 用来排序查询ROWNUM后的结果
SELECT * FROM
(
SELECT ROWNUM RN,T.* FROM ONE_NEW T WHERE ROWNUM<=6
)
WHERE RN>=2
图10
SELECT ROWNUM,A.* FROM
(
SELECT ROWNUM RN,T.* FROM ONE_NEW T WHERE ROWNUM<=6
) A
WHERE RN>=2
图11
看结果显示,查询出来的RN完成了第一次查询的排序,第二次从结果集中查询显示新的ROWNUM
感觉这样已经可以了,也查询到了我们要的结果了,是不是分页这样就可以了。
现在想对查询结果按one_name排序后取2到5条 按照图八的样子应该显示如下
图12
现在进行查询
SELECT * FROM
(
SELECT ROWNUM RN,T.* FROM ONE_NEW T WHERE ROWNUM<=5
ORDER BY T.ONE_NAME
)
WHERE RN>=2
图13
对比图12明显这种查询结果不同 ,这种是错误的,现在换个方式查询
4. 三层查询
SELECT * FROM (
SELECT ROWNUM RN,T.* FROM
(
SELECT * FROM ONE_NEW ORDER BY ONE_NAME
) T
WHERE ROWNUM<=5 )
WHERE RN>=2 ;
结果如下,
图14
这样就正确了,综上,oracle分页查询时 第一次查询的为待分页的结果集,
外面两层select是对结果集进行分页。
所以 ,Oracle分页查询语句为
select * from
( select A.*,rownum rn from
( select * from table) A
where rownum <=10
) where rn >0
end~
个人浅薄之见,欢迎指正~~ ~~ ~~ ~~ ~~ ~~ ~~~