Oracle分页查询探究

导语 :接触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

为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~

个人浅薄之见,欢迎指正~~ ~~ ~~ ~~ ~~ ~~ ~~~

猜你喜欢

转载自blog.csdn.net/qq519423035/article/details/81191461