使用plsql在游标中绑定数组

Posted

技术标签:

【中文标题】使用plsql在游标中绑定数组【英文标题】:bind array in cursor using plsql 【发布时间】:2013-12-27 12:56:54 【问题描述】:
declare
  cursor lc is 
    select * 
      from (select a.lin, a.pr, 
                   b.name, sum(a.up) as u,
                   sum (a.d)         as d
              from li_dy_4 a,
                   p_list  b 
             where a.pr=b.id 
               and b.parent_id != 0 
               and a.partitionid <= 308 
               and a.partitionid >= 302 
               and a.pr in (91,80)
             GROUP BY a.pr, b.name, a.lin  
             order by d desc) ;
  rec lc%ROWTYPE;

BEGIN 
  open lc;
  loop 
    FETCH lc into rec;
    dbms_output.put_line(rec.pr);
    exit when lc%NOTFOUND;
  end loop;
  close lc;
END;

上面的语句对我来说很好。我无法找到任何有希望的东西是改变“in”语句之后的值,即a.pr in (91,80) 我在这里手动列出了这些值,但我想将它作为a.pr column 的数字数组传递给光标。简而言之,我想做a.pr = idlist idlist 是一个数组。请任何人告诉我我的想法是否可行。

【问题讨论】:

Declaration of multiple values in Oracle BIND Variables的可能重复 你能告诉你使用什么数据库,Oracle 10g 还是 11g ? 【参考方案1】:

只是想提醒您,IN 子句仅支持1000 items。这可能是主要原因,SELECT 查询没有所谓的 BULK BINDING。我们有FORALL INSERT/UPDATE,就像BULK BINDING。不幸的是 select 没有。

但您仍然可以以不同的方式实现您的要求。

您可以尝试global temporary table(GTT),其中带有“插入的数据范围”的临时表仅适用于该会话。

您可以FORALL INSERT IN 子句的所有数据到该表中,并将 TABLE 加入您的查询。

否则,您可以拥有 nested table(如果是 oracle 10g)或简单的 pl/sql 类型本身(如果是 oracle 11g),将所有 IN 类项作为记录并将其加入到您的查询中。

示例:使用 NESTED TABLE ,对较少数量(

CREATE TYPE pr AS OBJECT
           (pr  NUMBER);
/
CREATE TYPE prList AS TABLE OF pr;
/

declare
  myPrList prList := prList ();
  cursor lc is 
    select * 
      from (select a.lin, a.pr, 
                   b.name, sum(a.up) as u,
                   sum (a.d)         as d
              from li_dy_4 a,
                   p_list  b,
                   TABLE(CAST(myPrList as prList)) my_list
             where a.pr=b.id 
               and b.parent_id != 0 
               and a.partitionid <= 308 
               and a.partitionid >= 302 
               and a.pr = my_list.pr
             GROUP BY a.pr, b.name, a.lin  
             order by d desc) ;
  rec lc%ROWTYPE;

BEGIN 
  /*Populate the Nested Table, with whatever collection you have */
  myPrList := prList ( pr(91),
                       pr(80));
  /*
     Sample code: for populating from your TABLE OF NUMBER type 

     FOR I IN 1..your_input_array.COUNT
     LOOP
          myPrList.EXTEND;
          myPrList(I) := pr(your_input_array(I));
     END LOOP;
  */
  open lc;
  loop 
    FETCH lc into rec;
    exit when lc%NOTFOUND; -- Your Exit WHEN condition should be checked afte FETCH iyself!
    dbms_output.put_line(rec.pr);
  end loop;
  close lc;
END;
/

【讨论】:

,我正在使用 oracle11gR2。我已经尝试了您提供的解决方案,而且我的记录也比您提到的要少。但是,我得到了。 PL/SQL:ORA-00904:“MY_LIST”。“PR”:无效标识符 PLS-00341:游标“LC”的声明不完整或格式错误....我该怎么办 你创建了类型? prList 和 pr ,我在 PL/SQL Block 之前提到过? 它应该可以工作,我试过了,它可以工作。你能在你的问题本身更新一下你有什么吗? myPrList prList := prList (); .. 你添加了吗? 我使用上述示例代码的目的是创建一个过程并将变量和数组传递给该过程。通过传递参数从 php 执行该过程。【参考方案2】:

我不知道你的全局表的确切结构,但你可以像这样在光标中使用集合

declare
 cursor c1 is
  select last_name ls  from empc;
 type x is table of employees.last_name%type;
 x1 x := x();
 cnt integer :=0;
begin
 for z in c1 loop
  cnt := cnt +1;
  x1.extend;
  x1(cnt) := z.ls;
  if x1(cnt) is NULL then-----------
   DBMS_OUTPUT.PUT_LINE('ASHISH');
  end if;
  dbms_output.put_line(cnt || ' '|| x1(cnt));
 end loop;
end;

【讨论】:

以上是关于使用plsql在游标中绑定数组的主要内容,如果未能解决你的问题,请参考以下文章

PLSQL 在变量中存储具有未知数据类型的游标(使用 FETCH INTO)

PLSQL - 游标不能在动态 sql 中使用

在 Oracle PLSQL 中使用游标的动态列名

如何在 PLSQL 中释放游标?

在数组循环中使用游标

PLSQL游标笔记一