使用 ROWNUM 查明查询是否超过任意限制?
Find out if query exceeds arbitrary limit using ROWNUM?
我在 Oracle 中有一个存储过程,我们正在根据参数限制 ROWNUM 的记录数。但是,我们还需要知道搜索结果计数是否超过任意限制(即使我们只传递达到限制的数据;搜索可以 return 大量数据,如果超过限制用户可能想要优化他们的查询。)
限制运行良好,但我试图传递一个 OUT 值作为标志,以在超过最大结果时发出信号。我的想法是获取内部 table 的计数并将其与外部 select 查询(使用 ROWNUM)的计数进行比较,但我不确定如何将其放入变量中.有没有人这样做过?有什么方法可以做到这一点而无需 select 将所有内容都检查两次?
谢谢。
编辑:目前,我实际上正在做两个相同的 selects - 一个仅用于计数,selected 到我的变量中,另一个用于实际记录。然后我将基本结果计数的比较返回给我的最大限制参数。这意味着两个 selects,这并不理想。仍在此处寻找答案。
您可以在查询中添加一列:
select * from (
select . . . , count(*) over () as numrows
from . . .
where . . .
) where rownum <= 1000;
然后上报numrows
作为最终结果集的大小
您可以使用嵌套子查询:
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;
内层是您的实际查询(您实际上可能有过滤器和排序子句)。中间后来限制为您的实际限制 + 1,这仍然允许 Oracle 使用停止键进行优化,并使用对该内部结果集的分析计数来查看您是否有第四条记录(不需要扫描所有匹配记录) .并且外层限制为您的原始限制。
对于包含 10 行的样本 table,得到:
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。
在我的应用程序中,我采用了一种非常简单的方法。我执行正常的 SELECT,当 returned 行数等于限制时,客户端应用程序显示 LIMIT reached
消息,因为我的查询很可能会 return 更多行,以防您不限制结果。
当然,当行数正好限制时,这是一个错误的指示。但是,在我的应用程序中,限制主要是由最终用户出于性能原因设置的,例如,典型的限制是“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;
将return整个结果集的第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
所在的行时,您就知道您已到达结果集的末尾,不会有更多记录到达。
Select 全部,然后 select 计数和数据,限制行数。
with
base as
(
select c1, c2, c3
from table
where condition
)
select (select count(*) from base), c1, c2, c3
from base
where rownum < 100
我在 Oracle 中有一个存储过程,我们正在根据参数限制 ROWNUM 的记录数。但是,我们还需要知道搜索结果计数是否超过任意限制(即使我们只传递达到限制的数据;搜索可以 return 大量数据,如果超过限制用户可能想要优化他们的查询。)
限制运行良好,但我试图传递一个 OUT 值作为标志,以在超过最大结果时发出信号。我的想法是获取内部 table 的计数并将其与外部 select 查询(使用 ROWNUM)的计数进行比较,但我不确定如何将其放入变量中.有没有人这样做过?有什么方法可以做到这一点而无需 select 将所有内容都检查两次?
谢谢。
编辑:目前,我实际上正在做两个相同的 selects - 一个仅用于计数,selected 到我的变量中,另一个用于实际记录。然后我将基本结果计数的比较返回给我的最大限制参数。这意味着两个 selects,这并不理想。仍在此处寻找答案。
您可以在查询中添加一列:
select * from (
select . . . , count(*) over () as numrows
from . . .
where . . .
) where rownum <= 1000;
然后上报numrows
作为最终结果集的大小
您可以使用嵌套子查询:
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;
内层是您的实际查询(您实际上可能有过滤器和排序子句)。中间后来限制为您的实际限制 + 1,这仍然允许 Oracle 使用停止键进行优化,并使用对该内部结果集的分析计数来查看您是否有第四条记录(不需要扫描所有匹配记录) .并且外层限制为您的原始限制。
对于包含 10 行的样本 table,得到:
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。
在我的应用程序中,我采用了一种非常简单的方法。我执行正常的 SELECT,当 returned 行数等于限制时,客户端应用程序显示 LIMIT reached
消息,因为我的查询很可能会 return 更多行,以防您不限制结果。
当然,当行数正好限制时,这是一个错误的指示。但是,在我的应用程序中,限制主要是由最终用户出于性能原因设置的,例如,典型的限制是“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;
将return整个结果集的第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
所在的行时,您就知道您已到达结果集的末尾,不会有更多记录到达。
Select 全部,然后 select 计数和数据,限制行数。
with
base as
(
select c1, c2, c3
from table
where condition
)
select (select count(*) from base), c1, c2, c3
from base
where rownum < 100