Oracle中rownum用法

rownum的说明

rownum是oracle特有的一个关键字。

对于基表,在insert记录时,oracle就按照insert的顺序,将rownum分配给每一行记录,因此在select一个基表的时候,rownum的排序是根据insert记录的顺序显示的。例如:

select rownum rn,t.* from emp t;

对于子查询,则rownum的顺序是根据子查询的查询顺序进行动态分配的,例如:

select rownum as t2_rn, t2.*
  from (select rownum as t1_rn, t1.* from emp t1 order by t1.sal) t2;

由上图可以看到T1_RN和T2_RN的区别。

t1中的rownum是根据emp这个基表的默认顺序分配的,而内层子循环是根据SAL字段进行排序,所以t2的rownum是根据内层子查询的记录顺序分配的。

rownum可以用于限制返回查询的总行数,且rownum不可以以任何表的名称作为前缀

1、rownum对于等于某值的查询条件:如果想找到第一条查询数据,可以使用rownum=1作为查询条件,但是想找到第二条查询数据,使用rownum=2则查不到数据,原因是:rownum都是从1开始,但是1以上的自然数与rownum做等于时,都认为是false条件,所以无法查询到rownum=n (n>1的自然数);

2、rownum对于大于某值的查询条件:要是想查询出第二行以后的记录,直接使用rownum>2是查不出数据的,原因是rownum是一个总是以1开始的伪例,rownum>n (n>1的自然数)依然不成立。可以使用子查询来解决,注意子查询中的rownum必须要有别名,否则还是不会查出记录来,这是因为rownum不是某个表的列,如果不起别名的话,无法知道rownum是子查询的列还是主查询的列。例如:

select * from(select rownum no ,id,name from student) where no>2;

3、rownum对于小于某值的查询条件: rownum对于rownum<n((n>1的自然数)的条件认为是成立的,所以可以找到记录。

注意:对于查询rownum在某区间的数据,必须使用子查询,例如要查询rownum在第二行到第三行之间的数据,包括第二行和第三行数据,那么我们只能写以下语句,先让它返回小于等于三的记录行,然后在主查询中判断新的rownum的别名列大于等于二的记录行。但是这样的操作会在大数据集中影响速度。

select * from (selectrownum no,id,name from student where rownum<=3 ) where no >=2

4、rownum和排序 Oracle中的rownum的是在取数据的时候产生的序号,所以想对指定排序的数据去指定的rowmun行数据就必须注意了。

select rownum ,id,name from student order by name;

对于这个查询语句,rownum并不是按name生成的序号,系统是按照记录插入时的顺序给记录排的号,rowid也是顺序分配的。为了解决这个问题,必须使用子查询:

select rownum ,id,name from (select * from student order by name);

rownum的一些使用技巧

场景一:使用rownum限制查询返回的记录数

1、例如,我们现在只想看到emp表中的第一条记录:

select * from emp where rownum=1;

2、现在,我们现在想查看emp中的前2条记录:

select * from emp where rownum<=2;

3、假如我们现在只想查看emp中的第二条记录,又该如何写语句呢?

如果where条件为:rownum=2,来看看查询结果:

发现没有查出任何数据,为什么呢?

因为rownum并不是当作实体数据存放在每一张表中,而是在每一次select查询的时候,根据基表的默认insert顺序由oracle动态分配的,有1才有2,如果rownum没有1,那么2也就没有了意义,所以这个查询就不会有任何结果出来。这个时候我们就需要利用子查询和别名列来实现这个需求:

select *
  from (select rownum as rn, t.* from emp t where rownum <= 2)
where rn = 2;

首先通过子查询,取出emp表的前2条记录,并将子查询中的rownum定义为别名rn,然后在外层查询中,使用where条件使rn=2即可,查询出emp表的第二条记录:

几种分页查询SQL语句

效率高的写法

无ORDER BY排序的写法。(效率最高)

(经过测试,此方法成本最低,只嵌套一层,速度最快!即使查询的数据量再大,也几乎不受影响,速度依然!)

SELECT *
  FROM (SELECT ROWNUM AS rowno, t.*
          FROM emp t
         WHERE hire_date BETWEEN TO_DATE('20060501', 'yyyymmdd') AND
               TO_DATE('20060731', 'yyyymmdd')
           AND ROWNUM <= 20) table_alias
 WHERE table_alias.rowno >= 10;

有ORDER BY排序的写法。(效率较高)

(经过测试,此方法随着查询范围的扩大,速度也会越来越慢)

SELECT *
  FROM (SELECT tt.*, ROWNUM AS rowno
          FROM (SELECT t.*
                  FROM emp t
                 WHERE hire_date BETWEEN TO_DATE('20060501', 'yyyymmdd') AND
                       TO_DATE('20060731', 'yyyymmdd')
                 ORDER BY create_time DESC, emp_no) tt
         WHERE ROWNUM <= 20) table_alias
 WHERE table_alias.rowno >= 10;

效率垃圾但又似乎很常用的分页写法

SELECT *
  FROM (SELECT ROWNUM AS rowno, t.*
          FROM k_task t
         WHERE flight_date BETWEEN TO_DATE('20060501', 'yyyymmdd') AND
               TO_DATE('20060731', 'yyyymmdd')) table_alias
 WHERE table_alias.rowno <= 20
   AND table_alias.rowno >= 10;
-- TABLE_ALIAS.ROWNO  between 10 and 100;

 

posted @ 2022-06-08 11:59  残城碎梦  阅读(16753)  评论(0编辑  收藏  举报