ROWNUM如何在分页查询中工作?

时间:2015-05-19 09:19:10

标签: sql oracle pagination rownum

所以我想在Oracle DB中选择一系列行。我需要这样做,因为我在表中有数百万行,我想将结果分页给用户(如果你知道在客户端执行此操作的另一种方法,我使用JavaFX,如果它很重要,但我不认为通过网络发送所有数据以在客户端对它们进行分页是个好主意。

所以在阅读这篇文章后:SQL ROWNUM how to return rows between a specific range,我有以下问题:

Select * From (Select t.*, rownum r from PERSON t) Where r > 100 and r < 110;

100110只是示例。在应用程序中,我只是要求下限并添加10_000的大小来获取下一个10_000行。

现在rownum列出现在结果中,我不想看到它。由于我对SQL不是很熟悉,所以这是我的问题:

  1. 为什么(这是我第一次尝试直到我搜索SO)Select * From Person Where rownum > 100 and rownum < 110;返回0行?
  2. 为什么没有简单的方法可以执行Select ... FROM ... WHERE rownum BETWEEN lowerBound AND upperBound之类的操作?

  3. 如何删除结果值中的r列?从那里SQL exclude a column using SELECT * [except columnA] FROM tableA?我显然需要创建一个视图或临时表,但考虑我的查询还有另一种方式吗?

  4. 是否确保正确的分页?我阅读了this article部分“使用ROWNUM分页”,其中说我应该通过一些独特的内容对这些值进行排序以获得一致的分页(因此,如果您能确认,我认为按rownum排序是正常的)。它不会破坏使用FIRST_ROWS(N)的目的吗?

  5. 我希望它不是太多,我可以分成不同的问题,但我认为让它们崩溃是相关的,因为它们密切相关。

    谢谢:)

3 个答案:

答案 0 :(得分:25)

您有4个问题,所有问题都围绕 ROWNUM 的使用和功能展开。我将逐一回答每个问题。

  

为什么(这是我在SO上搜索的第一次尝试)选择*来自人的地方rownum&gt; 100和rownum&lt; 110;返回0行?

Thomas Kyte关于ROWNUM和分页here的很好的解释。

ROWNUM 值在通过查询的谓词阶段之后但在查询进行任何排序或聚合之前分配给一行。此外,ROWNUM值仅在分配后递增,这就是以下查询永远不会返回行的原因:

select * 
  from t 
 where ROWNUM > 1;

因为ROWNUM&gt; 1对于第一行不成立,ROWNUM不会前进到2.因此,ROWNUM值不会大于1.

  

为什么没有简单的方法可以做一些像Select ... FROM ... WHERE rownum BETWEEN lowerBound和upperBound?

是的,有。从 Oracle 12c 开始,您可以使用新的前N行限制功能。 See my answer here

例如,以下查询会按升序将员工退回第四高第七高薪

SQL> SELECT empno, sal
  2  FROM   emp
  3  ORDER BY sal
  4  OFFSET 4 ROWS FETCH NEXT 4 ROWS ONLY;

     EMPNO        SAL
---------- ----------
      7654       1250
      7934       1300
      7844       1500
      7499       1600

SQL>
  

如何摆脱结果值中的r列?

而不是select *,在外部查询中列出所需的列名称。对于经常使用查询,创建视图是一个简单的一次性活动。

或者,在 SQL*Plus 中,您可以使用 NOPRINT 命令。它不会显示您不想显示的列名称。但是,它只适用于SQL * Plus。

例如,

COLUMN column_name NOPRINT

例如,

SQL> desc dept
 Name                                      Null?    Type
 ----------------------------------------- -------- ------------
 DEPTNO                                             NUMBER(2)
 DNAME                                              VARCHAR2(14)
 LOC                                                VARCHAR2(13)

SQL> COLUMN dname NOPRINT
SQL> COLUMN LOC NOPRINT
SQL> SELECT * FROM dept;

    DEPTNO
----------
        10
        20
        30
        40

SQL>
  

是否确保正确的分页?

是的,如果您正确编写分页查询。

例如,

SELECT val
FROM   (SELECT val, rownum AS rnum
        FROM   (SELECT val
                FROM   t
                ORDER BY val)
        WHERE rownum <= 8)
WHERE  rnum >= 5;

       VAL
----------
         3
         3
         4
         4

4 rows selected.

SQL>

或者,如上所示,使用12c上的新行限制功能。

很少有例子here

答案 1 :(得分:5)

回答问题2:在Oracle 12中,您可以使用分页

select owner, object_name, object_id
from t
order by owner, object_name
OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY;

答案 2 :(得分:2)

我通常会写一个这样的查询:

select * 
from 
(
    select a.*, rownum as rn  
    from table_name a
    where rownum <= 110
)
where rn > 100