0

我有以下片段(简化以排除无关的细节):

<<cursor_loop>> 
LOOP 
  fetch c1 into somerecord;
  EXECUTE IMMEDIATE 'begin EXIT cursor_loop WHEN 1 = 1; end;';
END LOOP cursor_loop;

当我运行它时,它失败并出现PLS-00201: identifier 'CURSOR_LOOP' must be declared错误。

如果我将循环标签留在立即执行之外,我会得到PLS-00376: illegal EXIT/CONTINUE statement; it must appear inside a loop.

显然后者是错误的,但尚不清楚为什么前者是错误的。

可以从立即执行中的语句中退出此循环吗?

4

3 回答 3

4

cursor_loop正如其他人已经说过的那样,由于范围的原因,您不能直接在动态 SQL 中引用。如果您坚持使用这种模式,那么您可以使用绑定变量标志将状态信息从动态代码传递回静态代码;就像是:

DECLARE
  break_loop pls_integer;
...
  break_loop := 0;
  <<cursor_loop>> 
  LOOP 
    fetch c1 into somerecord;
    EXECUTE IMMEDIATE 'begin if 1 = 1 then :break_loop := 1; end if; end;'
      USING OUT break_loop;
    EXIT cursor_loop WHEN break_loop = 1;
  END LOOP cursor_loop;
...

稍微更完整一些,但显然仍然非常做作,例如:

DECLARE
  break_loop pls_integer;
  somevar number;
  c1 sys_refcursor;
BEGIN
  OPEN c1 FOR
    select 1 from dual
    union all select 2 from dual
    union all select 3 from dual;

  break_loop := 0;
  dbms_output.put_line('before loop, break_loop is ' || break_loop);
  <<cursor_loop>> 
  LOOP 
    fetch c1 into somevar;
    exit when c1%notfound;
    dbms_output.put_line('got ' || somevar);
    EXECUTE IMMEDIATE 'begin if :somevar = 2 then :break_loop := 1; end if; end;'
      USING somevar, OUT break_loop;
    EXIT cursor_loop WHEN break_loop = 1;
  END LOOP cursor_loop;
  dbms_output.put_line('after loop, break_loop is ' || break_loop);
END;
/

PL/SQL procedure successfully completed.

before loop, break_loop is 0
got 1
got 2
after loop, break_loop is 1

由于动态检查,在获取值“3”之前退出循环。

于 2015-07-30T18:32:29.797 回答
3

不,你不能。

动态 SQL 语句在单独的范围内运行——它不能引用调用块中定义的变量或操作它们的值(当然,除非您的动态语句具有绑定变量,允许您使用USINGINTO子句EXECUTE IMMEDIATE传入和返回值)。同样,它不能引用循环名称,因为执行动态语句时该名称不在范围内。

在这种情况下,不清楚为什么要首先使用EXECUTE IMMEDIATE而不是将其编码EXIT为循环的正常部分。

于 2015-07-30T17:13:55.797 回答
2

我想不是。EXECUTE IMMEDIATE 用于运行 SQL 语句,而不是任何块。从文档:


EXECUTE IMMEDIATE 语句在单个操作中构建并执行动态 SQL语句。它是原生动态 SQL 处理大多数动态 SQL 语句的方法。

https://docs.oracle.com/cd/B28359_01/appdev.111/b28370/executeimmediate_statement.htm

于 2015-07-30T17:10:02.677 回答