从子查询存储过程分配变量

时间:2014-04-15 00:47:59

标签: oracle stored-procedures plsql subquery oracle-sqldeveloper

我有一个Oracle 11.2.0存储过程,它返回一些输出参数。查询的结果是使用从复杂子查询填充的refcursor。我需要将子查询中的记录计数作为NUMBER输出参数返回。我在尝试将计数分配给子查询内部的变量时遇到了麻烦。有人可以在Oracle中知道这是否可行,或者是否有另一种方法可以做到这一点。我只需要从存储过程中返回数据和数据记录的计数。我不确定如何分配和返回计数,因为查询结果是从子查询select语句返回的。我尝试做的一个例子如下:

p_results           OUT sys_refcursor,
p_count             OUT NUMBER
OPEN p_results 
FOR 
  WITH Output1 AS
    (
    SELECT * from table1
    ),
output2 AS
    (
    SELECT * from table2 a
    left outer join Output1 b
    on a.id = b.id
     )
    Select * from output2
    p_count := select count(id) from output2   --how can I return parameters for results and count using subquery

1 个答案:

答案 0 :(得分:1)

你无法做你想做的事。在获取最后一行之前,Oracle不知道游标将返回多少行。由于游标是仅向前结构,如果您的目标是将游标返回到调用应用程序,则无法在代码中从中获取游标。

您可以重复查询并分两步执行此操作

SELECT COUNT(id)
  INTO p_count
  FROM (<<your query>>);

OPEN p_results
 FOR <<your query>>;

这有明显的缺点,你将运行查询,计算所有结果,然后第二次重新运行查询,这是相对低效的。它有一个不太明显的缺点,即count可能与游标返回的行数不匹配,因为某些其他会话可能在您的初始SELECT语句开始的时间和游标的时间之间提交。打开,从而更改将返回的行集。

您还可以在结果的每一行添加计算count,即

OPEN p_results
 FOR ...
     Select o2.*, count(*) over () cnt 
       from output2 o2

这将消除两个查询返回不同行数的可能性。但是,它会使查询成本更高,因为Oracle需要在客户端开始从中获取结果集之前实现结果集。它可能比运行相同的查询两次更有效,除非每行重复的附加数值通过增加需要通过网络传输或由客户端缓冲的数据量来创建性能问题。

一般来说,我对任何将计数和一组结果都返回给调用应用程序的设计都非常怀疑。无论如何,调用应用程序将需要从光标获取代码。如果它具有该代码,则非常适合计算它实际获取的行数,然后对该计算结果进行操作。您的程序应该只返回sys_refcursor并将计数留给客户。