使用Select Query在另一个存储过程中执行存储过程

时间:2016-08-06 20:42:16

标签: sql stored-procedures plsql oracle-sqldeveloper

我想在我自己的存储过程中的表的每一行上调用存储过程。在SQL Developer工作区中,我可以这样简单地调用它:

SELECT my_stored_proc(...)
FROM my_table

但是在我的存储过程中,这似乎没有执行:

stmt := 'SELECT my_stored_proc(...) FROM my_table';
EXECUTE IMMEDIATE stmt;

这确实有效:

DECLARE
l_cursor sys_refcursor;

BEGIN
OPEN l_cursor FOR stmt;
LOOP
  FETCH l_cursor INTO ...;
  EXIT WHEN l_cursor%NOTFOUND;
  my_stored_proc(...);
END LOOP;
...

我的问题是为什么会发生这种情况。

2 个答案:

答案 0 :(得分:4)

第二个示例中的行为明确涵盖in a prominent note in the documentation

  

如果 dynamic_sql_statement 是SELECT语句,并且您省略了 into_clause bulk_collect_into_clause ,那么 execute_immediate_statement 永远不会执行。例如,此语句从不递增序列:

EXECUTE IMMEDIATE 'SELECT S.NEXTVAL FROM DUAL'

这基本上就是你在做什么。因为您没有选择过程的结果(或实际上是您的函数)变为变量,所以不执行查询,因此不会调用该函数。

由于表中有多行,因此无法选择标量变量,但可以批量收集到集合中;或者像在第三个例子中那样使用光标。 (虽然,如果使用相同的语句打开游标,你似乎每行调用两次函数 - 一次执行查询时,然后再次执行PL / SQL循环。我可能读得太多了进入你人为的例子......)

答案 1 :(得分:3)

答案很简单,但很复杂,许多初学PLSQL开发人员似乎无法掌握游标的整个概念......

SELECT my_stored_proc(...)
FROM my_table
SQL Developer中的

执行正常,因为SQL Developer会为您的查询打开一个游标,将游标提取到数据网格中,然后关闭游标。

stmt := 'SELECT my_stored_proc(...) FROM my_table';
EXECUTE IMMEDIATE stmt;
存储过程内部的

由于同样的原因而失败 - 它为动态SQL打开游标,但它没有任何PLSQL变量来获取游标的结果。如果你想要select某事,你需要

  • 为它打开游标,在循环中将数据提取到PLSQL变量中(并且对所获取的数据执行任何操作),然后关闭游标,
  • 或选择/批量选择查询结果为PLSQL变量(然后对获取的数据执行任何操作)。

...这是您在第三个代码段中所做的。