使用ROWNUM时的差异

5

我在网上搜索Oracle分页查询的方法,大多数都建议将查询语句包装两次:

SELECT * 
  FROM (SELECT t.*, ROWNUM rn 
          FROM tableName t 
         WHERE ROWNUM < 200) 
 WHERE rn > 100

我在想我能不能这样输入:

SELECT *, ROWNUM rn 
  FROM tableName t 
 WHERE ROWNUN BETWEEN 100 AND 200

看起来第二个查询也可以正常工作。这两个查询之间有任何(性能)差异吗?


1
我想你可能已经得到了你需要的答案,但我发现对于刚接触Oracle的人来说,分页查询通常很困难,特别是因为mysql使用LIMIT关键字使其变得如此简单。我会说这是Oracle初学者最常犯的错误之一,所以我最近写了一篇关于它的文章 - http://betteratoracle.com/posts/18-limiting-query-results-top-n-and-window-queries - Stephen ODonnell
2个回答

4

使用 ROWNUM 的正确方式是:

SELECT x.* 
  FROM (SELECT t.*, 
               ROWNUM rn 
          FROM tableName t) AS x
 WHERE x.rn > 100
   AND x.rn < 200

BETWEEN是包含的,因此这两个查询的逻辑不完全相同。

关于ROWNUM的更多信息,请参见此链接(包括Oracle文档链接)


谢谢您的回答。我最关心的是这两个查询在我的问题中是否有性能差异。您能否看一下以下链接:https://dev59.com/v3VC5IYBdhLWcg3wnCWA 它将查询包装了两次。 - GaryX
@GaryX:就像我所说的,这两个查询并不相同;第二个查询将返回表中的所有内容。在获得有效数据之前,性能是一个问题。 - OMG Ponies
@OMG Ponies,你的意思是说,“在获得有效数据之前,性能并不重要”吗? - Shannon Severance

4
问题在于您正在筛选生成ROWNUM的同一查询。因此,必须先使用子查询生成rownum,然后应用过滤。BETWEEN之所以有效,可能是引擎处理查询的某些微妙之处,但我会警惕它可能不会始终给您正确的结果。因此,这不是性能问题,而是确保获得正确结果的问题。
本文解释了为什么必须将大于号放在子查询外部:http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/pseudocolumns009.htm
SELECT * FROM employees
    WHERE ROWNUM > 1;

"

第一行记录的 ROWNUM 被赋值为 1,导致条件不成立。接下来要获取的第二行记录现在变成了第一行,也被赋值为 ROWNUM 1,并且使得条件不成立。所有随后获取的行都无法满足条件,因此没有行被返回。

"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接