【问题标题】:Executing a stored procedure inside another stored procedure using Select Query使用 Select Query 在另一个存储过程中执行存储过程
【发布时间】:2016-12-13 00:11:20
【问题描述】:

我想在我自己的存储过程中对表的每一行调用一个存储过程。在 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;
...

我的问题是为什么会这样。

【问题讨论】:

    标签: sql stored-procedures plsql oracle-sqldeveloper


    【解决方案1】:

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

    你的

    SELECT my_stored_proc(...)
    FROM my_table
    

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

    你的

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

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

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

    ...这就是您在第三个代码 sn-p 中所做的。

    【讨论】:

      【解决方案2】:

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

      如果 dynamic_sql_statement 是一个 SELECT 语句,并且您省略了 into_clausebulk_collect_into_clause,那么 execute_immediate_statement 永远不会执行.例如,此语句从不增加序列:

      EXECUTE IMMEDIATE 'SELECT S.NEXTVAL FROM DUAL'
      

      这基本上就是您正在做的事情。因为你没有选择你的过程的结果(或者,实际上是你的函数)进入一个变量,所以查询没有被执行,所以函数没有被调用。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-15
        • 2013-03-26
        • 2020-12-10
        • 2013-10-12
        • 1970-01-01
        • 2017-02-14
        • 1970-01-01
        • 2010-09-15
        相关资源
        最近更新 更多