因为ROWNUM是对结果集加的一个伪列,即先查到结果集之后再加上去的一个列 (强调:先要有结果集)。简单的说 rownum 是对符合条件结果的序列号。它总是从1开始排起的。这个伪字段可以用于限制查询返回的总行数,而且rownum不能以任何表的名称作为前缀。
另外:rowid 与 rownum 虽都被称为伪列,但它们的存在方式是不一样的,rowid 可以说是物理存在的,表示记录在表空间中的唯一位置ID,在DB中唯一。只要记录没被搬动过,rowid是不变的。rowid 相对于表来说又像表中的一般列,所以以 rowid 为条件就不会有 rownum那些情况发生。
1.rownum = n
如果希望找到第一条信息,可以使用rownum=1作为条件。
但是想找到表中第二条信息,使用rownum=2结果查不到数据。(注意不是报错,是没数据)
因为rownum都是从1开始,但是1以上的自然数在rownum做等于判断是时认为都是false条件,所以无法查到rownum = n(n>1的自然数)。(可以用在限制返回记录条数的地方,保证不出错,如:隐式游标)
2.rownum > n
如果想找到从第二行记录以后的记录,当使用rownum>2是查不出记录的,原因是由于rownum是一个总是从1开始的伪列,Oracle 认为rownum>n(n>1的自然数)这种条件依旧不成立,所以查不到记录 。
那如何才能找到第二行以后的记录?可以使用以下的子查询方法来解决。
注意子查询中的rownum必须要有别名,否则还是不会查出记录来,这是因为rownum不是某个表的列,如果不起别名的话,无法知道rownum是子查询的列还是主查询的列。
select * from(select rownum no ,FILE_ID,priority from index_file_info) where no>2;
3.rownum < n
如果想找到第三条记录以前的记录,当使用rownum<3是能得到两条记录的。显然rownum对于rownum<n((n>1的自然数)的条件认为是成立的,所以可以找到记录。
4.n < rownum < m
例如要查询rownum在第二行到第三行之间的数据,包括第二行和第三行数据,那么我们只能写以下语句,先让它返回小于等于三的记录行,然后在主查询中判断新的rownum的别名列大于等于二的记录行。但是这样的操作会在大数据集中影响速度。
select * from(select rownum num, FILE_ID,priority from index_file_info where rownum<=3) where num>=2;
5.rownum 和 order by
Oracle中的rownum的是在取数据的时候产生的序号,所以想对指定排序的数据去指定的rowmun行数据就必须注意了。
select rownum, FILE_ID,priority from index_file_info order by file_id;
rownum FILE_ID priority
627 eoa_0_10_103.txt 10
628
eoa_0_10_120.txt 10
可以看出,rownum并不是按照FILE_ID列来生成的序号。系统是按照记录插入时的顺序给记录排的号,rownum也是顺序分配的。为了解决这个问题,必须使用子查询
select rownum ,FILE_ID,priority from (select * from index_file_info order by FILE_ID);
rownum FILE_ID priority
1
eoa_0_10_103.txt 10
问题一:按某个字段排序,取前20条(分页)
“select * from tabname where rownum < 20 order by name" 但却发现oracle却不能按自己的意愿来执行,而是先随便取20条记录,然后再 order by,后经咨询oracle,说rownum确实就这样,想用的话,只能用子查询 来实现先排序,后 rownum,方法如下:
"select * from (select * fromtabname order by name) where rownum<20",但这样一来,效率会较低很多。 只需在orderby 的字段上加主键或索引即可让oracle先按 该字段排序,然后再rownum;
如果排序列上有索引,则借助索引去查询数据,这样,读取出来的数据和rownum产生的序号是一种正常的对应关系,如语句一的结果(empno上有主键索引)。
如果排序列上没有索引,则使用全表扫描的方式,依次从表中读取数据,读取完成后,最后进行排序,于是产生了类似语句二的结果(sal列上没有索引)。
select * from
(select rownum num, t.* from
(select FILE_ID, priority from index_file_info order by FILE_ID) t)
where num between 6 and 10;
当然,如果使用分析函数row_number就可以省略一层查询了,代码更简单点:
select * from
(select row_number() over (order by FILE_ID) num, priority, FILE_ID from index_file_info)
where num between 6 and 10;