2008-10-27 69 views
71

我对Oracle并不熟悉,因为我希望成为Oracle。我有大约25万条记录,我想每页显示100条记录。目前,我有一个存储过程,它使用数据适配器,数据集和dataadapter.Fill(dataset)方法从存储过程的结果中检索所有25万记录到数据集。如果我将“页码”和“每页记录数”作为整数值,我可以将其作为参数传递,那么返回该特定部分的最佳方法是什么?比如说,如果我从选择声明中通过10作为页码,120作为页数,它会给我从1880年到1200年,或者类似的东西,我的脑中的数学可能会关闭。我认为这不是重要的,如果我可以在SQL端得到它,那么我应该很酷。与Oracle分页

更新:我能够使用布赖恩的建议,它工作得很好。我想要进行一些优化,但是页面会在4到5秒内完成,而不是一分钟,而且我的分页控制能够很好地与我新存储的特效相集成。

回答

112

像这样的东西应该工作:From Frans Bouma's Blog

SELECT * FROM 
(
    SELECT a.*, rownum r__ 
    FROM 
    (
     SELECT * FROM ORDERS WHERE CustomerID LIKE 'A%' 
     ORDER BY OrderDate DESC, ShippingDate DESC 
    ) a 
    WHERE rownum < ((pageNumber * pageSize) + 1) 
) 
WHERE r__ >= (((pageNumber-1) * pageSize) + 1) 
+0

是ROWNUM保留字您的Oracle版本? – 2011-11-20 17:33:49

+3

是的,它是Oracle支持的“内置”列,始终从1开始,每行增加一个。因此,在这段代码中,如果您有1000行,则应用排序顺序,然后为每行分配一个rownum。外部选择使用这些行号根据您的页面大小来查找您要查找的'页面'。 – 2011-11-20 18:54:24

109

Ask Tom上分页,非常,非常有用的分析功能。

这是从该网页摘录:

select * from (
    select /*+ first_rows(25) */ 
    object_id,object_name, 
    row_number() over 
    (order by object_id) rn 
     from all_objects) 
    where rn between :n and :m 
     order by rn; 
4

尝试以下操作:

SELECT * 
FROM 
    (SELECT FIELDA, 
    FIELDB, 
    FIELDC, 
    ROW_NUMBER() OVER (ORDER BY FIELDC) R 
    FROM TABLE_NAME 
    WHERE FIELDA = 10 
) 
WHERE R >= 10 
AND R <= 15; 

通过 [tecnicume]

31

在完整性的利益,为人们寻找一个更现代化的解决方案,在Oracle 12c有一些新的功能,包括更好的分页和顶部处理。

寻呼

寻呼看起来是这样的:

SELECT * 
FROM user 
ORDER BY first_name 
OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY; 

前N个记录

获取最高的记录是这样的:

SELECT * 
FROM user 
ORDER BY first_name 
FETCH FIRST 5 ROWS ONLY 

请注意上述查询示例如何具有ORDER BY子句。新的命令尊重这些命令并在分类后的数据上运行。

我找不到FETCHOFFSET的Oracle参考页,但this page对这些新功能有很好的概述。

5

只是想总结答案和评论。有很多方法可以做分页。

在oracle 12c之前没有OFFSET/FETCH功能,所以请看@jasonk建议的whitepaper。这是我发现的关于不同方法的最全面的文章,详细解释了优点和缺点。在这里复制粘贴需要很长时间,所以我不会这样做。

jooq创建者还有一篇很好的文章,解释了oracle和其他数据库分页的一些常见注意事项。 jooq's blogpost

好消息,既然oracle 12c我们有一个新的OFFSET/FETCH功能。 OracleMagazine 12c new features。请参考“前N个查询和分页”

您可以检查通过发出下面的语句

SELECT * FROM V$VERSION