如何在PL/SQL过程体内创建游标

5

我希望能够在过程体内动态创建光标,同时使用for循环代替下面的代码。我已经实现了动态光标,但无法使用for循环。

PROCEDURE myprocedure
AS
  LV_TEST_CUR SYS_REFCURSOR;
  LV_QUERY VARCHAR2(200);
  LV_DATE  DATE;
BEGIN
  LV_QUERY:='select sysdate as mydate from dual';
  OPEN LV_TEST_CUR FOR LV_QUERY;
  /*FOR CUR_VAR IN LV_TEST_CUR
  LOOP
  dbms_output.put_line(CUR_VAR.mydate);
  end LOOP;
  */
  LOOP
    FETCH LV_TEST_CUR INTO LV_DATE;
    EXIT
  WHEN LV_TEST_CUR%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(LV_DATE);
  END LOOP;
  CLOSE LV_TEST_CUR;
END myprocedure;

如果我使用已注释的代码(for循环),会出现错误

PLS-00221: 不是过程或未定义。

在动态游标中可以使用for循环吗?

3个回答

6

在游标FOR循环中,您不能引用游标变量

但是您可以直接使用SELECT语句:

create or replace PROCEDURE myprocedure
AS
  LV_TEST_CUR SYS_REFCURSOR;
  LV_QUERY VARCHAR2(200);
  LV_DATE  DATE;
BEGIN
  FOR CUR_VAR IN (select sysdate as mydate from dual)
  LOOP
  dbms_output.put_line(CUR_VAR.mydate);
  end LOOP;

END myprocedure;
/

我认为这是关于该过程的一个很好的替代方案。它将简化我的代码。 - satheesh
如果我需要在循环内创建多个光标怎么办? - Deckard

1

您不能在动态SQL中使用FOR <row> IN <cursor> LOOP语法;请参见文档中的示例,该示例显示了当该代码被注释时您正在使用的方法。

您的示例根本不需要是动态的,但我假设您只是为了这个问题而简化了它。如果它有一个占位符,那么就没有地方设置它的值。如果您有:

LV_QUERY:='select sysdate - :days as mydate from dual';
FOR CUR_VAR IN LV_TEST_CUR LOOP
    dbms_output.put_line(CUR_VAR.mydate);
END LOOP;

如果使用 FOR ... IN ... 版本,就没有地方可以将值分配给 days 占位符。您必须使用动态的 OPEN 来完成这个操作:

LV_QUERY:='select sysdate - :days as mydate from dual';
-- pass '1' as the bind variable
OPEN LV_TEST_CUR FOR LV_QUERY USING 1;
LOOP
    FETCH LV_TEST_CUR INTO LV_DATE;
    EXIT WHEN LV_TEST_CUR%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(LV_DATE);
END LOOP;
CLOSE LV_TEST_CUR;

当然,您可能不需要占位符,而是动态构建查询字符串,但限制仍然适用。


是的,你说得对,我为了问题简化了代码。我明白在这种情况下我们不能使用for循环。 - satheesh

0
据我所知,您无法使用FOR循环与游标变量或“ref cursor”一起使用。 FOR循环仅用于硬编码的SQL语句或游标。
请参阅有关游标变量限制此处的部分,其中明确指出“您无法在游标FOR循环中引用游标变量”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接