PLS-00436:实现限制:不能引用BULK In-BIND记录表的字段

时间:2012-02-15 19:33:39

标签: sql oracle plsql

当我调用'archive_things'程序时,我收到此错误,而该程序又在INSERT INTO deleted_part_things
(id, part_id, file_name, file_type, thing, editable)

处发出错误 这是什么意思?

 PROCEDURE archive_things ( p_part_id IN NUMBER ) 
 IS    
  thing_list  bean_list;
 BEGIN

 thing_list := get_thingss_info(p_part_id);

 insert_deleted_things(thing_list);

 END archive_things;



 FUNCTION get_things_info ( p_part_id IN NUMBER)
  RETURN bean_list
 IS
  attachment_list  bean_list;
 BEGIN

  SELECT file_thing_bean (id, hot_part_id, file_name, file_type, thing, editable)
  BULK COLLECT INTO thing_list
  FROM part_things
  WHERE part_id =hot_part_id;

  RETURN thing_list;

END get_things_info;



PROCEDURE insert_deleted_things(  p_bean_list IN bean_list ) 

IS BEGIN    

FORALL x IN INDICES OF p_bean_list       
    INSERT INTO deleted_part_things
        (id, part_id, file_name, file_type, thing, auditable)  <<<<<  ERROR HERE!!!!!     
         VALUES 
         (   p_bean_list(x).id, p_bean_list(x).parent_id,  p_bean_list(x).file_name,  p_bean_list(x).file_type,
              p_bean_list(x).thing,   p_bean_list(x).editable
        );             

     END insert_deleted_things;  

2 个答案:

答案 0 :(得分:3)

两点:

  1. 在您的last question中,您提到您正在运行Oracle 10g。正如Ollie在他的回答中指出的那样,你不能使用你在11g之前使用的方法。
  2. 为什么要创建两个过程和一个函数?这很容易就是一个程序。正如你调用的初始程序调用另外两个程序,你通过拆分并使其变得更加复杂而获得任何收益。
  3. PLS-00436是11G之前的限制,因此您无法引用rowtypeforall中的列。它有几种方法:

    其中一个,正如Ollie建议的那样,表格中的列数与bulk collect中的列数相同。这并不总是可行的。

    Tom Kyte建议设置操作。对此的限制是您正在进行的bulk collect的大小。如果它大于撤消量你将遇到问题。此外,如果您想对数据执行其他操作,则必须单独执行此操作。

    最后一个选项(我知道我确定还有更多选项)是根据以下内容将您的记录收集到单个types而不是rowtype。这样做的缺点是它可能不像汤姆的方法那么快,而且不像奥利那样明确。

    我刚刚注意到Sathya's method,它也可以运行,但需要执行大量的SQL。

    PROCEDURE archive_things ( p_part_id IN NUMBER ) IS
    
       CURSOR c_get_all ( Cpart_id char) is
          SELECT file_attachment_bean (id, hot_part_id, file_name
                             , file_type, attachment, auditable)
            FROM hot_part_attachments
           WHERE hot_part_id = Cpart_id;
    
       t_id bean_list.id%type;
       t_hot_part_id bean_list.hot_part_id%type;
       t_file_name bean_list.file_name%type;
       t_file_type bean_list.file_type%type;
       t_attachment bean_list.attachment%type;
       t_auditable bean_list.auditable%type;
    
    BEGIN
    
       OPEN c_get_all(p_part_id);
       FETCH c_get_all bulk collect into
         t_id, t_hot_part_id, t_file_name, t_file_type, t_attachment, t_auditable;
    
       LOOP
    
          EXIT WHEN t_id.count = 0;
    
          FORALL x IN t_id.first .. t_id.last       
             INSERT INTO deleted_hot_part_attachments (id, hot_part_id, file_name, file_type
                                                       , attachment, auditable)     
             VALUES ( t_id(x), t_hot_part_id(x), t_file_name(x), t_file_type(x)
                    , t_attachment(x), t_auditable(x) );
    
          COMMIT; -- You may want to do this outside the procedure.
    
       END LOOP;
    
       CLOSE c_get_all;
    
    END;
    

答案 1 :(得分:-2)

SET SERVEROUTPUT ON;

declare

    cursor c1 IS select 

c_code,c_name,c_language
from t_country;

TYPE c1_tab is table of t_country%rowtype; 

c1_insert c1_tab;
l_count number:=0;

begin

open c1;
    loop    
    fetch c1 
    bulk collect into c1_insert
    limit 10000;    

         forall i in 1 .. c1_insert.count
        insert into t_country values (c1_insert(i).cCode,c1_insert(i).cName,c1_insert(i).cLanguage);

        commit;
     exit when c1%notfounD;
     end loop;
 CLOSE C1;
end;