使用ROWNUM查明查询是否超出任意限制?

时间:2015-03-10 14:34:04

标签: sql oracle plsql rownum

我在Oracle中有一个存储过程,我们根据参数限制ROWNUM的记录数。但是,我们还需要知道搜索结果计数是否超过任意限制(即使我们只将数据传递到限制;搜索可以返回大量数据,如果超出限制,用户可能需要改进他们的查询。)

限制运行良好,但我试图将OUT值作为标志传递,以便在超出最大结果时发出信号。我的想法是获取内部表的计数并将其与外部选择查询的计数(使用ROWNUM)进行比较,但我不确定如何将其转换为变量。有没有人这样做过?如果没有两次选择,我有什么方法可以做到这一点吗?

谢谢。

编辑:目前,我实际上做了两个相同的选择 - 一个仅用于计数,选择​​到我的变量,一个用于实际记录。然后我将基本结果计数的比较传回给我的最大限制参数。这意味着两个选择,这是不理想的。仍然在这里寻找答案。

4 个答案:

答案 0 :(得分:3)

您可以在查询中添加一列:

select * from (
  select . . . , count(*) over () as numrows
  from . . .
  where . . .
) where rownum <= 1000;

然后将numrows报告为最终结果集的大小。

答案 1 :(得分:2)

在我的应用程序中,我做了一个非常简单的方法。我执行正常的SELECT,当返回的行数等于限制时,客户端应用程序显示LIMIT reached消息,因为如果您不限制结果,我的查询很可能返回更多行。

当然,当行数完全限制时,这是一个错误的指示。但是,在我的应用程序中,限制主要是出于最终用户的性能原因而设置的,例如,典型的限制是“1000行”或“10000行”。

在我的情况下,这个解决方案是完全足够的 - 而且很简单。

<强>更新

您是否知道row_limiting_clause?它是在Oracle 12.1中引入的

例如此查询

SELECT employee_id, last_name
  FROM employees
  ORDER BY employee_id
  OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY;

将返回整个结果集的第6行到第16行。它可能会帮助您找到解决方案。

另一个想法就是这个:

SELECT employee_id, last_name
FROM employees
UNION ALL
SELECT NULL, NULL FROM dual
ORDER BY employee_id NULLS LAST

当您获得employee_id IS NULL行时,您知道您已达到结果集的末尾,并且不会再有其他记录到达。

答案 2 :(得分:1)

您可以使用嵌套子查询:

select id, case when max_count > 3 then 'Exceeded' else 'OK' end as flag
from (
 select id, rn, max(rn) over () as max_count
 from (
    select id, rownum as rn
    from t
  )
  where rownum <= 4
)
where rownum <= 3;

内部级别是您的实际查询(您可能真的有过滤器和order-by子句)。中间后来限制为您的实际限制+ 1,这仍然允许Oracle使用停止键进行优化,并使用内部结果集的分析计数来查看是否有第四条记录(无需扫描所有匹配的记录) 。外层限制在原来的限制范围内。

使用包含10行的样本表,可获得:

        ID FLAG    
---------- --------
         1 Exceeded 
         2 Exceeded 
         3 Exceeded 

如果内部查询的过滤器返回的行数较少,请说:

select id, rownum as rn
from t
where id < 4

它会得到:

        ID FLAG    
---------- --------
         1 OK       
         2 OK       
         3 OK       

当然,对于这个演示,我没有做任何订购,所以你会得到不确定的结果。根据您的描述,您将使用您的变量而不是3和(您的变量+ 1)而不是4。

答案 3 :(得分:0)

选择整个事物,然后选择计数和数据,限制行数。

with  
base as 
(
    select c1, c2, c3
    from table
    where condition 
) 
select (select count(*) from base), c1, c2, c3 
from base
where rownum < 100