Oracle中关于rownum和分页的详细描述(翻译)

原文为:http://www.oracle.com/technetwork/issue-archive/2006/06-sep/o56asktom-086197.html
Limiting Result Sets
rownum是一个很让人疑惑的oracle概念,这会导致很多人不会使用它,一般情况下,在以下的两个场合,我们会使用到rownum伪列:

  • 执行一个TOP-N查询,如查询最大或最多,最靠前的某些记录,与其它数据库(如mysql)的limit很相似.
  • 对查询进行分页,这个很常见,就不说了。

How ROWNUM Works
rownum是一个伪列,在一个查询中,它并不是真正的列,但在查询结果中就会存在这个列数据。在查询的结果中,rownum会依次从1开始赋值给查询的每一条记录。但这个值并不是固定的,会随着不同的查询发生变化,也就是说在一个数据表中,并不存在rownum这个列,即你不能在一个表中查询rownum为5的数据,没有这种数据。

那么rownum是什么时候被赋值的呢,了解这个时机会让你在一些查询中了解一个sql为什么要这样写。
rownum是在当数据查询一定的条件被查询出来但并没有被排序或者聚合的时候赋值的
也就是说,rownum是在有数据的时候才会递增,如果没有数据被查询出来,则不会递增。如下面的sql语句,则永远不会返回任何数据:

select * 
  from t 
 where ROWNUM > 1;

因为对于第一条数据来说,rowum > 1并不为真,因此rownum也不会递增到2,所以不会有数据的rownum大于1。
我们可以通过下面的一个标准的数据查询,来了解rownum是何时被赋值的。如下所示:

select ..., ROWNUM
  from t
 where <where clause>
 group by <columns>
having <having clause>
 order by <columns>;

那么,一般来说,它会按照以下的顺序来工作:

  1. The FROM/WHERE clause goes first.
  2. ROWNUM is assigned and incremented to each output row from the FROM/WHERE clause.
  3. SELECT is applied.
  4. GROUP BY is applied.
  5. HAVING is applied.
  6. ORDER BY is applied.

继续阅读“Oracle中关于rownum和分页的详细描述(翻译)”

oracle中row_number和rownum的区别和联系(翻译)

附问题:有以下一个SQL语句:

SELECT  *
FROM    (
        SELECT  t.*, row_number() OVER (ORDER BY ID) rn
        FROM    mytable t
        )
WHERE   rn BETWEEN :start and :end

sql中的order by语句大大降低了处理的速度,如果把order by去掉,相应的执行计划会大大地提高。如果换成下面的sql:

SELECT  t.*, row_number() OVER (ORDER BY ID) rn
FROM    mytable t
WHERE   rownum BETWEEN :start and :end

很明显,这个sql是错的,根本查询不了正确的数据信息。是否有其它的方法可以提高查询速度?
针对以上问题,就必须要了解一下关于row_number和rownum的区别,以及如何来运用这些信息。

首先了解一下rownum是如何进行工作的,根据oracle的官方文档:
如果对rownum进行大于比较,这个比较将直接返回false。如,下列sql语句将不能返回任何数据信息:

继续阅读“oracle中row_number和rownum的区别和联系(翻译)”