Oracle 11g:在过程中使用游标

Posted

技术标签:

【中文标题】Oracle 11g:在过程中使用游标【英文标题】:Oracle 11g: Using cursors inside a procedure 【发布时间】:2012-03-19 12:30:06 【问题描述】:

我试图从一个过程中返回两个引用游标并且遇到了一些麻烦。我要做的是从第一个光标中获取信息,从中选择一些字段并加入其他一些信息并将结果粘贴到表变量中......然后从该表中选择不同的项目到第二个光标。但我无法编译它。有人可以告诉我我做错了什么吗?

type T_CURSOR is REF CURSOR

procedure FetchSL3Details_PRC
(
c_items out T_CURSOR,
c_identifiers out T_CURSOR,
p_niin in char
) as
v_idents IDENTIFIER_TABLE_TYPE:= IDENTIFIER_TABLE_TYPE();
BEGIN

open c_items for
  select
    its.item_set_id,
    its.niin,
    its.parent_niin,
    its.commodity_id,
    its.service_type,
    its.sl3_type,
    its.qty,
    its.created_id,
    its.created_dt,
    its.modified_id,
    its.modified_dt
  from
    item_set its
  start with its.niin = p_niin
  connect by prior its.niin = its.parent_niin;

  for item in c_items loop
    v_idents.extend;
    v_idents(v_idents.LAST) := identifier_row_type(item.commodity_id,
                                                      get_group_name_fun(item.commodity_id),
                                                      0);
    v_idents.extend;
    v_idents(v_idents.LAST) := identifier_row_type(item.created_id,
                                                      get_formatted_name_fun(item.created_id),
                                                      0);
    v_idents.extend;
    v_idents(v_idents.LAST) := identifier_row_type(item.modified_id,
                                                      get_formatted_name_fun(item.modified_id),
                                                      0);
  end loop;

  open c_identifiers for
    select 
      distinct(v.id),
      v.name,
      v.type
    from
      v_idents v;

END FetchSL3Details_PRC;

【问题讨论】:

什么是 T_CURSOR?我一般使用 sys_refcursor 作为保持打开游标的变量类型。 T_CURSOR 是引用光标的 typedef... for 循环开头的错误是 (506,19) “C_ITEMS 不是过程或未定义”。我可以选择光标,但我不能为 for 循环重新打开它。它还抱怨 v_idents 表不存在... 【参考方案1】:

你不能使用这个结构:

for item in c_items loop

带有 REF CURSOR。它期望 c_items 是标准的 PL/SQL CURSOR。这是您遇到错误的直接原因。如果你想循环一个 REF CURSOR,据我所知,你需要使用显式的 FETCH 语句并自己处理循环条件。

此外,你所说的你正在尝试做的事情并不完全合理。如果您从过程主体内的c_items 游标中获取,将其返回给调用者也会令人困惑。在您的评论中,您使用了“选择进入光标”这一短语,这意味着您可能将光标视为可以反复迭代的静态集合。情况并非如此——游标代表内存中的活动查询。一旦从游标中取出一行,就不能再取出了。

由于我不了解代码的最终目标,因此我不确定该建议什么。如果您确实需要同时处理来自 c_items 的行并将其作为可用的 REF CURSOR 返回,那么唯一的选择可能是关闭并重新打开它。

【讨论】:

【参考方案2】:

改变这个:

open c_identifiers for
    select 
      distinct(v.id),
      v.name,
      v.type
    from
      v_idents v;

到:

open c_identifiers for
    select 
      distinct(v.id),
      v.name,
      v.type
    from
      TABLE(v_idents) v; -- Use TABLE

【讨论】:

谢谢,修复了临时表部分......仍然存在无法从循环的 c_items 游标中提取项目的问题,因此我什至可以填充该表。

以上是关于Oracle 11g:在过程中使用游标的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Oracle 11g 中使用游标在表中插入数据?

存储过程 oracle 11g 中的 TEMP 表

存储过程中的光标完成并卡住(Oracle Linux VM 上的 Oracle 11g)

如何从存储过程返回的游标将数据插入临时表

oracle过程中游标作为输入参数 求解。。。

『ORACLE』 PLSQL游标的使用(11g)