oracle中rownum用法[转载]

对于rownum来说它是oracle系统顺序分配为从 查询 返回的行的编号,返回的第一行分配的是1,第二行是2,依此类推,这个伪字段可以用于限制查询 返回的总行数,且rownum不能以任何表的名称作为前缀。

(1) rownum 对于等于某值的查询
如果希望找到学生表中第一 学生的信息,可以使用rownum=1作为 件。但是想找到学生表中第二 学生的信息,使用rownum=2结果查不到数据。因为rownum都是从1开始,但是1以上的自然数在rownum做等于判断是时认为都是false 件, 所以无法查到rownum = n(n>1的自然数)。
SQL> select rownum,id,name from student where rownum=1;(可以用在限制返回记录 数的地方,保证不出错,如:隐式游标)
SQL> select rownum,id,name from student where rownum =2;
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------

(2)rownum对于大于某值的查询
   如果想找到从第二行记录以后的记录,当使用rownum>2是查不出记录的,原因是由于rownum是一个总是从1开始的伪列,Oracle 认为rownum> n(n>1的自然数)这种 件依旧不成立,所以查不到记录。

查找
到第 二行以后的记录可使用以下的查询 方法 来解决。注意子查询 中的rownum必须要有别名, 否则还是不会查出记录来,这是因为rownum不是某个表的列,如果不起别名的话,无法知道rownum是子查询 的列还是主查询 的列
SQL>select * from(select rownum no ,id,name from student) where no>2;
        NO ID     NAME
---------- ------ ---------------------------------------------------
         3 200003 李三
         4 200004 赵四

