我想在我自己的存储过程中的表的每一行上调用存储过程。在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;
...
我的问题是为什么会发生这种情况。
答案 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
某事,你需要
...这是您在第三个代码段中所做的。