我在Oracle中有一个存储过程,我们根据参数限制ROWNUM的记录数。但是,我们还需要知道搜索结果计数是否超过任意限制(即使我们只将数据传递到限制;搜索可以返回大量数据,如果超出限制,用户可能需要改进他们的查询。)
限制运行良好,但我试图将OUT值作为标志传递,以便在超出最大结果时发出信号。我的想法是获取内部表的计数并将其与外部选择查询的计数(使用ROWNUM)进行比较,但我不确定如何将其转换为变量。有没有人这样做过?如果没有两次选择,我有什么方法可以做到这一点吗?
谢谢。
编辑:目前,我实际上做了两个相同的选择 - 一个仅用于计数,选择到我的变量,一个用于实际记录。然后我将基本结果计数的比较传回给我的最大限制参数。这意味着两个选择,这是不理想的。仍然在这里寻找答案。
答案 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