zoukankan      html  css  js  c++  java
  • oracle中 rownum与rowid的理

    一、 Oracle分页查询

    我们先看学习一下oracle分页查询的语法示例,然后在具体学习用rownum的原理。

    /*从第1条开始,每次选N个,从第1+M个开始每次选N*/

    /**/

     select t2.*

       from (select rid

               from (select r.rid, rownum linenum

                       from (select rowid rid

                               from tablename t [条件限制]

                              [order by rid desc]) r

                      WHERE rownum <= 5 [条件限制]

                      [order by rid desc])

      WHERE linenum >= 1) t1, tablename t2

      where t1.rid = t2.rowid

     /*排序,选出来5个,分页显示,下面两为两种方法*/

     select t2.*

       from (select rid

               from (select r.rid, rownum linenum

                       from (select rowid rid, t.* from tablename t) r

                      WHERE rownum <= 10 [条件限制]

                      [order by rowid desc])

              WHERE linenum >= 6) t1,

            tablename t2

      where t1.rid = t2.rowid

     

       select *

         from (select t.*, rownum rn

                 from tablename t

                where rownum <= 10 [条件限制]

                [order by t.rowid desc])

        where rn >= 6;

     

     select * from tablename where rownum>1

     select * from tablename where rownum>=1

     select * from tablename where rownum>0

    select   t2.* 
    from (select rid
              from (select r.rid, rownum linenum
                      from (select                    
                             rowid rid
                              from tablename t
                             [条件限制]) r
                     WHERE rownum <= 50)
             WHERE linenum >=1) t1,
          tablename t2
    where t1.rid = t2.rowid(利用rowid分页,效率最高的一种,t2.*根据需要换成需要查询的列)

    select count(element) from tablename

    二、 oracle中 rownumrowid的理解

    rownum,rowid都叫伪列。 但是,rownum是逻辑上的编号,且其值总是从1开始,每行的rounum不是固定的。而rowid是“物理”编号。若数据库文件没有移动,则每行的 rowid一般是固定不变的。

     

    racle中rownum用法的总结

    对于 Oracle 的 rownum 问题,很多资料都说不支持>,>=,=,between...and,只能用以上符号(<、<=、!=),并非说用>,>=,=,between..and 时会提示SQL语法错误,而是经常是查不出一条记录来,还会出现似乎是莫名其妙的结果来,其实您只要理解好了这个 rownum 伪列的意义就不应该感到惊奇,同样是伪列,rownum 与 rowid 可有些不一样,下面以例子说明 

    假设某个表 t1(c1) 有 20 条记录

     

    如果用 select rownum,c1 from t1 where rownum < 10, 只要是用小于号,查出来的结果很容易地与一般理解在概念上能达成一致,应该不会有任何疑问的。

     

    可如果用 select rownum,c1 from t1 where rownum > 10 (如果写下这样的查询语句,这时候在您的头脑中应该是想得到表中后面10条记录),你就会发现,显示出来的结果要让您失望了,也许您还会怀疑是不谁删了一些记录,然后查看记录数,仍然是 20 条啊?那问题是出在哪呢?

     

    先好好理解 rownum 的意义吧。因为ROWNUM是对结果集加的一个伪列,即先查到结果集之后再加上去的一个列 (强调:先要有结果集)。简单的说 rownum 是对符合条件结果的序列号。它总是从1开始排起的。所以你选出的结果不可能没有1,而有其他大于1的值。所以您没办法期望得到下面的结果集:

     

    11 aaaaaaaa

    12 bbbbbbb

    13 ccccccc

    .................

     

    rownum >10 没有记录,因为第一条不满足去掉的话,第二条的ROWNUM又成了1,所以永远没有满足条件的记录。或者可以这样理解:

     

    ROWNUM是一个序列,是oracle数据库从数据文件或缓冲区中读取数据的顺序。它取得第一条记录则rownum值为1,第二条为2,依次类推。如果你用>,>=,=,between...and这些条件,因为从缓冲区或数据文件中得到的第一条记录的rownum为1,则被删除,接着取下条,可是它的rownum还是1,又被删除,依次类推,便没有了数据。

     

    有了以上从不同方面建立起来的对 rownum 的概念,那我们可以来认识使用 rownum 的几种现像

     

    1. select rownum,c1 from t1 where rownum != 10 为何是返回前9条数据呢?它与 select rownum,c1 from tablename where rownum < 10 返回的结果集是一样的呢?

    因为是在查询到结果集后,显示完第 9 条记录后,之后的记录也都是 != 10,或者 >=10,所以只显示前面9条记录。也可以这样理解,rownum 为9后的记录的 rownum为10,因条件为 !=10,所以去掉,其后记录补上,rownum又是10,也去掉,如果下去也就只会显示前面9条记录了

     

    2. 为什么 rownum >1 时查不到一条记录,而 rownum >0 或 rownum >=1 却总显示所以的记录

    因为 rownum 是在查询到的结果集后加上去的,它总是从1开始

     

    3. 为什么 between 1 and 10 或者 between 0 and 10 能查到结果,而用 between 2 and 10 却得不到结果

    原因同上一样,因为 rownum 总是从 1 开始

     

    从上可以看出,任何时候想把 rownum = 1 这条记录抛弃是不对的,它在结果集中是不可或缺的,少了rownum=1 就像空中楼阁一般不能存在,所以你的 rownum 条件要包含到 1 

     

    但如果就是想要用 rownum > 10 这种条件的话话就要用嵌套语句,把 rownum 先生成,然后对他进行查询。

    select * 

    from (selet rownum as rn,t1.* from a where ...)

    where rn >10

     

    一般代码中对结果集进行分页就是这么干的。

    另外:rowid 与 rownum 虽都被称为伪列,但它们的存在方式是不一样的,rowid 可以说是物理存在的,表示记录在表空间中的唯一位置ID,在DB中唯一。只要记录没被搬动过,rowid是不变的。rowid 相对于表来说又像表中的一般列,所以以 rowid 为条件就不会有 rownum那些情况发生。

    另外还要注意:rownum不能以任何基表的名称作为前缀。

     

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 传球游戏
    Java实现 蓝桥杯VIP 算法训练 Hanoi问题
    Java实现 蓝桥杯VIP 算法训练 蜜蜂飞舞
    Java实现 蓝桥杯VIP 算法训练 奇偶判断
    Java实现 蓝桥杯VIP 算法训练 传球游戏
    Java实现 蓝桥杯VIP 算法训练 Hanoi问题
    Java实现 蓝桥杯VIP 算法训练 Hanoi问题
    Java实现 蓝桥杯VIP 算法训练 蜜蜂飞舞
    Java实现 蓝桥杯VIP 算法训练 蜜蜂飞舞
    Qt: 访问容器(三种方法,加上for循环就四种了)good
  • 原文地址:https://www.cnblogs.com/wuxi/p/2737947.html
Copyright © 2011-2022 走看看