Oracle PL/SQL 将游标(来自函数)中的每个值一一分配给另一个游标

Posted

技术标签:

【中文标题】Oracle PL/SQL 将游标(来自函数)中的每个值一一分配给另一个游标【英文标题】:Oracle PL/SQL Assign each value from a cursor(from function) to another cursor one by one 【发布时间】:2017-09-05 17:31:00 【问题描述】:

我有一个名为 GET_CLIENT_IN_SED(return sys_refcursor) 的函数,它给了我一个 id 编号列表(单列)。现在,在一个过程中,我试图循环遍历每个(一个接一个)这些值并将其用于调用第二个过程(它需要一个客户端 id 参数)。

PROCEDURE GET_ORDINARY_CLIENT;

PROCEDURE GET_ORDINARY_CLIENT_BY_SED
  ( sed_in IN varchar2, client_sed OUT SYS_REFCURSOR )
IS
   ordinary_clients sys_refcursor;

BEGIN
  ordinary_clients := GET_CLIENT_IN_SED(sed_in);
  for item in ordinary_clients loop
    client_sed := client_sed + ordinary_clients(i);
  end loop;
END;

【问题讨论】:

【参考方案1】:

据我所知,您需要执行以下操作:

功能:

此函数将输入作为数字并返回一个引用。与您的要求类似。

CREATE OR REPLACE FUNCTION get_num_sysrefcur (num IN NUMBER)
   RETURN SYS_REFCURSOR
AS
   my_cursor   SYS_REFCURSOR;
BEGIN
   --
   OPEN my_cursor FOR
      WITH ntable
           AS (SELECT 1 ID, 111 AGT, 'ABC' DESCRIP FROM DUAL
               UNION ALL
               SELECT 2 ID, 222 AGT, 'ABC' DESCRIP FROM DUAL
               UNION ALL
               SELECT 1 ID, 333 AGT, 'ABC' DESCRIP FROM DUAL)

         SELECT AGT FROM ntable WHERE ID = num;


   RETURN my_cursor;
END;
/

阻止(在您的情况下是程序) -- 这个匿名块将遍历从 sys_refcursor 返回的记录。类似于您希望第二个过程在哪里使用 sys_refcursor 的值并循环它(您可以创建过程来代替这个匿名块)。

DECLARE
   a   NUMBER := 1;

   TYPE ta IS TABLE OF NUMBER
      INDEX BY PLS_INTEGER;
   b   ta;
   x   SYS_REFCURSOR;
BEGIN
   x := get_num_sysrefcur (a);

  fetch x bulk collect into b;

  for i in 1..b.count
  loop
   -- Displaying the result of the ref_cursor.
   DBMS_OUTPUT.put_line (b(i));
  end loop;
END;

【讨论】:

批量收集是我喜欢使用的另一种有效方法(我发现使用集合比使用光标简单得多!)。虽然当数据量很大时最好不要使用,因为它存储在变量而不是迭代器中。 @Dessma 您也可以使用批量收集进行迭代。您有限制子句来限制 1 go 中的数据选择,您可以遍历所有记录【参考方案2】:

遍历引用游标不像遍历数组或表,这解释了为什么您的 FOR...LOOP 不起作用。

简而言之,ref_cursor 更像是集合上的“指针”或“迭代器”,而不是集合。在另一个问题中,您将找到一个使用 FETCH 迭代 ref_cursor 的非常清晰的示例。

How to use record to loop a ref cursor?

您的数据示例如下所示:

PROCEDURE GET_ORDINARY_CLIENT_BY_SED(sed_in     IN VARCHAR2,
                                     client_sed OUT SYS_REFCURSOR) IS
   ordinary_clients SYS_REFCURSOR;
   clt              NUMBER; -- assuming your cursor contains strictly numbers
BEGIN
   ordinary_clients := GET_CLIENT_IN_SED(sed_in);
   LOOP
      FETCH ordinary_clients
         INTO clt;
      EXIT WHEN ordinary_clients%NOTFOUND;
      dbms_output.put_line(clt);
      -- do some other things here with your number
   END LOOP;
END;

【讨论】:

我不想从表中加载,我想从 sys_refcursor 返回函数中加载,因为我没有存储在任何表中的值,只是有关如何获取值的说明。所以我不能使用 table_name%ROWTYPE 抱歉,我假设您的 ordinary_client 游标包含“复杂”类型,例如表格行。如果您的 refcursor 只包含简单的数据,例如数字,您可以 FETCH 到适当类型的简单变量中,并以相同的逻辑使用它们。我将使用其他信息编辑我的答案。

以上是关于Oracle PL/SQL 将游标(来自函数)中的每个值一一分配给另一个游标的主要内容,如果未能解决你的问题,请参考以下文章

Oracle --- 存储过程函数包游标触发器

Oracle --- 存储过程函数包游标触发器

PL/SQL 编程游标存储过程函数

如何传递从多个表创建的 PL/SQL 游标记录?

oracle PL/SQL 中的游标

触发器中的 Oracle PL/SQL 游标