1

I get this error when I call the procedure 'archive_things' which in turns gives the error at INSERT INTO deleted_part_things
(id, part_id, file_name, file_type, thing, editable)

what does this mean?

 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;  
Doc Holiday
  • 9,928
  • 32
  • 98
  • 151

2 Answers2

3

Two points:

  1. In your last question you mentioned that you're running Oracle 10g. As Ollie pointed out in his answer you can't use the method you're using until 11g.
  2. Why are you creating two procedures and a function? This could easily be one procedure. As the initial procedure you're calling calls the other two you gain nothing by splitting it and make it much more complicated.

PLS-00436 is a restriction prior to 11G whereby you're not able to reference columns in a rowtype in a forall. There are a few ways round it:

One, as Ollie suggested is to have the same number of columns in your table as in your bulk collect. This isn't always possible.

Tom Kyte suggests set operations. The restriction on this is the size of the bulk collect you're doing. If it's bigger than the amount of undo you're going to have problems. Also if you want to do something else with the data then you have to do that separately.

The last option ( that I know of I'm sure there are more ) is to collect your records into individual types rather than a rowtype as per the following. The downside of this is that it may not be as quick as Tom's method and it's by no mean as clear as Ollie's.

I've just noted Sathya's method, which would also work but requires a lot of SQL to be executed.

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;
Community
  • 1
  • 1
Ben
  • 51,770
  • 36
  • 127
  • 149
-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;
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574