"table of" collection into cursor

Let say i have a collection-variable called "emps":
TYPE emp_table IS TABLE OF employee%ROWTYPE;
emps emp_table;Now i'm inserting data into it. And then i want to put all data from "emps" to variable
"o_annuity_payments out SYS_REFCURSOR"
soemthing like this:
open o_annuity_payments for
bulk collect from emps;
how should i do?

CharlesRoos wrote:
Maybe such syntacts is allowed:
1. declare cursor type variable.Yes.
2. insert a row into cursor type variableNo.
Re: "table of" collection into cursor
A cursor is a pointer to a compiled SQL statement
http://download.oracle.com/docs/cd/E11882_01/server.112/e10713/sqllangu.htm#CHDFCAGA
When an application issues a SQL statement, the application makes a parse call to the database to prepare the statement for execution. The parse call opens or creates a cursor, which is a handle for the session-specific private SQL area that holds a parsed SQL statement and other processing information. It is not a result set.
You cannot insert a row into a cursor because you cannot insert a row into a compiled SQL statement.
maybe if you explain what you are trying to do more help can be given.

Similar Messages

  • Need to increase performance-bulk collect in cursor with limit and in the for loop inserting into the trigger table

    Hi all,
    I have a performance issue in the below code,where i am trying to insert the data from table_stg into target_tab and in parent_tab tables and then to child tables via cursor with bulk collect .the target_tab and parent_tab are huge tables and have a row wise trigger enabled on it .the trigger is mandatory . This timetaken for this block to execute is 5000 seconds.Now my requirement is to reduce it to 5 to 10 mins.
    can someone please guide me here.Its bit urgent .Awaiting for your response.
    declare
    vmax_Value NUMBER(5);
      vcnt number(10);
      id_val number(20);
      pc_id number(15);
      vtable_nm VARCHAR2(100);
      vstep_no  VARCHAR2(10);
      vsql_code VARCHAR2(10);
      vsql_errm varchar2(200);
      vtarget_starttime timestamp;
      limit_in number :=10000;
      idx           number(10);
              cursor stg_cursor is
             select
                   DESCRIPTION,
                   SORT_CODE,
                   ACCOUNT_NUMBER,
                     to_number(to_char(CORRESPONDENCE_DATE,'DD')) crr_day,
                     to_char(CORRESPONDENCE_DATE,'MONTH') crr_month,
                     to_number(substr(to_char(CORRESPONDENCE_DATE,'DD-MON-YYYY'),8,4)) crr_year,
                   PARTY_ID,
                   GUID,
                   PAPERLESS_REF_IND,
                   PRODUCT_TYPE,
                   PRODUCT_BRAND,
                   PRODUCT_HELD_ID,
                   NOTIFICATION_PREF,
                   UNREAD_CORRES_PERIOD,
                   EMAIL_ID,
                   MOBILE_NUMBER,
                   TITLE,
                   SURNAME,
                   POSTCODE,
                   EVENT_TYPE,
                   PRIORITY_IND,
                   SUBJECT,
                   EXT_PRD_ID_TX,
                   EXT_PRD_HLD_ID_TX,
                   EXT_SYS_ID,
                   EXT_PTY_ID_TX,
                   ACCOUNT_TYPE_CD,
                   COM_PFR_TYP_TX,
                   COM_PFR_OPT_TX,
                   COM_PFR_RSN_CD
             from  table_stg;
    type rec_type is table of stg_rec_type index by pls_integer;
    v_rt_all_cols rec_type;
    BEGIN
      vstep_no   := '0';
      vmax_value := 0;
      vtarget_starttime := systimestamp;
      id_val    := 0;
      pc_id     := 0;
      success_flag := 0;
              vstep_no  := '1';
              vtable_nm := 'before cursor';
        OPEN stg_cursor;
              vstep_no  := '2';
              vtable_nm := 'After cursor';
       LOOP
              vstep_no  := '3';
              vtable_nm := 'before fetch';
    --loop
        FETCH stg_cursor BULK COLLECT INTO v_rt_all_cols LIMIT limit_in;
                  vstep_no  := '4';
                  vtable_nm := 'after fetch';
    --EXIT WHEN v_rt_all_cols.COUNT = 0;
        EXIT WHEN stg_cursor%NOTFOUND;
    FOR i IN 1 .. v_rt_all_cols.COUNT
      LOOP
       dbms_output.put_line(upper(v_rt_all_cols(i).event_type));
        if (upper(v_rt_all_cols(i).event_type) = upper('System_enforced')) then
                  vstep_no  := '4.1';
                  vtable_nm := 'before seq sel';
              select PC_SEQ.nextval into pc_id from dual;
                  vstep_no  := '4.2';
                  vtable_nm := 'before insert corres';
              INSERT INTO target1_tab
                           (ID,
                            PARTY_ID,
                            PRODUCT_BRAND,
                            SORT_CODE,
                            ACCOUNT_NUMBER,
                            EXT_PRD_ID_TX,         
                            EXT_PRD_HLD_ID_TX,
                            EXT_SYS_ID,
                            EXT_PTY_ID_TX,
                            ACCOUNT_TYPE_CD,
                            COM_PFR_TYP_TX,
                            COM_PFR_OPT_TX,
                            COM_PFR_RSN_CD,
                            status)
             VALUES
                            (pc_id,
                             v_rt_all_cols(i).party_id,
                             decode(v_rt_all_cols(i).product_brand,'LTB',2,'HLX',1,'HAL',1,'BOS',3,'VER',4,0),
                             v_rt_all_cols(i).sort_code,
                             'XXXX'||substr(trim(v_rt_all_cols(i).ACCOUNT_NUMBER),length(trim(v_rt_all_cols(i).ACCOUNT_NUMBER))-3,4),
                             v_rt_all_cols(i).EXT_PRD_ID_TX,
                             v_rt_all_cols(i).EXT_PRD_HLD_ID_TX,
                             v_rt_all_cols(i).EXT_SYS_ID,
                             v_rt_all_cols(i).EXT_PTY_ID_TX,
                             v_rt_all_cols(i).ACCOUNT_TYPE_CD,
                             v_rt_all_cols(i).COM_PFR_TYP_TX,
                             v_rt_all_cols(i).COM_PFR_OPT_TX,
                             v_rt_all_cols(i).COM_PFR_RSN_CD,
                             NULL);
                  vstep_no  := '4.3';
                  vtable_nm := 'after insert corres';
        else
              select COM_SEQ.nextval into id_val from dual;
                  vstep_no  := '6';
                  vtable_nm := 'before insertcomm';
          if (upper(v_rt_all_cols(i).event_type) = upper('REMINDER')) then
                vstep_no  := '6.01';
                  vtable_nm := 'after if insertcomm';
              insert into parent_tab
                 (ID ,
                 CTEM_CODE,
                 CHA_CODE,            
                 CT_CODE,                           
                 CONTACT_POINT_ID,             
                 SOURCE,
                 RECEIVED_DATE,                             
                 SEND_DATE,
                 RETRY_COUNT)
              values
                 (id_val,
                  lower(v_rt_all_cols(i).event_type), 
                  decode(v_rt_all_cols(i).product_brand,'LTB',2,'HLX',1,'HAL',1,'BOS',3,'VER',4,0),
                  'Email',
                  v_rt_all_cols(i).email_id,
                  'IADAREMINDER',
                  systimestamp,
                  systimestamp,
                  0);  
         else
                vstep_no  := '6.02';
                  vtable_nm := 'after else insertcomm';
              insert into parent_tab
                 (ID ,
                 CTEM_CODE,
                 CHA_CODE,            
                 CT_CODE,                           
                 CONTACT_POINT_ID,             
                 SOURCE,
                 RECEIVED_DATE,                             
                 SEND_DATE,
                 RETRY_COUNT)
              values
                 (id_val,
                  lower(v_rt_all_cols(i).event_type), 
                  decode(v_rt_all_cols(i).product_brand,'LTB',2,'HLX',1,'HAL',1,'BOS',3,'VER',4,0),
                  'Email',
                  v_rt_all_cols(i).email_id,
                  'CORRESPONDENCE',
                  systimestamp,
                  systimestamp,
                  0); 
            END if; 
                  vstep_no  := '6.11';
                  vtable_nm := 'before chop';
             if (v_rt_all_cols(i).ACCOUNT_NUMBER is not null) then 
                      v_rt_all_cols(i).ACCOUNT_NUMBER := 'XXXX'||substr(trim(v_rt_all_cols(i).ACCOUNT_NUMBER),length(trim(v_rt_all_cols(i).ACCOUNT_NUMBER))-3,4);
              insert into child_tab
                 (COM_ID,                                            
                 KEY,                                                                                                                                            
                 VALUE)
              values
                (id_val,
                 'IB.Correspondence.AccountNumberMasked',
                 v_rt_all_cols(i).ACCOUNT_NUMBER);
             end if;
                  vstep_no  := '6.1';
                  vtable_nm := 'before stateday';
             if (v_rt_all_cols(i).crr_day is not null) then 
              insert into child_tab
                 (COM_ID,                                            
                 KEY,                                                                                                                                            
                 VALUE)
              values
                (id_val,
                 --'IB.Correspondence.Date.Day',
                 'IB.Crsp.Date.Day',
                 v_rt_all_cols(i).crr_day);
             end if;
                  vstep_no  := '6.2';
                  vtable_nm := 'before statemth';
             if (v_rt_all_cols(i).crr_month is not null) then 
              insert into child_tab
                 (COM_ID,                                            
                 KEY,                                                                                                                                            
                 VALUE)
              values
                (id_val,
                 --'IB.Correspondence.Date.Month',
                 'IB.Crsp.Date.Month',
                 v_rt_all_cols(i).crr_month);
             end if;
                  vstep_no  := '6.3';
                  vtable_nm := 'before stateyear';
             if (v_rt_all_cols(i).crr_year is not null) then 
              insert into child_tab
                 (COM_ID,                                            
                 KEY,                                                                                                                                            
                 VALUE)
              values
                (id_val,
                 --'IB.Correspondence.Date.Year',
                 'IB.Crsp.Date.Year',
                 v_rt_all_cols(i).crr_year);
             end if;
                  vstep_no  := '7';
                  vtable_nm := 'before type';
               if (v_rt_all_cols(i).product_type is not null) then
                  insert into child_tab
                     (COM_ID,                                            
                     KEY,                                                                                                                                        
                     VALUE)
                  values
                    (id_val,
                     'IB.Product.ProductName',
                   v_rt_all_cols(i).product_type);
                end if;
                  vstep_no  := '9';
                  vtable_nm := 'before title';         
              if (trim(v_rt_all_cols(i).title) is not null) then
              insert into child_tab
                 (COM_ID,                                            
                 KEY,                                                                                                                                            
                 VALUE )
              values
                (id_val,
                 'IB.Customer.Title',
                 trim(v_rt_all_cols(i).title));
              end if;
                  vstep_no  := '10';
                  vtable_nm := 'before surname';
              if (v_rt_all_cols(i).surname is not null) then
                insert into child_tab
                   (COM_ID,                                            
                   KEY,                                                                                                                                          
                   VALUE)
                values
                  (id_val,
                  'IB.Customer.LastName',
                  v_rt_all_cols(i).surname);
              end if;
                            vstep_no  := '12';
                            vtable_nm := 'before postcd';
              if (trim(v_rt_all_cols(i).POSTCODE) is not null) then
              insert into child_tab
                 (COM_ID,                                            
                 KEY,                                                                                                                                            
                 VALUE)                              
               values
                (id_val,
                 'IB.Customer.Addr.PostCodeMasked',
                  substr(replace(v_rt_all_cols(i).POSTCODE,' ',''),length(replace(v_rt_all_cols(i).POSTCODE,' ',''))-2,3));
              end if;
                            vstep_no  := '13';
                            vtable_nm := 'before subject';
              if (trim(v_rt_all_cols(i).SUBJECT) is not null) then
              insert into child_tab
                 (COM_ID,                                            
                 KEY,                                                                                                                                            
                 VALUE)                              
               values
                (id_val,
                 'IB.Correspondence.Subject',
                  v_rt_all_cols(i).subject);
              end if;
                            vstep_no  := '14';
                            vtable_nm := 'before inactivity';
              if (trim(v_rt_all_cols(i).UNREAD_CORRES_PERIOD) is null or
                  trim(v_rt_all_cols(i).UNREAD_CORRES_PERIOD) = '3' or
                  trim(v_rt_all_cols(i).UNREAD_CORRES_PERIOD) = '6' or
                  trim(v_rt_all_cols(i).UNREAD_CORRES_PERIOD) = '9') then
              insert into child_tab
                 (COM_ID,                                            
                 KEY,                                                                                                                                            
                 VALUE)                              
               values
                (id_val,
                 'IB.Correspondence.Inactivity',
                  v_rt_all_cols(i).UNREAD_CORRES_PERIOD);
              end if;
                          vstep_no  := '14.1';
                          vtable_nm := 'after notfound';
        end if;
                          vstep_no  := '15';
                          vtable_nm := 'after notfound';
        END LOOP;
        end loop;
                          vstep_no  := '16';
                          vtable_nm := 'before closecur';
        CLOSE stg_cursor;
                          vstep_no  := '17';
                          vtable_nm := 'before commit';
        DELETE FROM table_stg;
      COMMIT;
                          vstep_no  := '18';
                          vtable_nm := 'after commit';
    EXCEPTION
    WHEN OTHERS THEN
      ROLLBACK;
      success_flag := 1;
      vsql_code := SQLCODE;
      vsql_errm := SUBSTR(sqlerrm,1,200);
      error_logging_pkg.inserterrorlog('samp',vsql_code,vsql_errm, vtable_nm,vstep_no);
      RAISE_APPLICATION_ERROR (-20011, 'samp '||vstep_no||' SQLERRM:'||SQLERRM);
    end;
    Thanks

    Its bit urgent
    NO - it is NOT urgent. Not to us.
    If you have an urgent problem you need to hire a consultant.
    I have a performance issue in the below code,
    Maybe you do and maybe you don't. How are we to really know? You haven't posted ANYTHING indicating that a performance issue exists. Please read the FAQ for how to post a tuning request and the info you need to provide. First and foremost you have to post SOMETHING that actually shows that a performance issue exists. Troubleshooting requires FACTS not just a subjective opinion.
    where i am trying to insert the data from table_stg into target_tab and in parent_tab tables and then to child tables via cursor with bulk collect .the target_tab and parent_tab are huge tables and have a row wise trigger enabled on it .the trigger is mandatory . This timetaken for this block to execute is 5000 seconds.Now my requirement is to reduce it to 5 to 10 mins.
    Personally I think 5000 seconds (about 1 hr 20 minutes) is very fast for processing 800 trillion rows of data into parent and child tables. Why do you think that is slow?
    Your code has several major flaws that need to be corrected before you can even determine what, if anything, needs to be tuned.
    This code has the EXIT statement at the beginning of the loop instead of at the end
        FETCH stg_cursor BULK COLLECT INTO v_rt_all_cols LIMIT limit_in;
                  vstep_no  := '4';
                  vtable_nm := 'after fetch';
    --EXIT WHEN v_rt_all_cols.COUNT = 0;
        EXIT WHEN stg_cursor%NOTFOUND;
    The correct place for the %NOTFOUND test when using BULK COLLECT is at the END of the loop; that is, the last statement in the loop.
    You can use a COUNT test at the start of the loop but ironically you have commented it out and have now done it wrong. Either move the NOTFOUND test to the end of the loop or remove it and uncomment the COUNT test.
    WHEN OTHERS THEN
      ROLLBACK;
    That basically says you don't even care what problem occurs or whether the problem is for a single record of your 10,000 in the collection. You pretty much just throw away any stack trace and substitute your own message.
    Your code also has NO exception handling for any of the individual steps or blocks of code.
    The code you posted also begs the question of why you are using NAME=VALUE pairs for child data rows? Why aren't you using a standard relational table for this data?
    As others have noted you are using slow-by-slow (row by row processing). Let's assume that PL/SQL, the bulk collect and row-by-row is actually necessary.
    Then you should be constructing the parent and child records into collections and then inserting them in BULK using FORALL.
    1. Create a collection for the new parent rows
    2. Create a collection for the new child rows
    3. For each set of LIMIT source row data
      a. empty the parent and child collections
      b. populate those collections with new parent/child data
      c. bulk insert the parent collection into the parent table
      d. bulk insert the child collection into the child table
    And unless you really want to either load EVERYTHING or abandon everything you should use bulk exception handling so that the clean data gets processed and only the dirty data gets rejected.

  • Selecting the contents of a table(collection) into a strong REF Cursor

    I'm trying to roll some data into a table collection and return it as a strong named cursor.
    I have not been able to do this successfully yet.
    I have tried casting the table and I couldn't get that to work either.
    I have included the whole procedure but here is the line I am getting errors on:
    SELECT * bulk collect into o_response_data_cur from table (response_data_tbl);
    Any help on this would be great.
    P.S. - As this is being picked up by BizTalk I can't return a table.
    Thanks,
    Todd M
    PROCEDURE create_customer (
    i_interface_hdr IN BizTalk_TestCustomer.interface_hdr_rec,
    i_customer_rec IN BizTalk_TestCustomer.customer_rec,
    i_address_cur IN BizTalk_TestCustomer.CUR_Addresses,
    i_contact_cur IN BizTalk_TestCustomer.CUR_Contact,
    o_interface_status OUT varchar2,
    o_response_data_cur OUT BizTalk_TestCustomer.CUR_CreateCustResponse)
    IS
    l_response_rec create_cust_response_rec;
    response_data_tbl create_cust_response_tbl;
    BEGIN
    FOR i IN 1 .. 10
    LOOP
    l_response_rec.ERROR_TYPE := 'Pre-Validation Error';
    l_response_rec.ERROR_CODE := 'DUMMY-' || i;
    l_response_rec.error_message := 'Test Error Message-' || i;
    response_data_tbl (i) := l_response_rec;
    END LOOP;
    SELECT * bulk collect into o_response_data_cur from table (response_data_tbl);
    o_interface_status := 'FAILURE';
    END create_customer;
    END BizTalk_TestCustomer;
    Here is the important Spec info:
    TYPE create_cust_response_rec
    IS
    RECORD (
    orig_system_party_ref varchar2 (240),
    orig_system_cust_acct_ref varchar2 (240),
    orig_system_site_ref varchar2 (240),
    oracle_party_id number,
    oracle_customer_id number,
    oracle_site_id number,
    ERROR_TYPE strar_cust_intf_err.ERROR_TYPE%TYPE,
    ERROR_CODE strar_cust_intf_err.ERROR_CODE%TYPE,
    error_message strar_cust_intf_err.error_message%TYPE
    TYPE CUR_Addresses IS REF CURSOR RETURN BizTalk_TestCustomer.address_rec;
    TYPE CUR_Contact IS REF CURSOR RETURN BizTalk_TestCustomer.contact_rec;
    TYPE CUR_CreateCustResponse IS REF CURSOR RETURN BizTalk_TestCustomer.create_cust_response_rec;
    TYPE create_cust_response_tbl
    IS
    TABLE OF create_cust_response_rec
    INDEX BY binary_integer;

    I think this is one of the most complicated one to develop and execute perfectly. ;)
    Here is one such case ->
    satyaki>
    satyaki>select * from v$version;
    BANNER
    Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Prod
    PL/SQL Release 10.2.0.3.0 - Production
    CORE    10.2.0.3.0      Production
    TNS for 32-bit Windows: Version 10.2.0.3.0 - Production
    NLSRTL Version 10.2.0.3.0 - Production
    Elapsed: 00:00:00.55
    satyaki>
    satyaki>
    satyaki>create or replace type d_obj as object
      2    (
      3      buff    varchar2(310)
      4    );
      5  /
    Type created.
    Elapsed: 00:00:00.05
    satyaki>
    satyaki>
    satyaki>create or replace type d_rec as table of d_obj;
      2  /
    Type created.
    Elapsed: 00:00:01.14
    satyaki>
    satyaki>
    satyaki>
    satyaki>
    satyaki>create or replace function pipe_buff(e_sal in number)
      2  return d_rec
      3  pipelined
      4  is
      5    cursor c1
      6    is
      7      select d_obj(
      8                    ename||' Joined On '||to_char(hiredate,'DD-MON-YYYY hh24:mi:ss')
      9                  ) str
    10      from emp
    11      where sal > e_sal;
    12     
    13   r1 c1%rowtype;
    14  begin
    15    for r1 in c1
    16    loop
    17      pipe row(r1.str);
    18    end loop;
    19    return;
    20  end;
    21  /
    Function created.
    Elapsed: 00:00:01.69
    satyaki>
    satyaki>
    satyaki>
    satyaki>create or replace procedure gen_cur_pipe(
      2                                            s_sal in number,
      3                                            rc in out sys_refcursor
      4                                          )
      5  is  
      6    str1  varchar2(500);
      7  begin  
      8    str1 := 'select *           
      9             from table(cast(pipe_buff('||s_sal||') as d_rec))';           
    10  
    11   open rc for str1;  
    12  exception  
    13    when others then    
    14      dbms_output.put_line(sqlerrm);
    15  end;
    16  /
    Procedure created.
    Elapsed: 00:00:00.05
    satyaki>
    satyaki>
    satyaki>
    satyaki>create table test_dual
      2    (
      3      dummy    varchar2(310)
      4    );
    Table created.
    Elapsed: 00:00:00.10
    satyaki>
    satyaki>
    satyaki>
    satyaki>declare   
      2    rec_x test_dual%rowtype;   
      3    w sys_refcursor;
      4  begin  
      5    dbms_output.enable(1000000);  
      6    gen_cur_pipe(&num,w);  
      7    loop    
      8      fetch w into rec_x;     
      9       exit when w%notfound;             
    10         dbms_output.put_line('Employee Special Deatils: '||rec_x.dummy);
    11    end loop;  
    12    close w;
    13  exception  
    14    when others then    
    15      dbms_output.put_line(sqlerrm);
    16  end;
    17  /
    Enter value for num: 1000
    old   6:   gen_cur_pipe(&num,w);
    new   6:   gen_cur_pipe(1000,w);
    Employee Special Deatils: SATYAKI Joined On 02-NOV-2008 12:07:30
    Employee Special Deatils: SOURAV Joined On 14-SEP-2008 00:07:21
    Employee Special Deatils: WARD Joined On 22-FEB-1981 00:00:00
    Employee Special Deatils: JONES Joined On 02-APR-1981 00:00:00
    Employee Special Deatils: MARTIN Joined On 28-SEP-1981 00:00:00
    Employee Special Deatils: BLAKE Joined On 01-MAY-1981 00:00:00
    Employee Special Deatils: CLARK Joined On 09-JUN-1981 00:00:00
    Employee Special Deatils: SCOTT Joined On 19-APR-1987 00:00:00
    Employee Special Deatils: KING Joined On 17-NOV-1981 00:00:00
    Employee Special Deatils: TURNER Joined On 08-SEP-1981 00:00:00
    Employee Special Deatils: ADAMS Joined On 23-MAY-1987 00:00:00
    Employee Special Deatils: FORD Joined On 03-DEC-1981 00:00:00
    PL/SQL procedure successfully completed.
    Elapsed: 00:00:00.30
    satyaki>
    satyaki>
    satyaki>/
    Enter value for num: 4000
    old   6:   gen_cur_pipe(&num,w);
    new   6:   gen_cur_pipe(4000,w);
    Employee Special Deatils: SATYAKI Joined On 02-NOV-2008 12:07:30
    Employee Special Deatils: SOURAV Joined On 14-SEP-2008 00:07:21
    Employee Special Deatils: CLARK Joined On 09-JUN-1981 00:00:00
    Employee Special Deatils: KING Joined On 17-NOV-1981 00:00:00
    PL/SQL procedure successfully completed.
    Elapsed: 00:00:00.13
    satyaki>I'm not so sure about the performance.
    Regards.
    Satyaki De.

  • Use of FOR Cursor and BULK COLLECT INTO

    Dear all,
    in which case we prefer to use FOR cursor and cursor with BULK COLLECT INTO? The following contains two block that query identically where one is using FOR cursor, the other is using BULK COLLECT INTO . Which one that performs better given in the existing task? How do we measure performance between these two?
    I'm using sample HR schema:
    declare
    l_start number;
    BEGIN
    l_start:= DBMS_UTILITY.get_time;
    dbms_lock.sleep(1);
    FOR employee IN (SELECT e.last_name, j.job_title FROM employees e,jobs j
    where e.job_id=j.job_id and  e.job_id LIKE '%CLERK%' AND e.manager_id > 120 ORDER BY e.last_name)
    LOOP
      DBMS_OUTPUT.PUT_LINE ('Name = ' || employee.last_name || ', Job = ' || employee.job_title);
    END LOOP;
    DBMS_OUTPUT.put_line('total time: ' || to_char(DBMS_UTILITY.get_time - l_start) || ' hsecs');
    END;
    declare
    l_start number;
    type rec_type is table of varchar2(20);
    name_rec rec_type;
    job_rec rec_type;
    begin
    l_start:= DBMS_UTILITY.get_time;
    dbms_lock.sleep(1);
    SELECT e.last_name, j.job_title bulk collect into name_rec,job_rec FROM employees e,jobs j
    where e.job_id=j.job_id and  e.job_id LIKE '%CLERK%' AND e.manager_id > 120 ORDER BY e.last_name;
    for j in name_rec.first..name_rec.last loop
      DBMS_OUTPUT.PUT_LINE ('Name = ' || name_rec(j) || ', Job = ' || job_rec(j));
    END LOOP;
    DBMS_OUTPUT.put_line('total time: ' || to_char(DBMS_UTILITY.get_time - l_start) || ' hsecs');
    end;
    /In this code, I put timestamp in each block, but they are useless since they both run virtually instantaneous...
    Best regards,
    Val

    If you want to get 100% benifit of bulk collect then it must be implemented as below
    declare
         Cursor cur_emp
         is
         SELECT     e.last_name, j.job_title
         FROM     employees e,jobs j
         where     e.job_id=j.job_id
                   and  e.job_id LIKE '%CLERK%'
                   AND e.manager_id > 120
         ORDER BY e.last_name;
         l_start number;
         type rec_type is table of varchar2(20);
         name_rec rec_type;
         job_rec rec_type;
    begin
         l_start:= DBMS_UTILITY.get_time;
         dbms_lock.sleep(1);
         /*SELECT e.last_name, j.job_title bulk collect into name_rec,job_rec FROM employees e,jobs j
         where e.job_id=j.job_id and  e.job_id LIKE '%CLERK%' AND e.manager_id > 120 ORDER BY e.last_name;
         OPEN cur_emp;
         LOOP
              FETCH cur_emp BULK COLLECT INTO name_rec LIMIT 100;
              EXIT WHEN name_rec.COUNT=0;
              FOR j in 1..name_rec.COUNT
              LOOP
                   DBMS_OUTPUT.PUT_LINE ('Name = ' || name_rec(j) || ', Job = ' || job_rec(j));          
              END LOOP;
              EXIT WHEN cur_emp%NOTFOUND;
         END LOOP;
            CLOSE cur_emp;
         DBMS_OUTPUT.put_line('total time: ' || to_char(DBMS_UTILITY.get_time - l_start) || ' hsecs');
    end;
    /

  • How can I fill a table of objects from cursor with select * bulk collect???

    Hi All, I have a TYPE as OBJECT
    create or replace type dept2_o as object (
    deptno NUMBER(2),
    dname VARCHAR2(14),
    loc VARCHAR2(13));
    I can fill a table of objects from cursor with out select * bulk collect...., row by row
    declare
    TYPE dept2_t IS TABLE of dept2_o;
    dept_o_tab dept2_t:=dept2_t();
    i integer;
    begin
    i:=0;
    dept_o_tab.extend(20);
    for rec in (select * from dept) loop
    i:=i+1;
    dept_o_tab(i):=dept2_o(
    deptno => rec.deptno,
    dname => rec.dname,
    loc =>rec.loc
    end loop;
    for k IN 1..i loop
    dbms_output.put_line(dept_o_tab(k).deptno||' '||dept_o_tab(k).dname||' '||dept_o_tab(k).loc);
    end loop;
    end;
    RESULT
    10 ACCOUNTING NEW YORK
    20 RESEARCH DALLAS
    30 SALES CHICAGO
    40 OPERATIONS BOSTON
    But I can't fill a table of objects from cursor with select * bulk collect construction ...
    declare
    TYPE dept2_t IS TABLE of dept2_o;
    dept_o_tab dept2_t:=dept2_t();
    begin
    dept_o_tab.extend(20);
    select * bulk collect into dept_o_tab from dept;
    end;
    RESULT
    ORA-06550: line 6, column 39;
    PL/SQL: ORA-00947: not enough values ....
    How can I fill a table of objects from cursor with select * bulk collect???

    create or replace type dept_ot as object (
    deptno NUMBER(2),
    dname VARCHAR2(14),
    loc VARCHAR2(13));
    create table dept
    (deptno number
    ,dname varchar2(14)
    ,loc varchar2(13)
    insert into dept values (10, 'x', 'xx');
    insert into dept values (20, 'y', 'yy');
    insert into dept values (30, 'z', 'zz');
    select dept_ot (deptno, dname, loc)
      from dept
    create type dept_nt is table of dept_ot
    declare
       l_depts dept_nt;
    begin
       select dept_ot (deptno, dname, loc)
         bulk collect
         into l_depts
         from dept
       for i in l_depts.first .. l_depts.last
       loop
          dbms_output.put_line (l_depts(i).deptno);
          dbms_output.put_line (l_depts(i).dname);
          dbms_output.put_line (l_depts(i).loc);    
       end loop;
    end;
    /

  • Procedure failed while using bulk collect into clause and works with cursor

    hi all,
    I am using "BULK collect into" clause in my procedure and it is failing after 21 minutes and gives the error "end of file communication channel".
    after this error comes when i tried to connect database it is giving following error.
    ORA -01034 - Oracle not available.
    ORA- 27101 - shared memory realm does not exist.
    svr4- error :2 : No such file or directory.
    when i use cursor instead of BULK COLLECT INTO clause it is running successful.
    Following code is working with cursor.
    procedure work_kiosk_full(an_jobid in number ,ac_sqlcode out varchar2 ,ac_sqlerrm out varchar2) is
    ld_curr_time Date;
    cursor cur_work_kiosk is
    select distinct jt.jt_id AS jt_id,
    NVL ((ROUND ((jt_date_completed - jt_date_requested) * 24, 2)
    0
    ) AS actual_hrs_to_complete,
    NVL ((ROUND ((jt_date_responded - jt_date_requested) * 24, 2)
    0
    ) AS actual_hrs_to_respond,
    peo1.peo_name AS agent_name,
    peo1.peo_user_name AS asagent_soe_id,
    le.lglent_desc AS ap_system,
    ' ' AS assign_work_request_comment,
    DECODE (jt.jt_bill_id,
    138802, 'CLIENT BILLABLE',
    138803, 'CONTRACTED',
    138804, 'INTERNAL BILLABLE',
    NULL, ' '
    ) AS billable,
    bl.bldg_name_cc AS building, bl.bldg_id_ls AS building_id,
    DECODE (bl.bldg_active_cc,
    'Y', 'ACTIVE',
    'INACTIVE'
    ) AS building_status,
    DECODE (jt.jt_wrk_cause_id,
    141521, 'STANDARD WEAR AND TEAR',
    141522, 'NEGLIGENCE',
    141523, 'ACCIDENTAL',
    141524, 'MECHANICAL MALFUNCTION',
    141525, 'OVERSIGHT',
    141526, 'VANDAL',
    141527, 'STANDARD',
    141528, 'PROJECT WORK',
    6058229, 'TEST',
    NULL, ' '
    ) AS cause_type,
    ' ' AS comments, peo3.peo_name AS completed_by,
    jt.jt_requestor_email AS contact_email,
    jt.jt_requestor_name_first
    || ' '
    || jt.jt_requestor_name_last AS contact_name,
    jt.jt_requestor_phone AS contact_phone,
    cc.cstctrcd_apcode AS corp_code,
    cc.cstctrcd_code AS cost_center,
    jt.jt_date_closed AS date_closed,
    jt.jt_date_completed AS date_completed,
    jt.jt_date_requested AS date_requested,
    jt.jt_date_responded AS date_responded,
    jt.jt_date_response_ecd AS date_response_ecd,
    jt.jt_date_scheduled AS date_scheduled,
    DECODE (jt.jt_def_id,
    139949, 'WTG VENDOR RESPONSE',
    139950, 'WAITING ON PARTS',
    139951, 'LABOR AVAILABILITY',
    139952, 'DEFERRED- HI PRI WORK',
    139953, 'WTG APPROVAL',
    139954, 'FUNDING REQUIRED',
    139955, 'ACCESS DENIED',
    139956, 'WTG MATERIAL',
    NULL, ' '
    ) AS deferral_reason,
    jt.jt_description AS description,
    jt.jt_date_resched_ecd AS ecd,
    fmg.facility_manager AS facility_manager,
    fl.floors_text AS FLOOR, gl.genled_desc AS general_ledger,
    ' ' AS kiosk_date_requested, ' ' AS kiosk_dispatch_confirmed,
    ' ' AS kiosk_dispatched,
    eqp.equip_customer_code AS linked_equipment_alias,
    eqp.equip_id AS linked_equipment_id,
    eqp.equip_text AS linked_equipment_name,
    DECODE (jt_originator_type_id,
    1000, 'PROJECT MOVE REQUEST',
    138834, 'CUSTOMER INITIATED CORRECTION',
    138835, 'CUSTOMER INITIATED REQUEST',
    138836, 'CORRECTIVE MAINTENANCE',
    138837, 'CONFERENCE ROOM BOOKING',
    138838, 'PROJECT INITIATED REQUEST',
    138839, 'PLANNED PREVENTIVE MAINTENANCE',
    138840, 'SELF INITATED REQUEST',
    NULL, ' '
    ) AS originator_type,
    ' ' AS payment_terms, priority_text AS priority_code,
    swoty.sworktype_text AS problem_type,
    prop.property_name_cc AS property,
    jt.jt_cost_quote_total AS quote_total,
    par.levels_name AS region,
    DECODE (jt.jt_repdef_id,
    141534, 'ADJUSTED SETTING',
    141535, 'TRAINING FOR END',
    141536, 'NEW REQUEST',
    141537, 'NO REPAIR REQUIR',
    141538, 'REPLACED PARTS',
    141539, 'REPLACE EQUIPMEN',
    1000699, 'NEW REQUEST',
    NULL, ' '
    ) AS repair_definitions,
    jt.jt_repairdesc AS repair_description,
    jt.jt_requestor AS requestor, ' ' AS requestor_cost_center,
    jt.jt_requestor_email AS requestor_email,
    jt.jt_requestor_name_first AS requestor_name,
    jt.jt_requestor_phone AS requestor_phone,
    ' ' AS response_time, rm.room_name_cc AS room,
    p1.peo_provider_code1 AS service_provider,
    p1.peo_address_1 AS service_provider_address,
    peocity.city_text service_provider_city,
    p1.peo_provider_code1 AS service_provider_code,
    peocity.city_country_name AS service_provider_country,
    peocur.currency_text AS service_provider_currency,
    p1.peo_name AS service_provider_description,
    p1.peo_dispatch_method AS serv_prov_dispatc_hmethod,
    p1.peo_rate_double AS serv_prov_double_time_rate,
    p1.peo_email AS service_provider_email,
    p1.peo_emergency_phone AS serv_prov_emergency_phone,
    p1.peo_fax AS service_provider_fax_number,
    p1.peo_home_phone AS service_provider_home_phone,
    p1.peo_rate_hourly AS service_provider_hourly_rate,
    p1.peo_title AS service_provider_job_title,
    p1.peo_method_id AS service_provider_method,
    p1.peo_cell_phone AS service_provider_mobile_phone,
    p1.peo_pager AS service_provider_pager,
    p1.peo_rate_differential AS service_provider_rates,
    p1.peo_rate_differential AS ser_prov_shift_differential,
    peocity.city_state_prov_text AS serv_prov_state_province,
    DECODE (p1.peo_active,
    'Y', 'ACTIVE',
    'INACTIVE'
    ) AS service_provider_status,
    p1.peo_url AS serv_prov_web_site_address,
    p1.peo_phone AS service_provider_work_phone,
    p1.peo_postal_code AS serv_prov_zip_postal_code, ' ' AS shift,
    ' ' AS skill,
    DECODE (jt.jt_bigstatus_id,
    138813, 'NEW',
    138814, 'PENDING',
    138815, 'OPEN',
    138816, 'COMPLETED',
    138817, 'CLOSED',
    138818, 'CANCELLED',
    NULL, ' '
    ) AS status,
    lev.levels_name AS subregion, ' ' AS trade,
    p1.peo_ls_interface_code1 AS vendor_id,
    p1.peo_fax AS vendor_purchasing_fax,
    p1.peo_vendor_site_code AS vendor_sitecode,
    jt.jt_id AS vendor_ticket, p1.peo_name AS vendor_companyname,
    jt.jt_requestor_vip AS vip, wo.wo_id AS work_order_no,
    jt.jt_id AS work_request,
    jt.jt_class_id AS work_request_class,
    woty.worktype_text AS work_type, ' ' AS wr_cost,
    jt.jt_description AS wr_description,
    ' ' AS wr_dispatch_method,
    DECODE (jt.jt_bigstatus_id,
    138813, 'NEW',
    138814, 'PENDING',
    138815, 'OPEN',
    138816, 'COMPLETED',
    138817, 'CLOSED',
    138818, 'CANCELLED',
    NULL, ' '
    ) AS wr_status,
    ctry.country_name AS country
    FROM citi.jobticket jt,
    citi.property prop,
    citi.bldg bl,
    citi.bldg_levels bldglvl,
    citi.LEVELS lev,
    citi.LEVELS par,
    (SELECT crstools.stragg (peo_name) facility_manager,
    bldgcon_bldg_id
    FROM citi.bldg_contacts, citi.people
    WHERE bldgcon_peo_id = peo_id
    AND bldgcon_contype_id IN (40181, 10142)
    GROUP BY bldgcon_bldg_id) fmg,
    citi.floors fl,
    citi.room rm,
    citi.general_ledger gl,
    citi.legal_entity le,
    citi.cost_center_codes cc,
    citi.equipment eqp,
    citi.worktype woty,
    citi.subworktype swoty,
    citi.work_order wo,
    citi.jt_workers jtwo,
    citi.priority,
    citi.country ctry,
    citi.people p1,
    citi.people peo3,
    citi.people peo1,
    citi.city peocity,
    citi.currency peocur
    WHERE jt.jt_bldg_id = bl.bldg_id
    AND bl.bldg_id = bldglvl.bldg_levels_bldg_id
    AND bldglvl.bldg_levels_levels_id = lev.levels_id
    AND lev.levels_parent = par.levels_id(+)
    AND prop.property_id = bl.bldg_property_id
    AND bl.bldg_active_ls <> 'N'
    AND jt.jt_floors_id = fl.floors_id(+)
    AND jt.jt_room_id = rm.room_id(+)
    AND jt.jt_bldg_id = fmg.bldgcon_bldg_id(+)
    AND jt.jt_genled_id = gl.genled_id(+)
    AND gl.genled_lglent_id = le.lglent_id(+)
    AND jt.jt_cstctrcd_id = cc.cstctrcd_id(+)
    AND jt.jt_equip_id = eqp.equip_id(+)
    AND jt.jt_id = jtwo.jtw_jt_id(+)
    AND jt.jt_worktype_id = woty.worktype_id(+)
    AND jt.jt_sworktype_id = swoty.sworktype_id(+)
    AND jt.jt_wo_id = wo.wo_id
    AND jt.jt_priority_id = priority_id(+)
    --AND jt.jt_date_requested >= ADD_MONTHS (SYSDATE, -12)
    AND jt.jt_last_update >= ADD_MONTHS (ld_curr_time, -12)
    AND bl.bldg_country_id = ctry.country_id
    AND jtwo.jtw_peo_id = p1.peo_id(+)
    AND p1.peo_city_id = peocity.city_id(+)
    AND jt.jt_completed_by_peo_id = peo3.peo_id(+)
    AND p1.peo_rate_currency_id = peocur.currency_id(+)
    AND jt.jt_agent_peo_id = peo1.peo_id(+);
    BEGIN
    execute immediate 'truncate table crstools.drt_bom_work_kiosk';
    select sysdate into ld_curr_time from dual;
    FOR cur_rec in cur_work_kiosk LOOP
    IF MOD(cur_work_kiosk%rowcount,10000 ) = 0 then
    COMMIT;
    END IF;
    INSERT INTO crstools.drt_bom_work_kiosk
    ( JT_ID
    ,ACTUAL_HRS_TO_COMPLETE
    ,ACTUAL_HRS_TO_RESPOND
    ,AGENT_NAME
    ,ASAGENT_SOE_ID
    ,AP_SYSTEM
    ,ASSIGN_WORK_REQUEST_COMMENT
    ,BILLABLE
    ,BUILDING
    ,BUILDING_ID
    ,BUILDING_STATUS
    ,CAUSE_TYPE
    ,COMMENTS
    ,COMPLETED_BY
    ,CONTACT_EMAIL
    ,CONTACT_NAME
    ,CONTACT_PHONE
    ,CORP_CODE
    ,COST_CENTER
    ,DATE_CLOSED
    ,DATE_COMPLETED
    ,DATE_REQUESTED
    ,DATE_RESPONDED
    ,DATE_RESPONSE_ECD
    ,DATE_SCHEDULED
    ,DEFERRAL_REASON
    ,DESCRIPTION
    ,ECD
    ,FACILITY_MANAGER
    ,FLOOR
    ,GENERAL_LEDGER
    ,KIOSK_DATE_REQUESTED
    ,KIOSK_DISPATCH_CONFIRMED
    ,KIOSK_DISPATCHED
    ,LINKED_EQUIPMENT_ALIAS
    ,LINKED_EQUIPMENT_ID
    ,LINKED_EQUIPMENT_NAME
    ,ORIGINATOR_TYPE
    ,PAYMENT_TERMS
    ,PRIORITY_CODE
    ,PROBLEM_TYPE
    ,PROPERTY
    ,QUOTE_TOTAL
    ,REGION
    ,REPAIR_DEFINITIONS
    ,REPAIR_DESCRIPTION
    ,REQUESTOR
    ,REQUESTOR_COST_CENTER
    ,REQUESTOR_EMAIL
    ,REQUESTOR_NAME
    ,REQUESTOR_PHONE
    ,RESPONSE_TIME
    ,ROOM
    ,SERVICE_PROVIDER
    ,SERVICE_PROVIDER_ADDRESS
    ,SERVICE_PROVIDER_CITY
    ,SERVICE_PROVIDER_CODE
    ,SERVICE_PROVIDER_COUNTRY
    ,SERVICE_PROVIDER_CURRENCY
    ,SERVICE_PROVIDER_DESCRIPTION
    ,SERV_PROV_DISPATC_HMETHOD
    ,SERV_PROV_DOUBLE_TIME_RATE
    ,SERVICE_PROVIDER_EMAIL
    ,SERV_PROV_EMERGENCY_PHONE
    ,SERVICE_PROVIDER_FAX_NUMBER
    ,SERVICE_PROVIDER_HOME_PHONE
    ,SERVICE_PROVIDER_HOURLY_RATE
    ,SERVICE_PROVIDER_JOB_TITLE
    ,SERVICE_PROVIDER_METHOD
    ,SERVICE_PROVIDER_MOBILE_PHONE
    ,SERVICE_PROVIDER_PAGER
    ,SERVICE_PROVIDER_RATES
    ,SER_PROV_SHIFT_DIFFERENTIAL
    ,SERV_PROV_STATE_PROVINCE
    ,SERVICE_PROVIDER_STATUS
    ,SERV_PROV_WEB_SITE_ADDRESS
    ,SERVICE_PROVIDER_WORK_PHONE
    ,SERV_PROV_ZIP_POSTAL_CODE
    ,SHIFT
    ,SKILL
    ,STATUS
    ,SUBREGION
    ,TRADE
    ,VENDOR_ID
    ,VENDOR_PURCHASING_FAX
    ,VENDOR_SITECODE
    ,VENDOR_TICKET
    ,VENDOR_COMPANYNAME
    ,VIP
    ,WORK_ORDER_NO
    ,WORK_REQUEST
    ,WORK_REQUEST_CLASS
    ,WORK_TYPE
    ,WR_COST
    ,WR_DESCRIPTION
    ,WR_DISPATCH_METHOD
    ,WR_STATUS
    ,COUNTRY
    ,CREATE_DATE
    VALUES
    (cur_rec.jt_id
    ,cur_rec.ACTUAL_HRS_TO_COMPLETE
    ,cur_rec.ACTUAL_HRS_TO_RESPOND
    ,cur_rec.AGENT_NAME
    ,cur_rec.ASAGENT_SOE_ID
    ,cur_rec.AP_SYSTEM
    ,cur_rec.ASSIGN_WORK_REQUEST_COMMENT
    ,cur_rec.BILLABLE
    ,cur_rec.BUILDING
    ,cur_rec.BUILDING_ID
    ,cur_rec.BUILDING_STATUS
    ,cur_rec.CAUSE_TYPE
    ,cur_rec.COMMENTS
    ,cur_rec.COMPLETED_BY
    ,cur_rec.CONTACT_EMAIL
    ,cur_rec.CONTACT_NAME
    ,cur_rec.CONTACT_PHONE
    ,cur_rec.CORP_CODE
    ,cur_rec.COST_CENTER
    ,cur_rec.DATE_CLOSED
    ,cur_rec.DATE_COMPLETED
    ,cur_rec.DATE_REQUESTED
    ,cur_rec.DATE_RESPONDED
    ,cur_rec.DATE_RESPONSE_ECD
    ,cur_rec.DATE_SCHEDULED
    ,cur_rec.DEFERRAL_REASON
    ,cur_rec.DESCRIPTION
    ,cur_rec.ECD
    ,cur_rec.FACILITY_MANAGER
    ,cur_rec.FLOOR
    ,cur_rec.GENERAL_LEDGER
    ,cur_rec.KIOSK_DATE_REQUESTED
    ,cur_rec.KIOSK_DISPATCH_CONFIRMED
    ,cur_rec.KIOSK_DISPATCHED
    ,cur_rec.LINKED_EQUIPMENT_ALIAS
    ,cur_rec.LINKED_EQUIPMENT_ID
    ,cur_rec.LINKED_EQUIPMENT_NAME
    ,cur_rec.ORIGINATOR_TYPE
    ,cur_rec.PAYMENT_TERMS
    ,cur_rec.PRIORITY_CODE
    ,cur_rec.PROBLEM_TYPE
    ,cur_rec.PROPERTY
    ,cur_rec.QUOTE_TOTAL
    ,cur_rec.REGION
    ,cur_rec.REPAIR_DEFINITIONS
    ,cur_rec.REPAIR_DESCRIPTION
    ,cur_rec.REQUESTOR
    ,cur_rec.REQUESTOR_COST_CENTER
    ,cur_rec.REQUESTOR_EMAIL
    ,cur_rec.REQUESTOR_NAME
    ,cur_rec.REQUESTOR_PHONE
    ,cur_rec.RESPONSE_TIME
    ,cur_rec.ROOM
    ,cur_rec.SERVICE_PROVIDER
    ,cur_rec.SERVICE_PROVIDER_ADDRESS
    ,cur_rec.SERVICE_PROVIDER_CITY
    ,cur_rec.SERVICE_PROVIDER_CODE
    ,cur_rec.SERVICE_PROVIDER_COUNTRY
    ,cur_rec.SERVICE_PROVIDER_CURRENCY
    ,cur_rec.SERVICE_PROVIDER_DESCRIPTION
    ,cur_rec.SERV_PROV_DISPATC_HMETHOD
    ,cur_rec.SERV_PROV_DOUBLE_TIME_RATE
    ,cur_rec.SERVICE_PROVIDER_EMAIL
    ,cur_rec.SERV_PROV_EMERGENCY_PHONE
    ,cur_rec.SERVICE_PROVIDER_FAX_NUMBER
    ,cur_rec.SERVICE_PROVIDER_HOME_PHONE
    ,cur_rec.SERVICE_PROVIDER_HOURLY_RATE
    ,cur_rec.SERVICE_PROVIDER_JOB_TITLE
    ,cur_rec.SERVICE_PROVIDER_METHOD
    ,cur_rec.SERVICE_PROVIDER_MOBILE_PHONE
    ,cur_rec.SERVICE_PROVIDER_PAGER
    ,cur_rec.SERVICE_PROVIDER_RATES
    ,cur_rec.SER_PROV_SHIFT_DIFFERENTIAL
    ,cur_rec.SERV_PROV_STATE_PROVINCE
    ,cur_rec.SERVICE_PROVIDER_STATUS
    ,cur_rec.SERV_PROV_WEB_SITE_ADDRESS
    ,cur_rec.SERVICE_PROVIDER_WORK_PHONE
    ,cur_rec.SERV_PROV_ZIP_POSTAL_CODE
    ,cur_rec.SHIFT
    ,cur_rec.SKILL
    ,cur_rec.STATUS
    ,cur_rec.SUBREGION
    ,cur_rec.TRADE
    ,cur_rec.VENDOR_ID
    ,cur_rec.VENDOR_PURCHASING_FAX
    ,cur_rec.VENDOR_SITECODE
    ,cur_rec.VENDOR_TICKET
    ,cur_rec.VENDOR_COMPANYNAME
    ,cur_rec.VIP
    ,cur_rec.WORK_ORDER_NO
    ,cur_rec.WORK_REQUEST
    ,cur_rec.WORK_REQUEST_CLASS
    ,cur_rec.WORK_TYPE
    ,cur_rec.WR_COST
    ,cur_rec.WR_DESCRIPTION
    ,cur_rec.WR_DISPATCH_METHOD
    ,cur_rec.WR_STATUS
    ,cur_rec.COUNTRY
    ,ld_curr_time
    END LOOP;
    COMMIT;
    exception
    when others then
    rollback;
    dbms_output.put_line('SQLCODE :'||sqlcode ||' Error :'||sqlerrm);
    end work_kiosk_full;
    Note : total record inserted 849000.
    The same code does not work with bulk collect into caluse.
    Please help me out why this is happening.
    Thanks & regards
    shyam~

    Shyam,
    I agree with Billy.
    Why are you not using an INSERT..SELECT ?
    Also, what are you trying to achieve by
    - incremental commits?
    - copying data from one table to another (using expensive I/O)?
    - using dynamic DML?
    Most of these approaches are typically wrong - and not recommended for scalable and performant Oracle applications.I could see you using a CURSOR FOR LOOP if you were changing the data being inserted in such a way that you couldn't encapsulate the changes in a query, but you are doing a straight insert into the table from your Cursor. A much more efficient way would be to use the following modifications I made to your code example:
    PROCEDURE WORK_KIOSK_FULL(AN_JOBID   IN NUMBER,
                              AC_SQLCODE OUT VARCHAR2,
                              AC_SQLERRM OUT VARCHAR2) IS
    BEGIN
       EXECUTE IMMEDIATE 'truncate table crstools.drt_bom_work_kiosk';
       /* Note:  The APPEND hint forces a Direct Path INSERT (see Link below code sample) and is combined with the NOLOGGING Hint */
       /*        To dramtically increase performance.  The Direct Path INSERT inserts records above the High-Water Mark on the table. */
       INSERT /*+ APPEND NOLOGGING */ INTO CRSTOOLS.DRT_BOM_WORK_KIOSK
          (JT_ID
          ,ACTUAL_HRS_TO_COMPLETE
          ,ACTUAL_HRS_TO_RESPOND
          ,AGENT_NAME
          ,ASAGENT_SOE_ID
          ,AP_SYSTEM
    --      ,ASSIGN_WORK_REQUEST_COMMENT     /* I commented out this COLUMN because it doesn't make sense to me to insert */
          ,BILLABLE                          /* a couple of space characters into a table.   If the intent is to leave the column NULL */
          ,BUILDING                          /* don't include it in your INSERT statement and it will be NULL.  If there is a valid reason */
          ,BUILDING_ID                       /* for inserting the spaces, then remove the "line comments" from the insert and select statments */
          ,BUILDING_STATUS
          ,CAUSE_TYPE
    --      ,COMMENTS
          ,COMPLETED_BY
          ,CONTACT_EMAIL
          ,CONTACT_NAME
          ,CONTACT_PHONE
          ,CORP_CODE
          ,COST_CENTER
          ,DATE_CLOSED
          ,DATE_COMPLETED
          ,DATE_REQUESTED
          ,DATE_RESPONDED
          ,DATE_RESPONSE_ECD
          ,DATE_SCHEDULED
          ,DEFERRAL_REASON
          ,DESCRIPTION
          ,ECD
          ,FACILITY_MANAGER
          ,FLOOR
          ,GENERAL_LEDGER
    --      ,KIOSK_DATE_REQUESTED
    --      ,KIOSK_DISPATCH_CONFIRMED
    --      ,KIOSK_DISPATCHED
          ,LINKED_EQUIPMENT_ALIAS
          ,LINKED_EQUIPMENT_ID
          ,LINKED_EQUIPMENT_NAME
          ,ORIGINATOR_TYPE
    --      ,PAYMENT_TERMS
          ,PRIORITY_CODE
          ,PROBLEM_TYPE
          ,PROPERTY
          ,QUOTE_TOTAL
          ,REGION
          ,REPAIR_DEFINITIONS
          ,REPAIR_DESCRIPTION
          ,REQUESTOR
    --      ,REQUESTOR_COST_CENTER
          ,REQUESTOR_EMAIL
          ,REQUESTOR_NAME
          ,REQUESTOR_PHONE
    --      ,RESPONSE_TIME
          ,ROOM
          ,SERVICE_PROVIDER
          ,SERVICE_PROVIDER_ADDRESS
          ,SERVICE_PROVIDER_CITY
          ,SERVICE_PROVIDER_CODE
          ,SERVICE_PROVIDER_COUNTRY
          ,SERVICE_PROVIDER_CURRENCY
          ,SERVICE_PROVIDER_DESCRIPTION
          ,SERV_PROV_DISPATC_HMETHOD
          ,SERV_PROV_DOUBLE_TIME_RATE
          ,SERVICE_PROVIDER_EMAIL
          ,SERV_PROV_EMERGENCY_PHONE
          ,SERVICE_PROVIDER_FAX_NUMBER
          ,SERVICE_PROVIDER_HOME_PHONE
          ,SERVICE_PROVIDER_HOURLY_RATE
          ,SERVICE_PROVIDER_JOB_TITLE
          ,SERVICE_PROVIDER_METHOD
          ,SERVICE_PROVIDER_MOBILE_PHONE
          ,SERVICE_PROVIDER_PAGER
          ,SERVICE_PROVIDER_RATES
          ,SER_PROV_SHIFT_DIFFERENTIAL
          ,SERV_PROV_STATE_PROVINCE
          ,SERVICE_PROVIDER_STATUS
          ,SERV_PROV_WEB_SITE_ADDRESS
          ,SERVICE_PROVIDER_WORK_PHONE
          ,SERV_PROV_ZIP_POSTAL_CODE
    --      ,SHIFT
    --      ,SKILL
          ,STATUS
          ,SUBREGION
    --      ,TRADE
          ,VENDOR_ID
          ,VENDOR_PURCHASING_FAX
          ,VENDOR_SITECODE
          ,VENDOR_TICKET
          ,VENDOR_COMPANYNAME
          ,VIP
          ,WORK_ORDER_NO
          ,WORK_REQUEST
          ,WORK_REQUEST_CLASS
          ,WORK_TYPE
    --      ,WR_COST
          ,WR_DESCRIPTION
    --      ,WR_DISPATCH_METHOD
          ,WR_STATUS
          ,COUNTRY
          ,CREATE_DATE
       VALUES
          (SELECT DISTINCT
              JT.JT_ID AS JT_ID
             ,NVL((ROUND((JT_DATE_COMPLETED - JT_DATE_REQUESTED) * 24,2)),0) AS ACTUAL_HRS_TO_COMPLETE
             ,NVL((ROUND((JT_DATE_RESPONDED - JT_DATE_REQUESTED) * 24,2)),0) AS ACTUAL_HRS_TO_RESPOND
             ,PEO1.PEO_NAME AS AGENT_NAME
             ,PEO1.PEO_USER_NAME AS ASAGENT_SOE_ID
             ,LE.LGLENT_DESC AS AP_SYSTEM
    --         ,' ' AS ASSIGN_WORK_REQUEST_COMMENT
             ,DECODE(JT.JT_BILL_ID,138802,'CLIENT BILLABLE'
                                  ,138803,'CONTRACTED'
                                  ,138804,'INTERNAL BILLABLE',NULL,' ') AS BILLABLE
             ,BL.BLDG_NAME_CC AS BUILDING
             ,BL.BLDG_ID_LS AS BUILDING_ID
             ,DECODE(BL.BLDG_ACTIVE_CC, 'Y', 'ACTIVE', 'INACTIVE') AS BUILDING_STATUS
             ,DECODE(JT.JT_WRK_CAUSE_ID,141521,'STANDARD WEAR AND TEAR'
                                       ,141522,'NEGLIGENCE'
                                       ,141523,'ACCIDENTAL'
                                       ,141524,'MECHANICAL MALFUNCTION'
                                       ,141525,'OVERSIGHT'
                                       ,141526,'VANDAL'
                                       ,141527,'STANDARD'
                                       ,141528,'PROJECT WORK'
                                       ,6058229,'TEST',NULL,' ') AS CAUSE_TYPE
    --         ,' ' AS COMMENTS
             ,PEO3.PEO_NAME AS COMPLETED_BY
             ,JT.JT_REQUESTOR_EMAIL AS CONTACT_EMAIL
             ,JT.JT_REQUESTOR_NAME_FIRST || ' ' ||JT.JT_REQUESTOR_NAME_LAST AS CONTACT_NAME
             ,JT.JT_REQUESTOR_PHONE AS CONTACT_PHONE
             ,CC.CSTCTRCD_APCODE AS CORP_CODE
             ,CC.CSTCTRCD_CODE AS COST_CENTER
             ,JT.JT_DATE_CLOSED AS DATE_CLOSED
             ,JT.JT_DATE_COMPLETED AS DATE_COMPLETED
             ,JT.JT_DATE_REQUESTED AS DATE_REQUESTED
             ,JT.JT_DATE_RESPONDED AS DATE_RESPONDED
             ,JT.JT_DATE_RESPONSE_ECD AS DATE_RESPONSE_ECD
             ,JT.JT_DATE_SCHEDULED AS DATE_SCHEDULED
             ,DECODE(JT.JT_DEF_ID,139949,'WTG VENDOR RESPONSE'
                                 ,139950,'WAITING ON PARTS'
                                 ,139951,'LABOR AVAILABILITY'
                                 ,139952,'DEFERRED- HI PRI WORK'
                                 ,139953,'WTG APPROVAL'
                                 ,139954,'FUNDING REQUIRED'
                                 ,139955,'ACCESS DENIED'
                                 ,139956,'WTG MATERIAL',NULL,' ') AS DEFERRAL_REASON
             ,JT.JT_DESCRIPTION AS DESCRIPTION
             ,JT.JT_DATE_RESCHED_ECD AS ECD
             ,FMG.FACILITY_MANAGER AS FACILITY_MANAGER
             ,FL.FLOORS_TEXT AS FLOOR
             ,GL.GENLED_DESC AS GENERAL_LEDGER
    --         ,' ' AS KIOSK_DATE_REQUESTED
    --         ,' ' AS KIOSK_DISPATCH_CONFIRMED
    --         ,' ' AS KIOSK_DISPATCHED
             ,EQP.EQUIP_CUSTOMER_CODE AS LINKED_EQUIPMENT_ALIAS
             ,EQP.EQUIP_ID AS LINKED_EQUIPMENT_ID
             ,EQP.EQUIP_TEXT AS LINKED_EQUIPMENT_NAME
             ,DECODE(JT_ORIGINATOR_TYPE_ID,1000,'PROJECT MOVE REQUEST'
                                          ,138834,'CUSTOMER INITIATED CORRECTION'
                                          ,138835,'CUSTOMER INITIATED REQUEST'
                                          ,138836,'CORRECTIVE MAINTENANCE'
                                          ,138837,'CONFERENCE ROOM BOOKING'
                                          ,138838,'PROJECT INITIATED REQUEST'
                                          ,138839,'PLANNED PREVENTIVE MAINTENANCE'
                                          ,138840,'SELF INITATED REQUEST',NULL,' ') AS ORIGINATOR_TYPE
    --         ,' ' AS PAYMENT_TERMS
             ,PRIORITY_TEXT AS PRIORITY_CODE
             ,SWOTY.SWORKTYPE_TEXT AS PROBLEM_TYPE
             ,PROP.PROPERTY_NAME_CC AS PROPERTY
             ,JT.JT_COST_QUOTE_TOTAL AS QUOTE_TOTAL
             ,PAR.LEVELS_NAME AS REGION
             ,DECODE(JT.JT_REPDEF_ID,141534,'ADJUSTED SETTING'
                                    ,141535,'TRAINING FOR END'
                                    ,141536,'NEW REQUEST'
                                    ,141537,'NO REPAIR REQUIR'
                                    ,141538,'REPLACED PARTS'
                                    ,141539,'REPLACE EQUIPMEN'
                                    ,1000699,'NEW REQUEST',NULL,' ') AS REPAIR_DEFINITIONS
             ,JT.JT_REPAIRDESC AS REPAIR_DESCRIPTION
             ,JT.JT_REQUESTOR AS REQUESTOR
    --         ,' ' AS REQUESTOR_COST_CENTER
             ,JT.JT_REQUESTOR_EMAIL AS REQUESTOR_EMAIL
             ,JT.JT_REQUESTOR_NAME_FIRST AS REQUESTOR_NAME
             ,JT.JT_REQUESTOR_PHONE AS REQUESTOR_PHONE
    --         ,' ' AS RESPONSE_TIME
             ,RM.ROOM_NAME_CC AS ROOM
             ,P1.PEO_PROVIDER_CODE1 AS SERVICE_PROVIDER
             ,P1.PEO_ADDRESS_1 AS SERVICE_PROVIDER_ADDRESS
             ,PEOCITY.CITY_TEXT SERVICE_PROVIDER_CITY
             ,P1.PEO_PROVIDER_CODE1 AS SERVICE_PROVIDER_CODE
             ,PEOCITY.CITY_COUNTRY_NAME AS SERVICE_PROVIDER_COUNTRY
             ,PEOCUR.CURRENCY_TEXT AS SERVICE_PROVIDER_CURRENCY
             ,P1.PEO_NAME AS SERVICE_PROVIDER_DESCRIPTION
             ,P1.PEO_DISPATCH_METHOD AS SERV_PROV_DISPATC_HMETHOD
             ,P1.PEO_RATE_DOUBLE AS SERV_PROV_DOUBLE_TIME_RATE
             ,P1.PEO_EMAIL AS SERVICE_PROVIDER_EMAIL
             ,P1.PEO_EMERGENCY_PHONE AS SERV_PROV_EMERGENCY_PHONE
             ,P1.PEO_FAX AS SERVICE_PROVIDER_FAX_NUMBER
             ,P1.PEO_HOME_PHONE AS SERVICE_PROVIDER_HOME_PHONE
             ,P1.PEO_RATE_HOURLY AS SERVICE_PROVIDER_HOURLY_RATE
             ,P1.PEO_TITLE AS SERVICE_PROVIDER_JOB_TITLE
             ,P1.PEO_METHOD_ID AS SERVICE_PROVIDER_METHOD
             ,P1.PEO_CELL_PHONE AS SERVICE_PROVIDER_MOBILE_PHONE
             ,P1.PEO_PAGER AS SERVICE_PROVIDER_PAGER
             ,P1.PEO_RATE_DIFFERENTIAL AS SERVICE_PROVIDER_RATES
             ,P1.PEO_RATE_DIFFERENTIAL AS SER_PROV_SHIFT_DIFFERENTIAL
             ,PEOCITY.CITY_STATE_PROV_TEXT AS SERV_PROV_STATE_PROVINCE
             ,DECODE(P1.PEO_ACTIVE, 'Y', 'ACTIVE', 'INACTIVE') AS SERVICE_PROVIDER_STATUS
             ,P1.PEO_URL AS SERV_PROV_WEB_SITE_ADDRESS
             ,P1.PEO_PHONE AS SERVICE_PROVIDER_WORK_PHONE
             ,P1.PEO_POSTAL_CODE AS SERV_PROV_ZIP_POSTAL_CODE
    --         ,' ' AS SHIFT
    --         ,' ' AS SKILL
             ,DECODE(JT.JT_BIGSTATUS_ID,138813,'NEW'
                                       ,138814,'PENDING'
                                       ,138815,'OPEN'
                                       ,138816,'COMPLETED'
                                       ,138817,'CLOSED'
                                       ,138818,'CANCELLED',NULL,' ') AS STATUS
             ,LEV.LEVELS_NAME AS SUBREGION
    --         ,' ' AS TRADE
             ,P1.PEO_LS_INTERFACE_CODE1 AS VENDOR_ID
             ,P1.PEO_FAX AS VENDOR_PURCHASING_FAX
             ,P1.PEO_VENDOR_SITE_CODE AS VENDOR_SITECODE
             ,JT.JT_ID AS VENDOR_TICKET
             ,P1.PEO_NAME AS VENDOR_COMPANYNAME
             ,JT.JT_REQUESTOR_VIP AS VIP
             ,WO.WO_ID AS WORK_ORDER_NO
             ,JT.JT_ID AS WORK_REQUEST
             ,JT.JT_CLASS_ID AS WORK_REQUEST_CLASS
             ,WOTY.WORKTYPE_TEXT AS WORK_TYPE
    --         ,' ' AS WR_COST
             ,JT.JT_DESCRIPTION AS WR_DESCRIPTION
    --         ,' ' AS WR_DISPATCH_METHOD
             ,DECODE(JT.JT_BIGSTATUS_ID,138813,'NEW'
                                       ,138814,'PENDING'
                                       ,138815,'OPEN'
                                       ,138816,'COMPLETED'
                                       ,138817,'CLOSED'
                                       ,138818,'CANCELLED',NULL,' ') AS WR_STATUS
             ,CTRY.COUNTRY_NAME AS COUNTRY
             ,SYSDATE --LD_CURR_TIME
         FROM CITI.JOBTICKET JT,
              CITI.PROPERTY PROP,
              CITI.BLDG BL,
              CITI.BLDG_LEVELS BLDGLVL,
              CITI.LEVELS LEV,
              CITI.LEVELS PAR,
              (SELECT CRSTOOLS.STRAGG(PEO_NAME) FACILITY_MANAGER,
                      BLDGCON_BLDG_ID
                 FROM CITI.BLDG_CONTACTS, CITI.PEOPLE
                WHERE BLDGCON_PEO_ID = PEO_ID
                  AND BLDGCON_CONTYPE_ID IN (40181, 10142)
                GROUP BY BLDGCON_BLDG_ID) FMG,
              CITI.FLOORS FL,
              CITI.ROOM RM,
              CITI.GENERAL_LEDGER GL,
              CITI.LEGAL_ENTITY LE,
              CITI.COST_CENTER_CODES CC,
              CITI.EQUIPMENT EQP,
              CITI.WORKTYPE WOTY,
              CITI.SUBWORKTYPE SWOTY,
              CITI.WORK_ORDER WO,
              CITI.JT_WORKERS JTWO,
              CITI.PRIORITY,
              CITI.COUNTRY CTRY,
              CITI.PEOPLE P1,
              CITI.PEOPLE PEO3,
              CITI.PEOPLE PEO1,
              CITI.CITY PEOCITY,
              CITI.CURRENCY PEOCUR
        WHERE JT.JT_BLDG_ID = BL.BLDG_ID
          AND BL.BLDG_ID = BLDGLVL.BLDG_LEVELS_BLDG_ID
          AND BLDGLVL.BLDG_LEVELS_LEVELS_ID = LEV.LEVELS_ID
          AND LEV.LEVELS_PARENT = PAR.LEVELS_ID(+)
          AND PROP.PROPERTY_ID = BL.BLDG_PROPERTY_ID
          AND BL.BLDG_ACTIVE_LS = 'N'
          AND JT.JT_FLOORS_ID = FL.FLOORS_ID(+)
          AND JT.JT_ROOM_ID = RM.ROOM_ID(+)
          AND JT.JT_BLDG_ID = FMG.BLDGCON_BLDG_ID(+)
          AND JT.JT_GENLED_ID = GL.GENLED_ID(+)
          AND GL.GENLED_LGLENT_ID = LE.LGLENT_ID(+)
          AND JT.JT_CSTCTRCD_ID = CC.CSTCTRCD_ID(+)
          AND JT.JT_EQUIP_ID = EQP.EQUIP_ID(+)
          AND JT.JT_ID = JTWO.JTW_JT_ID(+)
          AND JT.JT_WORKTYPE_ID = WOTY.WORKTYPE_ID(+)
          AND JT.JT_SWORKTYPE_ID = SWOTY.SWORKTYPE_ID(+)
          AND JT.JT_WO_ID = WO.WO_ID
          AND JT.JT_PRIORITY_ID = PRIORITY_ID(+)
             --AND jt.jt_date_requested >= ADD_MONTHS (SYSDATE, -12)
          AND JT.JT_LAST_UPDATE >= ADD_MONTHS(LD_CURR_TIME, -12)
          AND BL.BLDG_COUNTRY_ID = CTRY.COUNTRY_ID
          AND JTWO.JTW_PEO_ID = P1.PEO_ID(+)
          AND P1.PEO_CITY_ID = PEOCITY.CITY_ID(+)
          AND JT.JT_COMPLETED_BY_PEO_ID = PEO3.PEO_ID(+)
          AND P1.PEO_RATE_CURRENCY_ID = PEOCUR.CURRENCY_ID(+)
          AND JT.JT_AGENT_PEO_ID = PEO1.PEO_ID(+)
       COMMIT;
    EXCEPTION
       WHEN OTHERS THEN
          ROLLBACK;
          DBMS_OUTPUT.PUT_LINE('SQLCODE :' || SQLCODE || ' Error :' || SQLERRM);
    END WORK_KIOSK_FULL;Here's the link for infor on the [Oracle Direct-Path INSERT |http://download.oracle.com/docs/cd/B10501_01/server.920/a96524/c21dlins.htm#10778].
    Also, if you are truly intent on using a CURSOR FOR LOOP with the BULK COLLECT, I suggest you read Steven Feuerstein's article [PL/SQL Practices: On BULK COLLECT |http://www.oracle.com/technology/oramag/oracle/08-mar/o28plsql.html].
    Hope this helps.
    Craig...
    If my response or the response of another was helpful, please mark it accordingly

  • Merging a collection into a table

    I have a table with some blank columns.
    I take all the data from the table in a collection and then process the data to fill those empty columns.
    Now i have the collection with all the valid data.
    Is it possible to cast this same collection into a table and merge it again into the original table?
    I am trying to do so, but there is an error saying "cant use local collection"...
    Any help on this would be appreciated.

    Thanks a lot for your suggestion.
    I would like to give you an elaborate process.
    I have a table ABC. Some columns of that table are empty. I need to get those filled using some other tables.
    Firstly, using a cursor I fetch the records in a collection say V_ABC.
    Now in a FOR loop, I am fetching the missing data from other tables for every record in the collection and setting it in the empty places in the collection V_ABC itself.
    So finally i have the collection V_ABC which has complete data.
    The FOR loop is now ended.
    Now i try to merge this V_ABC into tale ABC like this:
    MERGE INTO ABC abc
    USING TABLE(CAST(V_ABC AS TT_ABC)) z
    ON (abc.random_column_name = z.random_column_name)
    WHEN MATCHED THEN
    UPDATE
    SET abc.initially_empty_column = z.initially_empty_column
    The exact error is "Error: PLS-00642: local collection types not allowed in SQL statements".
    I am forced to use PL-SQL because of performance issues.
    Could you provide an alternate way?
    I guess one way would be to create another empty collection and EXTENDing it and creating a replica of V_ABC. Then probably it will allow me to merge. But i m not sure.

  • Bind ordered pair of nested tables into cursor

    Hello,
    I'd like to ask you for help. I was searching for this topic, but haven't found any answer.
    This is a very simple example that works with HR schema.
    I have a stored type:
    CREATE TYPE t_ids AS TABLE OF NUMBER(9);
    and simple procedure. There is a cursor with paremeter that accepts nested table and uses MEMBER OF operator.
    CREATE OR REPLACE PROCEDURE m_test
    AS
    CURSOR mycur (a_ids t_ids)
    IS
    SELECT last_name
    FROM employees
    WHERE employee_id MEMBER OF a_ids;
    some_ids t_ids;
    TYPE t_result IS TABLE OF employees.first_name%TYPE;
    result_table t_result;
    BEGIN
    some_ids := t_ids(100,101,102);
    OPEN mycur (some_ids);
    FETCH mycur BULK COLLECT INTO result_table;
    CLOSE mycur;
    DBMS_OUTPUT.PUT_LINE('count: ' || result_table.COUNT);
    END m_test;
    This example works fine. BUT - What I need is to modify the cursor in this way:
    CURSOR mycur (a_ids t_ids)
    IS
    SELECT last_name
    FROM employees
    WHERE *(employee_id,manager_id)* MEMBER OF (a_ids,a_ids);
    Well - this does not function - and is't my question - which operator should I use to compare ordered pair with two nested tables?
    Thank you!
    Pavel Ruzicka
    Edited by: user8117512 on 28.8.2009 6:12

    user8117512 wrote:
    No, no, pls. don't look at repeating a_ids. This is only an example. There could be two different nested tables.
    There is, lets say,
    (employee_id,manager_id) MEMBER OF (a_fist_table,a_second_table);But this syntax doesn't have a meaning (yet). So you'll have to explain what you mean with that syntax.
    Possibilities:
    - Treat the two independent collections a_first_table and a_second_table as a collection containing elements that are a tuple. Only use the ones with a subscript occuring in both collections. Then check if the tuple (employee_id,manager_id) occurs within that set.
    - Check if employee_id or manager_id occurs within the set a_first_table UNION ALL a_second table. If so, then it's a member.
    You'll have to be more specific, before we start guessing.
    Regards,
    Rob.

  • Loading data into multiple tables - Bulk collect or regular Fetch

    I have a procedure to load data from one source table into eight different destination tables. The 8 tables have some of the columns of the source table with a common key.
    I have run into a couple of problems and have a few questions where I would like to seek advice:
    1.) Procedure with and without the BULK COLLECT clause took the same time for 100,000 records. I thought I would see improvement in performance when I include BULK COLLECT with LIMIT.
    2.) Updating the Load_Flag in source_table happens only for few records and not all. I had expected all records to be updated
    3.) Are there other suggestions to improve the performance? or could you provide links to other posts or articles on the web that will help me improve the code?
    Notes:
    1.) 8 Destination tables have at least 2 Million records each, have multiple indexes and are accessed by application in Production
    2.) There is an initial load of 1 Million rows with a subsequent daily load of 10,000 rows. Daily load will have updates for existing rows (not shown in code structure below)
    The structure of the procedure is as follows
    Declare
    dest_type is table of source_table%ROWTYPE;
    dest_tab dest_type ;
    iCount NUMBER;
    cursor source_cur is select * from source_table FOR UPDATE OF load_flag;
    BEGIN
    OPEN source_cur;
    LOOP
    FETCH source_cur -- BULK COLLECT
    INTO dest_tab -- LIMIT 1000
    EXIT WHEN source_cur%NOTFOUND;
    FOR i in dest_tab.FIRST .. dest_tab.LAST LOOP
    <Insert into app_tab1 values key, col12, col23, col34 ;>
    <Insert into app_tab2 values key, col15, col29, col31 ;>
    <Insert into app_tab3 values key, col52, col93, col56 ;>
    UPDATE source_table SET load_flag = 'Y' WHERE CURRENT OF source_cur ;
    iCount := iCount + 1 ;
    IF iCount = 1000 THEN
    COMMIT ;
    iCount := 0 ;
    END IF;
    END LOOP;
    END LOOP ;
         COMMIT ;
    END ;
    Edited by: user11368240 on Jul 14, 2009 11:08 AM

    Assuming you are on 10g or later, the PL/SQL compiler generates the bulk fetch for you automatically, so your code is the same as (untested):
    DECLARE
        iCount NUMBER;
        CURSOR source_cur is select * from source_table FOR UPDATE OF load_flag;
    BEGIN
        OPEN source_cur;
        FOR r IN source_cur
        LOOP
            <Insert into app_tab1 values key, col12, col23, col34 ;>
            <Insert into app_tab2 values key, col15, col29, col31 ;>
            <Insert into app_tab3 values key, col52, col93, col56 ;>
            UPDATE source_table SET load_flag = 'Y' WHERE CURRENT OF source_cur ;
            iCount := iCount + 1 ;
            IF iCount = 1000 THEN
                COMMIT ;
                iCount := 0 ;
            END IF;
            END LOOP;
        COMMIT ;
    END ;However most of the benefit of bulk fetching would come from using the array with a FORALL expression, which the PL/SQL compiler can't automate for you.
    If you are fetching 1000 rows at a time, purely from a code simplification point of view you could lose iCount and the IF...COMMIT...END IF and just commit each time after looping through the 1000-row array.
    However I'm not sure how committing every 1000 rows helps restartability, even if your real code has a WHERE clause in the cursor so that it only selects rows with load_flag = 'N' or whatever. If you are worried that it will roll back all your hard work on failure, why not just commit in your exception handler?

  • Error in bulk collect into nested table

    I keep getting an error while trying to compile this line:
    fetch c_juros bulk collect into wrk_juros_plano(p_ind_segreg);
    LINE/COL ERROR
    0/0      PLS-00801: internal error [74306]When i put that single line into comments it goes fine. Sure it doesn't do what I want.
    The data structure i use is as follows:
      cursor c_juros(p_ind_segreg in varchar2) is
        select (((power(1 + (i.prc_juros_atuari_ano / 100), 1 / 12) - 1) * 100) / 100) prc_juros_efetiv_mes,
               i.dat_inic_vigenc,
               (nvl(i.dat_fim_vigenc, sysdate) + 1) dat_fim_vigenc,
               i.ind_segreg
          from v_indexador_taxa_atuarial i
         where i.ind_segreg = p_ind_segreg
         order by i.dat_inic_vigenc;
      type t_juros_plano     is table of c_juros%rowtype;
      type t_tab_juros_plano is table of t_juros_plano index by binary_integer;
      wrk_juros_plano t_tab_juros_plano;the code goes like this:
      begin
        if not(wrk_juros_plano.exists(p_ind_segreg))
        then
          if c_juros%isopen
          then
            close c_juros;
          end if;
          open c_juros(p_ind_segreg);
          wrk_juros_plano(p_ind_segreg) := t_juros_plano();
          fetch c_juros bulk collect into wrk_juros_plano(p_ind_segreg);
        end if;
      ...p_ind_segreg is my input parameter, that should be the index of the array.
    The purpose is to create the parameter indexed element if it doesn't already exist, fetching it
    from the cursor, that defines a nested table.
    I tried removing the initialization line to no effect, among other things.

    Ok, I just found out a way around it. It works, but that error is probably a bug, cause workarounds are not really cute.
    I declared a nested table compatible with the element from the associative array:
    wrk_juros t_juros_plano;and chaged that line that was causing the error
    fetch c_juros bulk collect into wrk_juros_plano(p_ind_segreg);for
    fetch c_juros bulk collect into wrk_juros;
    wrk_juros_plano(p_ind_segreg) := wrk_juros;Awesome =\

  • COLLECT into table of VARCHAR2 giving ORA-22814 error

    Hello,
    I am trying to collect a VARCHAR2(5 CHAR) column into a table type of VARCHAR2(5 CHAR) but it gives me the ORA-22814: attribute or element value is larger than specified in type.
    Even if I cast my string to this data type.
    SQL> CREATE OR REPLACE TYPE T_VARCHAR2_5_TAB AS TABLE OF VARCHAR2(5 CHAR);
      2  /
    Type created.
    SQL>
    SQL> DESC site_section_cours;
    Name                                      Null?    Type
    SEQ_SITE_COURS                            NOT NULL NUMBER
    CODE_SESSION                              NOT NULL VARCHAR2(6 CHAR)
    NUMERO_REFERENCE_SECTION_COURS            NOT NULL VARCHAR2(5 CHAR)
    CODE_STATUT_PUBLICATION_PDF               NOT NULL VARCHAR2(2 CHAR)
    CONTROLE_MODIFICATION                     NOT NULL NUMBER
    SEQ_BAREME_NOTES                                   NUMBER
    SQL>
    SQL> SELECT CAST(
      2              COLLECT(
      3              sisc.numero_reference_section_cours
      4              ORDER BY sisc.code_session, sisc.numero_reference_section_cours
      5              )
      6              AS t_varchar2_5_tab
      7           ) AS lov
      8  FROM   site_section_cours sisc;
              COLLECT(
    ERROR at line 2:
    ORA-22814: attribute or element value is larger than specified in type
    SQL>
    SQL> SELECT CAST(
      2              COLLECT(
      3              CAST(
      4                sisc.numero_reference_section_cours AS VARCHAR2 (5 CHAR)
      5              )
      6              ORDER BY sisc.code_session, sisc.numero_reference_section_cours
      7              )
      8              AS t_varchar2_5_tab
      9           ) AS lov
    10  FROM   site_section_cours sisc;
              COLLECT(
    ERROR at line 2:
    ORA-22814: attribute or element value is larger than specified in type What am I missing?
    Thanks
    Bruno

    A new test: try to collect into 10 and 20 char table type.
    Not working with 10 but working with 20.
    SQL> SELECT CAST(
      2              COLLECT(
      3              sisc.numero_reference_section_cours
      4              ORDER BY sisc.code_session, sisc.numero_reference_section_cours
      5              )
      6              AS t_varchar2_10_tab
      7           ) AS lov
      8  FROM   site_section_cours sisc;
              COLLECT(
    ERROR at line 2:
    ORA-22814: attribute or element value is larger than specified in type
    SQL>
    SQL> SELECT CAST(
      2              COLLECT(
      3              sisc.numero_reference_section_cours
      4              ORDER BY sisc.code_session, sisc.numero_reference_section_cours
      5              )
      6              AS t_varchar2_20_tab
      7           ) AS lov
      8  FROM   site_section_cours sisc;
    LOV                                                                            
    T_VARCHAR2_20_TAB('10001', '10003', '10004', '10016', '10018', '10019', '10020',
    '10022', '10025', '10028', '10029', '10030', '10031', '10032', '10039', '10040'
    , '10041', '10003', '21000', '21001', '21002', '21004', '21005', '21006', '21007
    ', '21008', '21009', '21010', '82001', '11972', '11986', '10018', '10019')      Bruno

  • Select values from table%ROWTYPE variable into a cursor

    I have a stored procedure which has an OUT parameter of table1%ROWTYPE.
    In future we might have to add more OUT parameters of table2%ROWTYPE etc. But at any point of time only one will have values.
    So instead of having table%ROWTYPE as OUT parameter, can I send these single row ( with variable values) in a cursor, so that declaration part atleast will not change.
    Is it possible to select values from table%ROWTYPE variable into a cursor.
    cursorOUT IS
    SELECT * FROM varREC;
    where varREC is table.ROWTYPE variable.
    Or which is the better solution in this situation.
    Thanks.

    SQL> var a refcursor
    SQL> declare
      2   bb emp%ROWTYPE;
      3  begin
      4   select * into bb from emp where rownum = 1;
      5   open :a for select bb.ename ename, bb.empno empno from dual;
      6  end;
      7  /
    PL/SQL procedure successfully completed.
    SQL> print a
    ENAME                                 EMPNO
    SMITH                                  7369Rgds.

  • Insert into cursor one at a time

    Hello,
    Is it possible to insert one value per cycle execution on a cursor? For example:
    c_anuncios cursor_anuncios;
    c_result my_result_cursor;
    BEGIN
         LOOP
              EXIT WHEN(c_anunciantes%NOTFOUND);
    --get one comparison value
              FETCH c_anunciantes INTO idAnunciante;          
              SELECT * FROM anuncio a
              --INTO where? how do I record this single value on c_result
              WHERE a.anunciante=id_anunciante;
         END LOOP;
    RETURN c_result;
    There's no way (that I can think of) that I can do "OPEN c_result FOR SELECT"... because I always need to do as many queries as I have elements on the "c_anunciantes" cursor, correct?
    Thanks in advance! :)

    If I understand correctly, you want to gather 5 id numbers in a cursor and then open a cursor using each of those 5 keys and then have access to all of the rows returned by the 5 cursors in the same structure.
    Will this version of your query compile?
    OPEN c_anuncios FOR
    SELECT *
    FROM anuncio a3
    WHERE anunciante IN (SELECT a1.id
    FROM anunciante a1, anuncio a2
    WHERE a2.anunciante = a1.id
    AND a2.palavra_chave = 3
    AND rownum < 6
    HAVING COUNT(a1.id) > 0
    ORDER BY COUNT(a1.id) DESC, SUM(a2.preco) DESC, a1.id ASC
    GROUP BY a1.id)
    ORDER BY a3.preco DESC, a3.num_cliques DESC, a3.id ASC;
    Perhaps the following example would satisfy your requirement. It is certainly not strictly set based but bulk binding will reduce the number of context switches required to run the PL/SQL.
    DECLARE
    -- this procedure will loop through a set of keys to open a set of cursors
    -- and store all rows from those cursors in a collection
    -- the final set of records can be referenced individually by subscript 1..n
    TYPE five_row_typ IS VARRAY(5) OF anunciante.id%TYPE;
    five_rows five_row_typ; -- to store the 5 keys to intermediate datasets
    TYPE anuncio_tbl_typ IS TABLE OF anuncio%ROWTYPE;
    anuncio_tbl anuncio_tbl_typ;
    -- to store the intermediate result set for each of the 5 rows
    total_anuncio_tbl := anuncio_tbl_typ(); -- initialize an empty collection
    --to hold result sets from each of the 5 queries
    CURSOR anunciante_cur(p_chave anunciante.id%TYPE, p_rows NUMBER) IS
    SELECT a1.id
    FROM anunciante a1, anuncio a2
    WHERE a2.anunciante = a1.id
    AND a2.palavra_chave = p_chave
    AND rownum < p_rows + 1
    GROUP BY a1.id
    HAVING COUNT(a1.id) > 0
    ORDER BY COUNT(a1.id) DESC, SUM(a2.preco) DESC, a1.id ASC;
    CURSOR anuncio_cur(p_id anuncio.anunciante%TYPE) IS
    SELECT *
    FROM anuncio a3
    WHERE anunciante = p_id
    ORDER BY a3.preco DESC, a3.num_cliques DESC, a3.id ASC;
    k NUMBER := 0;
    BEGIN
    OPEN anunciante_cur(3, 5);
    FETCH anunciante_cur BULK COLLECT
    INTO five_rows; -- this will get all keys for cursors that follow
    CLOSE anunciante_cur;
    IF five_rows.EXISTS(1)
    THEN
    FOR i IN five_rows.FIRST .. five_rows.LAST
    LOOP
    OPEN anuncio_cur(five_rows(i));-- cursor will be opened p_rows times
    LOOP
    FETCH anuncio_cur BULK COLLECT
    INTO anuncio_tbl;-- this will get all rows from a single cursor in one pass
    -- each of the 5 intemediate result sets will pass through this collection
    IF anuncio_tbl.EXISTS(1)
    THEN
    FOR j IN anuncio_tbl.FIRST .. anuncio_tbl.LAST
    LOOP
    k := k + 1;
    total_anuncio_tbl.EXTEND;
    total_anuncio_tbl(k) := anuncio_tbl(i);
    -- and each element (row) of each of the 5 result sets will end here
    -- whether there is one or many rows in each set
    END LOOP;
    END IF;
    EXIT WHEN anuncio_cur%NOTFOUND OR anuncio_cur%NOTFOUND IS NULL;
    END LOOP;
    CLOSE anuncio_cur;
    END LOOP;
    END IF;
    END;
    Regards,
    Peter

  • Bulk collect into statement

    Hello All,
    I am trying to copy data using database link.
    I am using Oracle 11g on Windows.
    I check data in source table and it exists. When I execute below block it successfully executes but return no data in target database.
    SET SERVEROUTPUT ON
    DECLARE
      TYPE t_bulk_collect_test_1 IS TABLE OF NT_PROP%ROWTYPE;
      l_tab1 t_bulk_collect_test_1;
      CURSOR c_data1 IS
        SELECT *
        FROM NT_PROP@dp_copy;
    BEGIN
      OPEN c_data1;
      LOOP
        FETCH c_data1
        BULK COLLECT INTO l_tab1 LIMIT 10000;
        commit;
      EXIT WHEN l_tab1.count = 0;
      END LOOP;
      CLOSE c_data1;
    END;
    Could someone please let me know what is the eror in this code.
    Thanks in advance

    I think you are expecting BULK INSERT using FORALL. Please see below example.
    See below link also
    http://www.oracle-base.com/articles/9i/bulk-binds-and-record-processing-9i.php#save_exceptions
    DECLARE
      TYPE t_bulk_collect_test_1 IS TABLE OF NT_PROP%ROWTYPE;
      l_tab1 t_bulk_collect_test_1;
      CURSOR c_data1 IS
        SELECT *
        FROM NT_PROP@dp_copy;
        ex_dml_errors EXCEPTION;
         PRAGMA EXCEPTION_INIT(ex_dml_errors, -24381);
    BEGIN
      OPEN c_data1;
      LOOP
        FETCH c_data1
        BULK COLLECT INTO l_tab1 LIMIT 10000;
        BEGIN
          forall i in l_tab1.first..l_tab1.count  save exceptions
           insert into target_tab values l_tab1(i);
        EXCEPTION
              WHEN ex_dml_errors THEN
              l_error_count := SQL%BULK_EXCEPTIONS.count;
              DBMS_OUTPUT.put_line('Number of failures: ' || l_error_count);
          FOR i IN 1 .. l_error_count LOOP
            DBMS_OUTPUT.put_line('Error: ' || i ||
              ' Array Index: ' || SQL%BULK_EXCEPTIONS(i).error_index ||
              ' Message: ' || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
          END LOOP;
        END;
      EXIT WHEN l_tab1.count = 0;
      END LOOP;
      CLOSE c_data1;
    END;
    Cheers,
    Suri

  • Bulk Collect into is storing less no of rows in collection when using LIMIT?

    I have written the following anonymous PL SQL Block. However, the line dbms_output.put_line(total_tckt_col.LAST) gives me output as 366 (in DBMS_OUTPUT is SQL Developer) which is correct when no limit is set. If the limit is set to 100 in the FETCH statement then dbms_output.put_line(total_tckt_col.LAST) gives me 66. What I am doing wrong here?
    DECLARE
       CURSOR cur_total_tckt 
       is
       select  t.ticket_id ticket_id, t.created_date created_date, t.created_by created_by, t.ticket_status ticket_status,
      t.last_changed last_changed, h.created_date closed_date
       from n01.cc_ticket_info t
       inner join n01.cc_ticket_status_history h
       on (t.ticket_id = h.ticket_id)
       where t.last_changed >= '6/28/2012 17:28:59' and t.last_changed < (sysdate + interval '1' day);
      type total_tckt_colcn
       is
       TABLE OF cur_total_tckt%rowtype;
      total_tckt_col total_tckt_colcn;
      total_coach_col total_tckt_colcn;
       begin
      total_tckt_col  := total_tckt_colcn ();
      total_coach_col := total_tckt_colcn ();
       OPEN cur_total_tckt;
      loop
       fetch cur_total_tckt bulk collect into total_tckt_col;
    -- fetch cur_total_tckt bulk collect into total_tckt_col limit 100;
       EXIT
       WHEN (cur_total_tckt%NOTFOUND);
       END LOOP ;
       CLOSE cur_total_tckt;  
      dbms_output.put_line(total_tckt_col.LAST); 
       FOR i IN total_tckt_col.first..total_tckt_col.last
      LOOP
      dbms_output.put_line(i);
       END LOOP;
       end;

    Ishan wrote:
    Here is modified version of your code on standard EMP table in scott schema.
    Did you test it? All you demonstrate is last batch has 4 rows. But you print it outsite the loop. This way if last batch is incomplete (has less than limit rows) your loop doesn't process last batch. Assume you want to print enames:
    DECLARE
        CURSOR cur_total_tckt
          IS
            select  ename
              from  emp; -- I have a total of 14 records in this table
            type total_tckt_colcn
              is
                TABLE OF cur_total_tckt%rowtype;
            total_tckt_col total_tckt_colcn;
    BEGIN
        total_tckt_col  := total_tckt_colcn ();
        OPEN cur_total_tckt;
        LOOP
          fetch cur_total_tckt bulk collect into total_tckt_col limit 5;
          EXIT WHEN cur_total_tckt%NOTFOUND;
          FOR v_i IN 1..total_tckt_col.count LOOP
            dbms_output.put_line(total_tckt_col(v_i).ename);
          END LOOP;
        END LOOP ;
        CLOSE cur_total_tckt;
    END;
    SMITH
    ALLEN
    WARD
    JONES
    MARTIN
    BLAKE
    CLARK
    SCOTT
    KING
    TURNER
    PL/SQL procedure successfully completed.
    SQL>
    As you can see, it didn't print last batch. Why? Because NOTFOUND is set to true if exact number of rows you asked to fetch was not fetched. So last batch has 4 rows while code asks to fetch 5. Therefore, NOTFOUND is set to true and code exits before processing that last batch. So you have to repeat processing code again outside the loop:
    DECLARE
        CURSOR cur_total_tckt
          IS
            select  ename
              from  emp; -- I have a total of 14 records in this table
            type total_tckt_colcn
              is
                TABLE OF cur_total_tckt%rowtype;
            total_tckt_col total_tckt_colcn;
    BEGIN
        total_tckt_col  := total_tckt_colcn ();
        OPEN cur_total_tckt;
        LOOP
          fetch cur_total_tckt bulk collect into total_tckt_col limit 5;
          EXIT WHEN cur_total_tckt%NOTFOUND;
          FOR v_i IN 1..total_tckt_col.count LOOP
            dbms_output.put_line(total_tckt_col(v_i).ename);
          END LOOP;
        END LOOP ;
        FOR v_i IN 1..total_tckt_col.count LOOP
          dbms_output.put_line(total_tckt_col(v_i).ename);
        END LOOP;
        CLOSE cur_total_tckt;
    END;
    SMITH
    ALLEN
    WARD
    JONES
    MARTIN
    BLAKE
    CLARK
    SCOTT
    KING
    TURNER
    ADAMS
    JAMES
    FORD
    MILLER
    PL/SQL procedure successfully completed.
    SQL>
    But you must agree repeating that processing code twice isn't best solution. When using BULK COLLECT LIMIT we should exit not by NOTFOUND but rather by collection.count = 0:
    DECLARE
        CURSOR cur_total_tckt
          IS
            select  ename
              from  emp; -- I have a total of 14 records in this table
            type total_tckt_colcn
              is
                TABLE OF cur_total_tckt%rowtype;
            total_tckt_col total_tckt_colcn;
    BEGIN
        total_tckt_col  := total_tckt_colcn ();
        OPEN cur_total_tckt;
        LOOP
          fetch cur_total_tckt bulk collect into total_tckt_col limit 6;
          EXIT WHEN total_tckt_col.count = 0;
          FOR v_i IN 1..total_tckt_col.count LOOP
            dbms_output.put_line(total_tckt_col(v_i).ename);
          END LOOP;
        END LOOP ;
        CLOSE cur_total_tckt;
    END;
    SMITH
    ALLEN
    WARD
    JONES
    MARTIN
    BLAKE
    CLARK
    SCOTT
    KING
    TURNER
    ADAMS
    JAMES
    FORD
    MILLER
    PL/SQL procedure successfully completed.
    SQL>
    SY.

Maybe you are looking for