(3)rownum对于小于某值的查询
rownum对于rownum<n((n>1的自然数)的 件认为是成立的,所以可以找到记录。
SQL> select rownum,id,name from student where rownum <3;
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
        1 200001 张一
        2 200002 王二

查询 rownum在某区间的数据,必须使用子查询 例如要查询 rownum在第二行到第 三行之间的数据,包括第二行和第三行数据,那么我们只能写以下语句,先让它返回小于等于三的记录行,然后在主查询 中判断新的rownum的别名列大于等于二的记录行。但是 这样的操作会在大数据集中影响速度。
SQL> select * from (select rownum no ,id,name from student where rownum<=3 ) where no >=2;
        NO ID     NAME
---------- ------ ---------------------------------------------------
         2 200002 王二
         3 200003 李三

(4)rownum和排序  
Oracle中的rownum的是在取数据的时候产生的序号, 所以
想对指定排序的数据去指定的rowmun行数据就必须注意了。
SQL> select rownum ,id,name from student order by name;
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
         3 200003 李三
         2 200002 王二
         1 200001 张一
         4 200004 赵四
可以看出,rownum并不是按照name列来生成的序号。系统是按照记录插入时的顺序给记录排的号, rowid也是顺序分配的。为了解决这个问题,
必须使用子查询
SQL> select rownum ,id,name from (select * from student order by name);
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
         1 200003 李三
         2 200002 王二
         3 200001 张一
         4 200004 赵四
这样就成了按name排序,并且用rownum标出正确序号(有小到大)
笔者在工作中有一上百万
条记录 的表,在jsp页面中需对该表进行分页显示,便考虑用rownum来作,下面是具体方法(每页显示20 ):
“select * from tabname where rownum<20 order by name" 但却发现oracle却不能按自己的意愿来执行,而是先随便取20条记录 ,然后再order by ,后经咨询oracle,说rownum确实就这样,想用的话,只能用子查询 来实现先排序,后rownum ,方法如下:
"select * from (select * from tabname order by name) where rownum<20",但这样一来,效率会低很多。
后经笔者试验,只需在order by 的字段上加主键或索引即可让oracle先按该字段排序, 然后再rownum;方法不变:    “select * from tabname where rownum<20 order by name"

取得某列中 第N 大的行

select column_name from
(select table_name.*,dense_rank() over (order by column desc) rank from table_name)
where rank = &N;
 假如要返回前5条记录

  select * from tablename where rownum<6;(或是rownum <= 5 或是rownum != 6)
假如要返回第5-9条记录

select * from tablename
where …
and rownum<10
minus
select * from tablename
where …
and rownum<5
order by name
选出结果后用name排序显示结果。(先选再排序)

注意:只能用以上符号(<、<=、!=)。

select * from tablename where rownum != 10;返回的是前9条记录
不能用:>,>=,=,Between...and。由于rownum是一个总是从1开始的伪列,Oracle 认为这种 件不成立。

另外,这个方法更快:

select * from (
select rownum r,a from yourtable
where rownum <= 20
order by name )
where r > 10
这样取出第11-20条记录 !(先选再排序再选)

要先排序再选则须用select嵌套:内层排序外层选。
rownum是随着结果集生成的,一旦生成,就不会变化了;同时,生成的结果是依次递加的,没有1就永远不会有2!
rownum 是在查询 集合产生的过程中产生的伪列,并且如果where 件中存在 rownum 件的话,则:

1: 假如判定 件是常量,则:
只能 rownum = 1, <= 大于1 的自然数, = 大于1 的数是没有结果的;大于一个数也是没有结果的
当出现一个 rownum 不满足 件的时候则 查询 结束 this is stop key(一个不满足,系统将该记录过滤掉,则下一条记录 的rownum还是这个,所以后面的就不再有满足记录,this is stop key)

2: 假如判定值不是常量,则:

件是 = var , 则只有当 var 为1 的时候才满足 件,这个时候不存在 stop key ,必须进行full scan ,对每个满足其他where 件的数据进行判定,选出一行后才能去选rownum=2的行……

 

以下摘自《中国IT实验室》

1. ORACLE 实现 SELECT TOP N

   由于 ORACLE 不支持 SELECT TOP 句,所以在 ORACLE 常是用 ORDER BY ROWNUM 合来 实现 SELECT TOP N 查询

简单 实现 方法如下所示:

SELECT  列名1...列名n  FROM

    (SELECT  列名1...列名n  FROM 表名 ORDER BY 列名1...列名n )

   WHERE ROWNUM <= N (抽出 记录 数)

ORDER BY ROWNUM ASC

   下面 个例子 简单说 明一下。

客表 customer(id,name) 有如下数据:

ID NAME

   01 first

   02 Second

   03 third

   04 forth

   05 fifth

   06 sixth

   07 seventh

   08 eighth

   09 ninth

   10 tenth

   11 last

   NAME 的字母 抽出前三个 客的 SQL 句如下所示:

SELECT * FROM

    (SELECT * FROM CUSTOMER ORDER BY NAME)

   WHERE ROWNUM <= 3

   ORDER BY ROWNUM ASC

  

ID NAME

   08 eighth

   05 fifth

   01 first

2. TOP N 纪录 中抽出第 M M <= N 记录

ROWNUM 记录 表中数据 号的一个 藏子段,所以可以在得到 TOP N 记录 候同 抽出 记录 ROWNUM ,然后再从 N 记录 中抽取 记录编 M 记录 ,即使我 希望得到的 果。

从上面的分析可以很容易得到下面的 SQL 句。

SELECT 列名1...列名n FROM

     (

     SELECT ROWNUM RECNO, 列名1...列名n FROM

       (SELECT 列名1...列名n FROM 表名 ORDER BY 列名1...列名n )

     WHERE ROWNUM <= N (抽出 记录 数)

   ORDER BY ROWNUM ASC

     )

   WHERE RECNO = M M <= N

以上表的数据 ,那 得到以 NAME 的字母 排序的第二个 客的信息的 SQL 应该这样 写:

   SELECT ID, NAME FROM

     (

      SELECT ROWNUM RECNO, ID, NAME FROM

        (SELECT * FROM CUSTOMER ORDER BY NAME)

         WHERE ROWNUM <= 3

         ORDER BY ROWNUM ASC )

       WHERE RECNO = 2

     则为

   ID NAME

    05 fifth

3. 抽出按某 方式排序的 记录 集中的第 N 记录

   2 明中,当 M = N 候,即 标题讲 果。 实际 上, 2 的做法在里面 N>M 的部分的数据是基本上不会用到的,我 们仅仅 明方便而采用。

   如上所述, SQL 应为

SELECT 列名1...列名n FROM

     (

      SELECT ROWNUM RECNO, 列名1...列名n FROM

        (SELECT 列名1...列名n FROM 表名 ORDER BY 列名1...列名n )

         WHERE ROWNUM <= N (抽出 记录 数)

      ORDER BY ROWNUM ASC

     )

     WHERE RECNO = N

     2 中的例子的 SQL 则为

    SELECT ID, NAME FROM

      (

       SELECT ROWNUM RECNO, ID, NAME FROM

         (SELECT * FROM CUSTOMER ORDER BY NAME)

       WHERE ROWNUM <= 2

       ORDER BY ROWNUM ASC

      )

      WHERE RECNO = 2

    

   ID NAME

    05 fifth

4. 抽出按某 方式排序的 记录 集中的第 M 记录开 始的 X 记录

   3 里所 仅仅 是抽取一 记录 的情况,当我 需要抽取多 记录 候,此 2 中的 N 的取 值应该 是在 N >= (M + X - 1) 个范 内,当 经济 的取 就是取等好的 候了的 候了。当然最后的抽取 件也不是 RECNO = N 了, 应该 RECNO BETWEEN M AND (M + X - 1) 了,所以随之而来的 SQL 则为

   SELECT 列名1...列名n FROM

    (

     SELECT ROWNUM RECNO, 列名1...列名n FROM

      (

      SELECT 列名1...列名n FROM 表名 ORDER BY 列名1...列名n )

      WHERE ROWNUM <= N N >= (M + X - 1)

    ORDER BY ROWNUM ASC

      )

     WHERE RECNO BETWEEN M AND (M + X - 1)

    以上面的数据 例, 抽取 NAME 的字母 的第 2 记录开 始的 3 记录 SQL

   SELECT ID, NAME FROM

     (

      SELECT ROWNUM RECNO, ID, NAME FROM

        (SELECT * FROM CUSTOMER ORDER BY NAME)

      WHERE ROWNUM <= (2 + 3 - 1)

      ORDER BY ROWNUM ASC

     )

     WHERE RECNO BETWEEN 2 AND (2 + 3 - 1)

     果如下:

   ID NAME

    05 fifth

    01 first

   04 forth

    以此 ,再 展的 ,做成存 储过 程,将 记录 数以及抽取 记录 参数,就可以 实现 抽取数据。

   当然了,上面所 的都是一些最基本的, 实际应 用中往往都没有 这么简单 ,但是不管怎 么说 ,不管 复杂 是由 简单 的元素构成,掌握一些最基本的方法始 是重要的。

;