以后如何定义游标?

时间:2019-08-27 17:06:41

标签: oracle plsql cursor

Oracle Docs中,它提到了游标具有两个部分,即声明和定义。

  

您可以先声明它(使用cursor_declaration),然后然后在同一块中定义它,子程序或程序包(使用cursor_definition),或者同时声明并定义(使用cursor_definition) )。

我已经看过但未能找到一个代码示例,该示例显示了稍后如何定义光标。

我想声明三个游标,但仅在进行时定义它们。例如,游标1将删除游标2需要做的工作。我有来自不同系统的数据,可以用以下三种方法之一进行匹配。一旦匹配,就不需要再次匹配,因此其他匹配的游标就不需要在开始时就定义好了的那些值。

这是我期望的样子,但可能是错误的

DECLARE
    CURSOR X IS ...; --cursor declaration and definition
    CURSOR Y; --cursor declaration
    CURSOR Z; --cursor declaration
BEGIN
    FOR i IN X LOOP
        --DO STUFF
    END LOOP;
    Y IS ...; --cursor definition
    FOR ii IN Y LOOP
        --DO STUFF
    END LOOP;
    Z IS ...; --cursor definition
    FOR iii IN Z LOOP
        --DO STUFF
    END LOOP;
END;

有一些相关问题

  • answer并未在主体中定义光标,而是将其向上移动到了声明中。
  • question上有一条关于再次运行查询的评论,这不是重点

2 个答案:

答案 0 :(得分:3)

我必须承认,我从未考虑过或尝试过“推迟”单个块内光标的定义。但是,它们肯定会正确地通知您可以在程序包规范中定义游标声明,并将其“隐藏”在正文中。

这是一个例子:

CREATE PACKAGE species_pkg 
IS 
   CURSOR species_cur 
      RETURN endangered_species%ROWTYPE; 
END;
/

CREATE PACKAGE BODY species_pkg 
IS 
   CURSOR species_cur 
      RETURN endangered_species%ROWTYPE 
   IS 
        SELECT * 
          FROM endangered_species 
      ORDER BY common_name; 
END;
/

您可以使用我的LiveSQL script进行尝试。

但是我真的不认为这就是您想要实现解决方案的目的。相反,我会使用光标变量,如Mick Mnemonic在他的答案中向您展示的。

将游标声明从其定义中分离出来的主要好处是,您可以遵循神圣的“信息隐藏”原理。从理论上讲,开发人员不需要了解查询的实现,而只需了解返回的数据集的描述。

答案 1 :(得分:1)

听起来您想要REF CURSOR

DECLARE
    CURSOR X IS SELECT stuff FROM mytable; --cursor declaration and definition

    TYPE cursor_type IS REF CURSOR;
    cursor_y cursor_type; --cursor declaration
    cursor_z cursor_type; --cursor declaration

    query_string VARCHAR2(200) := 'SELECT stuff FROM anothertable WHERE id=:b1';
BEGIN
    FOR i IN X LOOP
        --DO STUFF
    END LOOP;

    OPEN cursor_y FOR query_string USING my_bind_variable1;
    --cursor definition using dynamic SQL and a bind variable

    FOR ii IN Y LOOP
        --DO STUFF
    END LOOP;

    OPEN cursor_z FOR SELECT stuff FROM anothertable2; --cursor definition

    FOR iii IN Z LOOP
        --DO STUFF
    END LOOP;
END;