Problem in Bulk collect

Hi ,
I have declared a cursor with bulk collect. I have to insert only 2 columns values from tableA to TableB. The number of columns in tableA and TableB are not equal.
DECLARE
CURSOR c1                                    
IS
SELECT COLUMN1,COLUMN2,COLUMN3,COLUMN5 FROM TABLEA WHERE COLUMNS1='XXXXXXXX';
TYPE Cust_tab IS TABLE OF C1%ROWTYPE;
Custs Cust_tab;
BEGIN
     OPEN c1;
LOOP
     FETCH c1 BULK COLLECT INTO Custs LIMIT 100;
EXIT WHEN c1%NOTFOUND;               
     END LOOP;
     FORALL i IN 1 .. Custs.COUNT
SAVE EXCEPTIONS
INSERT into TABLEB(COL1,COL2,COL3,COL5) VALUES (Custs(i).COLUMN1,Custs(i).COLUMN2,Custs(i).COLUMN3,Custs(i).COLUMN5);
END ;
Iam getting an error as
ERROR at line 16:
ORA-06550: line 16, column 66:
PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND
table of records
ORA-06550: line 16, column 66:
PLS-00382: expression is of wrong type
ORA-06550: line 16, column 88:
PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND
table of records
ORA-06550: line 16, column 88:
PLS-00382: expression is of wrong type
ORA-06550: line 16, column 107:
PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND
table of records
ORA-06550: line 16, column 107:
PLS-00382: expression is of wrong type
ORA-06550: line 16, column 124:
PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND
table of records
ORA-06550: line 16, column 124:
PLS-00382: expression is of wrong type
ORA-06550: line 16, column 66:
PL/SQL: ORA-22806: not an object or REF
ORA-06550: line 16, column 14:
PL/SQL: SQL Statement ignored.
Please let me know how to get out of the error.

INSERT into TABLEB(COL1,COL2,COL3,COL5)
SELECT COLUMN1,COLUMN2,COLUMN3,COLUMN5 FROM TABLEA WHERE COLUMNS1='XXXXXXXX';
works like a charm. Moreover: it SCALES!!
There is no reason in this case to use BULK COLLECT.
You should only use PL/SQL if you can't do it using SQL.
You can do it using SQL: you should use SQL.
Other than that: just read the error message, realize you can't directly use a collection involved in a fetch, just set up an extra collection and assign the old collection to the new.
The code is wrong anyway, as it doesn't allow for more than one fetch.
Sybrand Bakker
Senior Oracle DBA

Similar Messages

  • Having problem using BULK COLLECT - FORALL

    Hi,
    I'm facing a problem while setting a table type value before inserting into a table using FORALL.
    My concern is that i'm unable to generate the values in FOR LOOP, as by using dbms_output.put_line i observed that after 100 rows execution the process exits giving error as
    ORA-22160: element at index [1] does not exist
    ORA-06512: at "XYZ", line 568
    ORA-06512: at line 2
    I need to use the values stored in FOR LOOP in the same order for insertion in table TEMP using FOR ALL;
    I'm guessing that i'm using the wrong technique for storing values in FOR LOOP.
    Below given is my SP structure.
    Any suggestion would be hepful.
    Thanks!!
    create or replace procedure XYZ
    cursor cur is
    select A,B,C,D from ABCD; ---expecting 40,000 row fetch
    type t_A is table of ABCD.A%type index by pls_integer;
    type t_B is table of ABCD.B%type index by pls_integer;
    type t_C is table of ABCD.C%type index by pls_integer;
    type t_D is table of ABCD.D%type index by pls_integer;
    v_A t_A;
    v_B t_B;
    v_C t_C;
    v_D t_D;
    type t_E is table of VARCHAR2(100);
    type t_F is table of VARCHAR2(100);
    v_E t_E := t_E();
    v_F t_F := t_F();
    begin
    open cur;
    loop
    fetch cur BULK COLLECT INTO v_A,v_B,v_C,v_D limit 100;
    for i in 1 .. v_A.count loop
    v_E.extend(i);
    select 1111 into v_E(i) from dual;
    v_F.extend(i);
    v_F(i) := 'Hi !!';
    ----calculating v_E(i) and v_F(i) here----
    end loop;
    forall in i in 1 .. v_A.count
    insert into table TEMP values (v_E(i), v_F(i));
    exit when cur%NOTFOUND;
    end loop;
    close cur;
    end;
    BANNER
    Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
    PL/SQL Release 10.2.0.4.0 - Production
    CORE     10.2.0.4.0     Production
    TNS for HPUX: Version 10.2.0.4.0 - Production
    NLSRTL Version 10.2.0.4.0 - Production
    -------

    The problem is that inside the IF ELSIF blocks i need to query various tables..As I thought. But why did you concentrate on BULK COLLECT - FORALL?
    The cursor whereas does take more time to execute.More time then?
    We have join of two tables have 18,00,000(normal table) and >17,92,2067(MView) records, having inidex on one the join column.
    After joining these two and adding the filter conditions i'm having around >40,000 >rows.? You have a cursor row. And then inside the loop you have a query which returns 40'000 rows? What do you do with that data?
    Is the query you show running INSIDE the loop?
    I guess you still talk about the LOOP query and your are unhappy that it is not taking an index?
    1. The loop is NOT the problem. It's the "... i need to query various tables"
    2. ORACLE is ok when it's NOT taking the index. That is faster!!
    3. If you add code and execution plans, please add tags. Otherwise it's unreadable.
    Try to merge your LOOP query with the "various tables" and make ONE query out of 40000*various ;-)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               

  • Problem with BULK COLLECT with million rows - Oracle 9.0.1.4

    We have a requirement where are supposed to load 58 millions of rows into a FACT Table in our DATA WAREHOUSE. We initially planned to use Oracle Warehouse Builder but due to performance reasons, decided to write custom code. We wrote a custome procedure which opens a simple cursor and reads all the 58 million rows from the SOURCE Table and in a loop processes the rows and inserts the records into a TARGET Table. The logic works fine but it took 20hrs to complete the load.
    We then tried to leverage the BULK COLLECT and FORALL and PARALLEL options and modified our PL/SQL code completely to reflect these. Our code looks very simple.
    1. We declared PL/SQL BINARY_INDEXed Tables to store the data in memory.
    2. We used BULK COLLECT into FETCH the data.
    3. We used FORALL statement while inserting the data.
    We did not introduce any of our transformation logic yet.
    We tried with the 600,000 records first and it completed in 1 min and 29 sec with no problems. We then doubled the no. of rows to 1.2 million and the program crashed with the following error:
    ERROR at line 1:
    ORA-04030: out of process memory when trying to allocate 16408 bytes (koh-kghu
    call ,pmucalm coll)
    ORA-06512: at "VVA.BULKLOAD", line 66
    ORA-06512: at line 1
    We got the same error even with 1 million rows.
    We do have the following configuration:
    SGA - 8.2 GB
    PGA
    - Aggregate Target - 3GB
    - Current Allocated - 439444KB (439 MB)
    - Maximum allocated - 2695753 KB (2.6 GB)
    Temp Table Space - 60.9 GB (Total)
    - 20 GB (Available approximately)
    I think we do have more than enough memory to process the 1 million rows!!
    Also, some times the same program results in the following error:
    SQL> exec bulkload
    BEGIN bulkload; END;
    ERROR at line 1:
    ORA-03113: end-of-file on communication channel
    We did not even attempt the full load. Also, we are not using the PARALLEL option yet.
    Are we hitting any bug here? Or PL/SQL is not capable of mass loads? I would appreciate any thoughts on this?
    Thanks,
    Haranadh
    Following is the code:
    set echo off
    set timing on
    create or replace procedure bulkload as
    -- SOURCE --
    TYPE src_cpd_dt IS TABLE OF ima_ama_acct.cpd_dt%TYPE;
    TYPE src_acqr_ctry_cd IS TABLE OF ima_ama_acct.acqr_ctry_cd%TYPE;
    TYPE src_acqr_pcr_ctry_cd IS TABLE OF ima_ama_acct.acqr_pcr_ctry_cd%TYPE;
    TYPE src_issr_bin IS TABLE OF ima_ama_acct.issr_bin%TYPE;
    TYPE src_mrch_locn_ref_id IS TABLE OF ima_ama_acct.mrch_locn_ref_id%TYPE;
    TYPE src_ntwrk_id IS TABLE OF ima_ama_acct.ntwrk_id%TYPE;
    TYPE src_stip_advc_cd IS TABLE OF ima_ama_acct.stip_advc_cd%TYPE;
    TYPE src_authn_resp_cd IS TABLE OF ima_ama_acct.authn_resp_cd%TYPE;
    TYPE src_authn_actvy_cd IS TABLE OF ima_ama_acct.authn_actvy_cd%TYPE;
    TYPE src_resp_tm_id IS TABLE OF ima_ama_acct.resp_tm_id%TYPE;
    TYPE src_mrch_ref_id IS TABLE OF ima_ama_acct.mrch_ref_id%TYPE;
    TYPE src_issr_pcr IS TABLE OF ima_ama_acct.issr_pcr%TYPE;
    TYPE src_issr_ctry_cd IS TABLE OF ima_ama_acct.issr_ctry_cd%TYPE;
    TYPE src_acct_num IS TABLE OF ima_ama_acct.acct_num%TYPE;
    TYPE src_tran_cnt IS TABLE OF ima_ama_acct.tran_cnt%TYPE;
    TYPE src_usd_tran_amt IS TABLE OF ima_ama_acct.usd_tran_amt%TYPE;
    src_cpd_dt_array src_cpd_dt;
    src_acqr_ctry_cd_array      src_acqr_ctry_cd;
    src_acqr_pcr_ctry_cd_array     src_acqr_pcr_ctry_cd;
    src_issr_bin_array      src_issr_bin;
    src_mrch_locn_ref_id_array     src_mrch_locn_ref_id;
    src_ntwrk_id_array      src_ntwrk_id;
    src_stip_advc_cd_array      src_stip_advc_cd;
    src_authn_resp_cd_array      src_authn_resp_cd;
    src_authn_actvy_cd_array      src_authn_actvy_cd;
    src_resp_tm_id_array      src_resp_tm_id;
    src_mrch_ref_id_array      src_mrch_ref_id;
    src_issr_pcr_array      src_issr_pcr;
    src_issr_ctry_cd_array      src_issr_ctry_cd;
    src_acct_num_array      src_acct_num;
    src_tran_cnt_array      src_tran_cnt;
    src_usd_tran_amt_array      src_usd_tran_amt;
    j number := 1;
    CURSOR c1 IS
    SELECT
    cpd_dt,
    acqr_ctry_cd ,
    acqr_pcr_ctry_cd,
    issr_bin,
    mrch_locn_ref_id,
    ntwrk_id,
    stip_advc_cd,
    authn_resp_cd,
    authn_actvy_cd,
    resp_tm_id,
    mrch_ref_id,
    issr_pcr,
    issr_ctry_cd,
    acct_num,
    tran_cnt,
    usd_tran_amt
    FROM ima_ama_acct ima_ama_acct
    ORDER BY issr_bin;
    BEGIN
    OPEN c1;
    FETCH c1 bulk collect into
    src_cpd_dt_array ,
    src_acqr_ctry_cd_array ,
    src_acqr_pcr_ctry_cd_array,
    src_issr_bin_array ,
    src_mrch_locn_ref_id_array,
    src_ntwrk_id_array ,
    src_stip_advc_cd_array ,
    src_authn_resp_cd_array ,
    src_authn_actvy_cd_array ,
    src_resp_tm_id_array ,
    src_mrch_ref_id_array ,
    src_issr_pcr_array ,
    src_issr_ctry_cd_array ,
    src_acct_num_array ,
    src_tran_cnt_array ,
    src_usd_tran_amt_array ;
    CLOSE C1;
    FORALL j in 1 .. src_cpd_dt_array.count
    INSERT INTO ima_dly_acct (
         CPD_DT,
         ACQR_CTRY_CD,
         ACQR_TIER_CD,
         ACQR_PCR_CTRY_CD,
         ACQR_PCR_TIER_CD,
         ISSR_BIN,
         OWNR_BUS_ID,
         USER_BUS_ID,
         MRCH_LOCN_REF_ID,
         NTWRK_ID,
         STIP_ADVC_CD,
         AUTHN_RESP_CD,
         AUTHN_ACTVY_CD,
         RESP_TM_ID,
         PROD_REF_ID,
         MRCH_REF_ID,
         ISSR_PCR,
         ISSR_CTRY_CD,
         ACCT_NUM,
         TRAN_CNT,
         USD_TRAN_AMT)
         VALUES (
         src_cpd_dt_array(j),
         src_acqr_ctry_cd_array(j),
         null,
         src_acqr_pcr_ctry_cd_array(j),
              null,
              src_issr_bin_array(j),
              null,
              null,
              src_mrch_locn_ref_id_array(j),
              src_ntwrk_id_array(j),
              src_stip_advc_cd_array(j),
              src_authn_resp_cd_array(j),
              src_authn_actvy_cd_array(j),
              src_resp_tm_id_array(j),
              null,
              src_mrch_ref_id_array(j),
              src_issr_pcr_array(j),
              src_issr_ctry_cd_array(j),
              src_acct_num_array(j),
              src_tran_cnt_array(j),
              src_usd_tran_amt_array(j));
    COMMIT;
    END bulkload;
    SHOW ERRORS
    -----------------------------------------------------------------------------

    do you have a unique key available in the rows you are fetching?
    It seems a cursor with 20 million rows that is as wide as all the columnsyou want to work with is a lot of memory for the server to use at once. You may be able to do this with parallel processing (dop over 8) and a lot of memory for the warehouse box (and the box you are extracting data from)...but is this the most efficient (and thereby fastest) way to do it?
    What if you used a cursor to select a unique key only, and then during the cursor loop fetch each record, transform it, and insert it into the target?
    Its a different way to do a lot at once, but it cuts down on the overall memory overhead for the process.
    I know this isnt as elegant as a single insert to do it all at once, but sometimes trimming a process down so it takes less resources at any given moment is much faster than trying to do the whole thing at once.
    My solution is probably biased by transaction systems, so I would be interested in what the data warehouse community thinks of this.
    For example:
    source table my_transactions (tx_seq_id number, tx_fact1 varchar2(10), tx_fact2 varchar2(20), tx_fact3 number, ...)
    select a cursor of tx_seq_id only (even at 20 million rows this is not much)
    you could then either use a for loop or even bulk collect into a plsql collection or table
    then process individually like this:
    procedure process_a_tx(p_tx_seq_id in number)
    is
    rTX my_transactions%rowtype;
    begin
    select * into rTX from my_transactions where tx_seq_id = p_tx_seq_id;
    --modify values as needed
    insert into my_target(a, b, c) values (rtx.fact_1, rtx.fact2, rtx.fact3);
    commit;
    exception
    when others
    rollback;
    --write to a log or raise and exception
    end process_a_tx;
    procedure collect_tx
    is
    cursor tx is
    select tx_seq_id from my_transactions;
    begin
    for rTx in cTx loop
    process_a_tx(rtx.tx_seq_id);
    end loop;
    end collect_tx;

  • Problem with Bulk Collect ... FORALL

    I've written following code to bulk collect records from a cursor into a collection and insert it into a table using FORALL loop
    OPEN x;
        LOOP
          FETCH x BULK COLLECT INTO v_collection LIMIT 1000;
          FORALL i IN 1..v_collection.count
              INSERT INTO tablename(column1, column2) VALUES(v_collection(i).val1, v_collection(i).val2);
              COMMIT;
          EXIT WHEN x%NOTFOUND;
        END LOOP;I have verified that query which is executed by cursor returns records but when my procedure is executed the insert statement inside the FORALL loop never executes. Am I missing something over here?
    Regards,
    Fahad

    Yes, the cursor is returning a row.
    I've found the solution myself. There was a trigger which was deleting data on commit. Due to this, the records were not inserting.

  • Using bulk collect and for all to solve a problem

    Hi All
    I have a following problem.
    Please forgive me if its a stupid question :-) im learning.
    1: Data in a staging table xx_staging_table
    2: two Target table t1, t2 where some columns from xx_staging_table are inserted into
    Some of the columns from the staging table data are checked for valid entries and then some columns from that row will be loaded into the two target tables.
    The two target tables use different set of columns from the staging table
    When I had a thousand records there was no problem with a direct insert but it seems we will now have half a million records.
    This has slowed down the process considerably.
    My question is
    Can I use the bulk collect and for all functionality to get specific columns from a staging table, then validate the row using those columns
    and then use a bulk insert to load the data into a specific table.?
    So code would be like
    get_staging_data cursor will have all the columns i need from the staging table
    cursor get_staging_data
    is select * from xx_staging_table (about 500000) records
    Use bulk collect to load about 10000 or so records into a plsql table
    and then do a bulk insert like this
    CREATE TABLE t1 AS SELECT * FROM all_objects WHERE 1 = 2;
    CREATE OR REPLACE PROCEDURE test_proc (p_array_size IN PLS_INTEGER DEFAULT 100)
    IS
    TYPE ARRAY IS TABLE OF all_objects%ROWTYPE;
    l_data ARRAY;
    CURSOR c IS SELECT * FROM all_objects;
    BEGIN
    OPEN c;
    LOOP
    FETCH c BULK COLLECT INTO l_data LIMIT p_array_size;
    FORALL i IN 1..l_data.COUNT
    INSERT INTO t1 VALUES l_data(i);
    EXIT WHEN c%NOTFOUND;
    END LOOP;
    CLOSE c;
    END test_proc;
    In the above example t1 and the cursor have the same number of columns
    In my case the columns in the cursor loop are a small subset of the columns of table t1
    so can i use a forall to load that subset into the table t1? How does that work?
    Thanks
    J

    user7348303 wrote:
    checking if the value is valid and theres also some conditional processing rules ( such as if the value is a certain value no inserts are needed)
    which are a little more complex than I can put in a simpleWell, if the processing is too complex (and conditional) to be done in SQL, then doing that in PL/SQL is justified... but will be slower as you are now introducing an additional layer. Data now needs to travel between the SQL layer and PL/SQL layer. This is slower.
    PL/SQL is inherently serialised - and this also effects performance and scalability. PL/SQL cannot be parallelised by Oracle in an automated fashion. SQL processes can.
    To put in in simple terms. You create PL/SQL procedure Foo that processes SQL cursor and you execute that proc. Oracle cannot run multiple parallel copies of Foo. It perhaps can parallelise that SQL cursor that Foo uses - but not Foo itself.
    However, if Foo is called by the SQL engine it can run in parallel - as the SQL process calling Foo is running in parallel. So if you make Foo a pipeline table function (written in PL/SQL), and you design and code it as a thread-safe/parallel enabled function, it can be callled and used and executed in parallel, by the SQL engine.
    So moving your PL/SQL code into a parallel enabled pipeline function written in PL/SQL, and using that function via parallel SQL, can increase performance over running that same basic PL/SQL processing as a serialised process.
    This is of course assuming that the processing that needs to be done using PL/SQL code, can be designed and coded for parallel processing in this fashion.

  • Bulk Collect Limiting data problem

    Hi all,
    i am using a cursor for migrating data form one table to another.
    i say:
    fetch c_mycur bulk collect into r_myrow limit 10000;
    exit when c_mycur%notfound;
    forall i in r_myrow.first .. r_myrow.last
    insert into table2 values r_myrow(i);
    But there is a missout point that:
    Table1 has 400234 data but it copies 400000 to the table2.
    I want it to do full copy.How can i correct this???
    Thanks...

    Dear all..
    Sory i just want to share about bulk collect limiting problem, because i also get the same problem when using it. Actually before I just want to check the performance between bulk collect with explicit cursor and implicit cursor. below is my testing :
    SQL> ed
    Wrote file afiedt.buf
    1 DECLARE
    2 CURSOR c_server IS
    3 SELECT * FROM TRAN_DATA;
    4 TYPE transerver IS TABLE OF c_server%ROWTYPE;
    5 cur_server transerver;
    6 TYPE mytran IS TABLE OF TRAN_DATA%ROWTYPE;
    7 c_tran mytran;
    8 START_TIME NUMBER;
    9 END_TIME NUMBER;
    10 L_count NUMBER;
    11 BEGIN
    12 EXECUTE IMMEDIATE 'TRUNCATE TABLE TRAN_DATA_SERVERS';
    13 START_TIME := DBMS_UTILITY.GET_tIME;
    14 OPEN c_server;
    15 LOOP
    16 FETCH c_server BULK COLLECT INTO cur_server LIMIT 100;
    [b] 17 EXIT WHEN c_server%NOTFOUND;
    18 FORALL i IN cur_server.FIRST..cur_server.LAST
    19 INSERT INTO tran_data_servers VALUES cur_Server(i);
    20 END LOOP;
    21 CLOSE c_server;
    22 SELECT count(*) INTO l_count FROM tran_data_servers;
    23 DBMS_OUTPUT.PUT_LINE('row processing = '||L_cOUNT);
    24 END_TIME := DBMS_UTILITY.GET_tIME;
    25 DBMS_OUTPUT.PUT_LINE('TIME FOR CURSOR BULK FOR ALL = '||TO_CHAR(END_TIME-START_TIME));
    26 EXECUTE IMMEDIATE 'TRUNCATE TABLE array_TRAN_DATA';
    27 START_TIME := DBMS_UTILITY.GET_tIME;
    28 SELECT * BULK COLLECT INTO c_tran FROM TRAN_DATA;
    29 FORALL i IN c_tran.FIRST..c_tran.LAST
    30 INSERT INTO array_tran_data VALUES c_tran(i);
    31 END_TIME := DBMS_UTILITY.GET_tIME;
    32 L_count:= null;
    33 SELECT count(*) INTO l_count FROM array_tran_data;
    34 DBMS_OUTPUT.PUT_LINE('row processing = '||L_cOUNT);
    35 DBMS_OUTPUT.PUT_LINE('select into BULK FOR ALL = '||TO_CHAR(END_TIME-START_TIME));
    36* END;
    37 /
    row processing = 287400
    TIME FOR CURSOR BULK FOR ALL = 789
    row processing = 287417
    select into BULK FOR ALL = 811
    PL/SQL procedure successfully completed.
    SQL> ed
    Wrote file afiedt.buf
    1 DECLARE
    2 CURSOR c_server IS
    3 SELECT * FROM TRAN_DATA;
    4 TYPE transerver IS TABLE OF c_server%ROWTYPE;
    5 cur_server transerver;
    6 TYPE mytran IS TABLE OF TRAN_DATA%ROWTYPE;
    7 c_tran mytran;
    8 START_TIME NUMBER;
    9 END_TIME NUMBER;
    10 L_count NUMBER;
    11 BEGIN
    12 EXECUTE IMMEDIATE 'TRUNCATE TABLE TRAN_DATA_SERVERS';
    13 START_TIME := DBMS_UTILITY.GET_tIME;
    14 OPEN c_server;
    15 LOOP
    16 FETCH c_server BULK COLLECT INTO cur_server LIMIT 100;
    17 FORALL i IN cur_server.FIRST..cur_server.LAST
    18 INSERT INTO tran_data_servers VALUES cur_Server(i);
    [b]19 EXIT WHEN c_server%NOTFOUND;
    20 END LOOP;
    21 CLOSE c_server;
    22 SELECT count(*) INTO l_count FROM tran_data_servers;
    23 DBMS_OUTPUT.PUT_LINE('row processing = '||L_cOUNT);
    24 END_TIME := DBMS_UTILITY.GET_tIME;
    25 DBMS_OUTPUT.PUT_LINE('TIME FOR CURSOR BULK FOR ALL = '||TO_CHAR(END_TIME-START_TIME));
    26 EXECUTE IMMEDIATE 'TRUNCATE TABLE array_TRAN_DATA';
    27 START_TIME := DBMS_UTILITY.GET_tIME;
    28 SELECT * BULK COLLECT INTO c_tran FROM TRAN_DATA;
    29 FORALL i IN c_tran.FIRST..c_tran.LAST
    30 INSERT INTO array_tran_data VALUES c_tran(i);
    31 END_TIME := DBMS_UTILITY.GET_tIME;
    32 L_count:= null;
    33 SELECT count(*) INTO l_count FROM array_tran_data;
    34 DBMS_OUTPUT.PUT_LINE('row processing = '||L_cOUNT);
    35 DBMS_OUTPUT.PUT_LINE('select into BULK FOR ALL = '||TO_CHAR(END_TIME-START_TIME));
    36* END;
    SQL> /
    row processing = 287417
    TIME FOR CURSOR BULK FOR ALL = 558
    row processing = 287417
    select into BULK FOR ALL = 624
    PL/SQL procedure successfully completed.
    As you can see if we put the EXIT WHEN c_server%NOTFOUND; before the forall statement then not all the row will processing, but if we put EXIT WHEN c_server%NOTFOUND; after the forall statement it's will processing all rows. So maybe the solutions just put the EXIT WHEN c_server%NOTFOUND; after the forall statement. As you can see also there's the different bulk collect with implicit and explicit cursor, i think using explicit with limit will be more faster.
    Thank you
    Thanks

  • Problem with Assocaite Array & Bulk Collect

    Hi All,
    I encountered compilation error when I executed the following block. Improper reference of elements in associate array ( at var.party_name (r) in the code ) is giving problems. Please help me in correcting it.
    Regards,
    Kashif
    DECLARE
       TYPE record1 IS RECORD (
          party_name           racsf_cust_pre_staging_int.party_name%TYPE,
          shipping_address_1   racsf_cust_pre_staging_int.shipping_address_1%TYPE,
          cust_acct_site_id    racsf_cust_pre_staging_int.cust_acct_site_id%TYPE
       TYPE typ_cust_pre_staging_int IS TABLE OF record1
          INDEX BY BINARY_INTEGER;
       var   typ_cust_pre_staging_int;
    BEGIN
       SELECT party_name,
              shipping_address_1,
              cust_acct_site_id
       BULK COLLECT INTO var
         FROM racsf_cust_pre_staging_int;
       FORALL r IN var.FIRST .. var.LAST
          UPDATE racsf_cust_pre_staging_int
             SET party_name = var.party_name (r),
                 shipping_address_1 = var.shipping_address_1 (r)
           WHERE cust_acct_site_id = var.cust_acct_site_id (r);
    END;

    I thought if i collect BULK collect and update all records, it will avoid context switching b/w SQL & PL/SQL engines and decrease the execution time.Right idea to get rid of FOR loop
    But if you can do in a single SQL statement and avoid collections that is best.
    How many records in the collection?
    Use LIMIT if necessary as already mentioned - 500 to 1000 might be a sensible limit
    I believe this is representative of your current error (I'm using insert and new table for simplicity):
    SQL> create table t
      2  (col1 number
      3  ,col2 number);
    Table created.
    SQL>
    SQL> declare
      2   cursor c_t
      3   is
      4     select rownum col1, rownum col2
      5     from   dual
      6     connect by rownum <= 10000;
      7   type tt_t is table of t%rowtype index by pls_integer;
      8   v_t  tt_t;
      9  begin
    10    open c_t;
    11    loop
    12        fetch c_t bulk collect into v_t limit 1000;
    13        exit when v_t.count = 0;
    14        forall i in 1 .. v_t.count
    15          insert into t
    16          (col1,col2)
    17          values
    18          (v_t.col1(i), v_t.col2(i));
    19    end loop;
    20  end;
    21  /
            (v_t.col1(i), v_t.col2(i));
    ERROR at line 18:
    ORA-06550: line 18, column 14:
    PLS-00302: component 'COL1' must be declared
    ORA-06550: line 18, column 27:
    PLS-00302: component 'COL2' must be declared
    ORA-06550: line 18, column 27:
    PLS-00302: component 'COL2' must be declared
    ORA-06550: line 18, column 23:
    PL/SQL: ORA-00904: "V_T"."COL2": invalid identifier
    ORA-06550: line 15, column 9:
    PL/SQL: SQL Statement ignored
    SQL> If you change to the following you will run into PLS-00436 - a right PITA.
    SQL> declare
      2   cursor c_t
      3   is
      4     select rownum col1, rownum col2
      5     from   dual
      6     connect by rownum <= 10000;
      7   type tt_t is table of t%rowtype index by pls_integer;
      8   v_t  tt_t;
      9  begin
    10    open c_t;
    11    loop
    12        fetch c_t bulk collect into v_t limit 1000;
    13        exit when v_t.count = 0;
    14        forall i in 1 .. v_t.count
    15          insert into t
    16          (col1,col2)
    17          values
    18          (v_t(i).col1, v_t(i).col2);
    19    end loop;
    20  end;
    21  /
            (v_t(i).col1, v_t(i).col2);
    ERROR at line 18:
    ORA-06550: line 18, column 10:
    PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND table of records
    ORA-06550: line 18, column 10:
    PLS-00382: expression is of wrong type
    ORA-06550: line 18, column 23:
    PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND table of records
    ORA-06550: line 18, column 23:
    PLS-00382: expression is of wrong type
    ORA-06550: line 18, column 10:
    PL/SQL: ORA-22806: not an object or REF
    ORA-06550: line 15, column 9:
    PL/SQL: SQL Statement ignoredFor workarounds other than using single arrays per column, see Adrian Billington's article here:
    http://www.oracle-developer.net/display.php?id=410
    Easiest solution is one array per column:
    SQL> declare
      2   cursor c_t
      3   is
      4     select rownum col1, rownum col2
      5     from   dual
      6     connect by rownum <= 10000;
      7   type tt_t1 is table of t.col1%type index by pls_integer;
      8   type tt_t2 is table of t.col2%type index by pls_integer;
      9   v_t1  tt_t1;
    10   v_t2  tt_t2;
    11  begin
    12    open c_t;
    13    loop
    14        fetch c_t bulk collect into v_t1,v_t2 limit 1000;
    15        exit when v_t1.count = 0;
    16        forall i in 1 .. v_t1.count
    17          insert into t
    18          (col1,col2)
    19          values
    20          (v_t1(i), v_t2(i));
    21    end loop;
    22  end;
    23  /
    PL/SQL procedure successfully completed.
    SQL> Best solution would have been a single piece of SQL:
    SQL>    insert into t
      2     (col1,col2)
      3     select rownum col1, rownum col2
      4     from   dual
      5     connect by rownum <= 10000
      6  /
    10000 rows created.
    SQL>

  • PROBLEM With my procedure (BULK COLLECT)

    This s my code
    CREATE OR REPLACE PROCEDURE BULK_COLLECT_tipo_per IS
    TYPE T_ARRAY_TAB IS TABLE OF tipo_per_22%ROWTYPE
    INDEX BY PLS_INTEGER;
    T_ARRAY_COL T_ARRAY_TAB;
    cursor CUR is
    SELECT CIF_ID,
    MAX(C1) CL_ORI,
    MAX(C2) F_COTI,
    MAX(C3) EX_ORI,
    MAX(C4) F_EX_MAX
    FROM (SELECT /*+ PARALLEL(C,8) */
    C.CIF_ID,
    MAX(NVL(DECODE(CANAL_ORIGEN, 'INDIRECTO', '1'),
    DECODE(CANAL_ORIGEN, 'DIRECTO', '0'))) C1,
    NULL C2,
    NULL C3,
    NULL C4
    FROM DBM_PHOTO_POLARIS C
    GROUP BY CIF_ID
    UNION
    SELECT DISTINCT /*+ PARALLEL(C,8) */ C.ID CIF_ID,
    NULL C1,
    MAX(FECHA_PRESU) C2,
    NULL C3,
    NULL C4
    FROM EMI_PRESU_SOLIC@POLCP C
    WHERE FECHA_PRESU > SYSDATE - 730
    GROUP BY ID
    UNION
    SELECT /*+ PARALLEL(C,8)*/
    C.CIF_ID,
    NULL C1,
    NULL C2,
    MAX(NVL(DECODE(MAX_BAJA_INDIRECTO, 'S', '1'),
    DECODE(MAX_BAJA_DIRECTO, 'S', '0'))) C3,
    MAX(FECHA_PROCESO) C4
    FROM MX_EX_CLIENTES_5AÑOS C
    WHERE FECHA_PROCESO > SYSDATE - 1825
    AND (MAX_BAJA_INDIRECTO = 'S' OR MAX_BAJA_DIRECTO = 'S')
    GROUP BY CIF_ID)
    GROUP BY CIF_ID;
    BEGIN
    OPEN CUR;
    LOOP
    FETCH CUR BULK COLLECT
    INTO T_ARRAY_COL LIMIT 100;
    FORALL I IN 1 .. T_ARRAY_COL.COUNT
    INSERT INTO TIPO_PER_2
    (CIF_ID , CL_ORI,F_COTI ,EX_ORI ,F_EX_MAX)
    VALUES
    (T_ARRAY_COL(i).CIF_ID,
    T_ARRAY_COL(i).CL_ORI,
    T_ARRAY_COL(i).F_COTI,
    T_ARRAY_COL(i).EX_ORI ,
    T_ARRAY_COL(i).F_EX_MAX);
    EXIT WHEN CUR%NOTFOUND;
    END LOOP;
    COMMIT;
    CLOSE CUR;
    END;
    And this is the errors...
    Compilation errors for PROCEDURE MARKETING.BULK_COLLECT_TIPO_PER
    Error: PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND table of records
    Line: 58
    Text: (T_ARRAY_COL(i).CIF_ID,
    Error: PLS-00382: expression is of wrong type
    Line: 58
    Text: (T_ARRAY_COL(i).CIF_ID,
    Error: PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND table of records
    Line: 59
    Text: T_ARRAY_COL(i).CL_ORI,
    Error: PLS-00382: expression is of wrong type
    Line: 59
    Text: T_ARRAY_COL(i).CL_ORI,
    Error: PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND table of records
    Line: 60
    Text: T_ARRAY_COL(i).F_COTI,
    Error: PLS-00382: expression is of wrong type
    Line: 60
    Text: T_ARRAY_COL(i).F_COTI,
    Error: PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND table of records
    Line: 61
    Text: T_ARRAY_COL(i).EX_ORI ,
    Error: PLS-00382: expression is of wrong type
    Line: 61
    Text: T_ARRAY_COL(i).EX_ORI ,
    Error: PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND table of records
    Line: 62
    Text: T_ARRAY_COL(i).F_EX_MAX);
    Error: PLS-00382: expression is of wrong type
    Line: 62
    Text: T_ARRAY_COL(i).F_EX_MAX);
    Error: PL/SQL: ORA-22806: not an object or REF
    Line: 58
    Text: (T_ARRAY_COL(i).CIF_ID,
    Error: PL/SQL: SQL Statement ignored
    Line: 55
    Text: INSERT INTO TIPO_PER_2
    i try to solve this errors but i cant....help please

    How about replacing your insert with following
    INSERT INTO TIPO_PER_2
    VALUES
    T_ARRAY_COL(i);
    I USED YOUR SUGESTION BUT ....
    Compilation errors for PROCEDURE MARKETING.BULK_COLLECT_TIPO_PER
    Error: PL/SQL: ORA-00947: not enough values
    Line: 63
    Text: INSERT INTO TIPO_PER_2
    Error: PL/SQL: SQL Statement ignored
    Line: 63
    Text: INSERT INTO TIPO_PER_2
    I NOT UNDERSTAND WHAT IS THE RESTRICTION IN MY CASE?
    THANKS---------------------------------------------------------------------

  • Bulk Collect Problem

    I have table Tab1 has 20 columns
    i have table tab2 has 10 columns , i want you uses the bulk collect insert in tab2 to tab 1 only selected columns from the tab1 .
    TYPE ARRAY IS TABLE OF tab2%ROWTYPE;
    l_tab_array ARRAY;
    BEGIN
    SELECT * BULK COLLECT INTO l_tab_array
    FROM tab1;
    FORALL x in l_tab_array.First..l_tab_array.Last
    INSERT INTO tab2(column1,column2 ) VALUES l_tab_array(x) ; --please tell me how to access the array column.
    END;
    i tried INSERT INTO tab2(column1) VALUES (l_tab_array(x).col1)
    10:21:07 AM 47/61 PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND table of records
    10:21:07 AM 47/61 PLS-00382: expression is of wrong type
    10:21:07 AM 47/61 PL/SQL: ORA-22806: not an object or REF
    please give the insert statement with array .
    Regards
    ram
    Edited by: Mani on Feb 10, 2011 3:19 PM

    Yep - this is a right pain in older versions of Oracle.
    You need to have one associative array per column.
    Also see this article from Adrian Billington about alternatives:
    http://www.oracle-developer.net/display.php?id=410
    However, it may be that you're misusing collections etc when the best solutions is always a SQL single statement:
    INSERT
    INTO ...
    SELECT..
    Edited by: Dom Brooks on Feb 10, 2011 3:25 PM

  • 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.

  • Can I use Bulk Collect results as input parameter for another cursor

    MUSIC            ==> remote MUSIC_DB database, MUSIC table has 60 million rows
    PRICE_DATA ==> remote PRICING_DB database, PRICE_DATE table has 1 billion rows
    These two table once existed in same database, but size of database exceeded available hardware size and hardware budget, so the PRICE_DATA table was moved to another Oracle database.  I need to create a single report that combines data from both of these tables, and a distributed join with DRIVING_SITE hint will not work because the size of both table is too large to push to one DRIVING_SITE location, so I wrote this PLSQL block to process in small blocks.
    QUESTION: how can use bulk collect from one cursor and pass that bulk collected information as input to second cursor without specifically listing each cell of the PLSQL bulk collection?  See sample pseudo-code below, I am trying to determine more efficient way to code than hard-coding 100 parameter names into 2nd cursor.
    NOTE: below is truly pseudo-code, I had to change the names of everything to adhere to NDA, but below works and is fast enough for my purposes, but if I want to change from 100 input parameters to 200, I have to add more hard-coded values.  There has got to be a better way.
    DECLARE
         -- define cursor that retrieves distinct SONG_IDs from MUSIC table in remote music database
         CURSOR C_CURRENT_MUSIC
         IS
        select distinct SONG_ID
        from MUSIC@MUSIC_DB
        where PRODUCTION_RELEASE=1
         /*  define a parameterized cursor that accepts 100 SONG_IDs and retrieves
              required pricing information
         CURSOR C_get_music_price_data
                   P_SONG_ID_001 NUMBER, P_SONG_ID_002 NUMBER, P_SONG_ID_003 NUMBER, P_SONG_ID_004 NUMBER, P_SONG_ID_005 NUMBER, P_SONG_ID_006 NUMBER, P_SONG_ID_007 NUMBER, P_SONG_ID_008 NUMBER, P_SONG_ID_009 NUMBER, P_SONG_ID_010 NUMBER,
                   P_SONG_ID_011 NUMBER, P_SONG_ID_012 NUMBER, P_SONG_ID_013 NUMBER, P_SONG_ID_014 NUMBER, P_SONG_ID_015 NUMBER, P_SONG_ID_016 NUMBER, P_SONG_ID_017 NUMBER, P_SONG_ID_018 NUMBER, P_SONG_ID_019 NUMBER, P_SONG_ID_020 NUMBER,
                   P_SONG_ID_021 NUMBER, P_SONG_ID_022 NUMBER, P_SONG_ID_023 NUMBER, P_SONG_ID_024 NUMBER, P_SONG_ID_025 NUMBER, P_SONG_ID_026 NUMBER, P_SONG_ID_027 NUMBER, P_SONG_ID_028 NUMBER, P_SONG_ID_029 NUMBER, P_SONG_ID_030 NUMBER,
                   P_SONG_ID_031 NUMBER, P_SONG_ID_032 NUMBER, P_SONG_ID_033 NUMBER, P_SONG_ID_034 NUMBER, P_SONG_ID_035 NUMBER, P_SONG_ID_036 NUMBER, P_SONG_ID_037 NUMBER, P_SONG_ID_038 NUMBER, P_SONG_ID_039 NUMBER, P_SONG_ID_040 NUMBER,
                   P_SONG_ID_041 NUMBER, P_SONG_ID_042 NUMBER, P_SONG_ID_043 NUMBER, P_SONG_ID_044 NUMBER, P_SONG_ID_045 NUMBER, P_SONG_ID_046 NUMBER, P_SONG_ID_047 NUMBER, P_SONG_ID_048 NUMBER, P_SONG_ID_049 NUMBER, P_SONG_ID_050 NUMBER,
                   P_SONG_ID_051 NUMBER, P_SONG_ID_052 NUMBER, P_SONG_ID_053 NUMBER, P_SONG_ID_054 NUMBER, P_SONG_ID_055 NUMBER, P_SONG_ID_056 NUMBER, P_SONG_ID_057 NUMBER, P_SONG_ID_058 NUMBER, P_SONG_ID_059 NUMBER, P_SONG_ID_060 NUMBER,
                   P_SONG_ID_061 NUMBER, P_SONG_ID_062 NUMBER, P_SONG_ID_063 NUMBER, P_SONG_ID_064 NUMBER, P_SONG_ID_065 NUMBER, P_SONG_ID_066 NUMBER, P_SONG_ID_067 NUMBER, P_SONG_ID_068 NUMBER, P_SONG_ID_069 NUMBER, P_SONG_ID_070 NUMBER,
                   P_SONG_ID_071 NUMBER, P_SONG_ID_072 NUMBER, P_SONG_ID_073 NUMBER, P_SONG_ID_074 NUMBER, P_SONG_ID_075 NUMBER, P_SONG_ID_076 NUMBER, P_SONG_ID_077 NUMBER, P_SONG_ID_078 NUMBER, P_SONG_ID_079 NUMBER, P_SONG_ID_080 NUMBER,
                   P_SONG_ID_081 NUMBER, P_SONG_ID_082 NUMBER, P_SONG_ID_083 NUMBER, P_SONG_ID_084 NUMBER, P_SONG_ID_085 NUMBER, P_SONG_ID_086 NUMBER, P_SONG_ID_087 NUMBER, P_SONG_ID_088 NUMBER, P_SONG_ID_089 NUMBER, P_SONG_ID_090 NUMBER,
                   P_SONG_ID_091 NUMBER, P_SONG_ID_092 NUMBER, P_SONG_ID_093 NUMBER, P_SONG_ID_094 NUMBER, P_SONG_ID_095 NUMBER, P_SONG_ID_096 NUMBER, P_SONG_ID_097 NUMBER, P_SONG_ID_098 NUMBER, P_SONG_ID_099 NUMBER, P_SONG_ID_100 NUMBER
         IS
         select
         from PRICE_DATA@PRICING_DB
         where COUNTRY = 'USA'
         and START_DATE <= sysdate
         and END_DATE > sysdate
         and vpc.SONG_ID IN
                   P_SONG_ID_001 ,P_SONG_ID_002 ,P_SONG_ID_003 ,P_SONG_ID_004 ,P_SONG_ID_005 ,P_SONG_ID_006 ,P_SONG_ID_007 ,P_SONG_ID_008 ,P_SONG_ID_009 ,P_SONG_ID_010,
                   P_SONG_ID_011 ,P_SONG_ID_012 ,P_SONG_ID_013 ,P_SONG_ID_014 ,P_SONG_ID_015 ,P_SONG_ID_016 ,P_SONG_ID_017 ,P_SONG_ID_018 ,P_SONG_ID_019 ,P_SONG_ID_020,
                   P_SONG_ID_021 ,P_SONG_ID_022 ,P_SONG_ID_023 ,P_SONG_ID_024 ,P_SONG_ID_025 ,P_SONG_ID_026 ,P_SONG_ID_027 ,P_SONG_ID_028 ,P_SONG_ID_029 ,P_SONG_ID_030,
                   P_SONG_ID_031 ,P_SONG_ID_032 ,P_SONG_ID_033 ,P_SONG_ID_034 ,P_SONG_ID_035 ,P_SONG_ID_036 ,P_SONG_ID_037 ,P_SONG_ID_038 ,P_SONG_ID_039 ,P_SONG_ID_040,
                   P_SONG_ID_041 ,P_SONG_ID_042 ,P_SONG_ID_043 ,P_SONG_ID_044 ,P_SONG_ID_045 ,P_SONG_ID_046 ,P_SONG_ID_047 ,P_SONG_ID_048 ,P_SONG_ID_049 ,P_SONG_ID_050,
                   P_SONG_ID_051 ,P_SONG_ID_052 ,P_SONG_ID_053 ,P_SONG_ID_054 ,P_SONG_ID_055 ,P_SONG_ID_056 ,P_SONG_ID_057 ,P_SONG_ID_058 ,P_SONG_ID_059 ,P_SONG_ID_060,
                   P_SONG_ID_061 ,P_SONG_ID_062 ,P_SONG_ID_063 ,P_SONG_ID_064 ,P_SONG_ID_065 ,P_SONG_ID_066 ,P_SONG_ID_067 ,P_SONG_ID_068 ,P_SONG_ID_069 ,P_SONG_ID_070,
                   P_SONG_ID_071 ,P_SONG_ID_072 ,P_SONG_ID_073 ,P_SONG_ID_074 ,P_SONG_ID_075 ,P_SONG_ID_076 ,P_SONG_ID_077 ,P_SONG_ID_078 ,P_SONG_ID_079 ,P_SONG_ID_080,
                   P_SONG_ID_081 ,P_SONG_ID_082 ,P_SONG_ID_083 ,P_SONG_ID_084 ,P_SONG_ID_085 ,P_SONG_ID_086 ,P_SONG_ID_087 ,P_SONG_ID_088 ,P_SONG_ID_089 ,P_SONG_ID_090,
                   P_SONG_ID_091 ,P_SONG_ID_092 ,P_SONG_ID_093 ,P_SONG_ID_094 ,P_SONG_ID_095 ,P_SONG_ID_096 ,P_SONG_ID_097 ,P_SONG_ID_098 ,P_SONG_ID_099 ,P_SONG_ID_100
         group by
               vpc.SONG_ID
              ,vpc.STOREFRONT_ID
         TYPE SONG_ID_TYPE IS TABLE OF MUSIC@MUSIC_DB%TYPE INDEX BY BINARY_INTEGER;
         V_SONG_ID_ARRAY                         SONG_ID_TYPE                     ;
         v_commit_counter           NUMBER := 0;
    BEGIN
         /* open cursor you intent to bulk collect from */
         OPEN C_CURRENT_MUSIC;
         LOOP
              /* in batches of 100, bulk collect ADAM_ID mapped TMS_IDENTIFIER into PLSQL table or records */
              FETCH C_CURRENT_MUSIC BULK COLLECT INTO V_SONG_ID_ARRAY LIMIT 100;
                   EXIT WHEN V_SONG_ID_ARRAY.COUNT = 0;
                   /* to avoid NO DATA FOUND error when pass 100 parameters to OPEN cursor, if the arrary
                      is not fully populated to 100, pad the array with nulls to fill up to 100 cells. */
                   IF (V_SONG_ID_ARRAY.COUNT >=1 and V_SONG_ID_ARRAY.COUNT <> 100) THEN
                        FOR j IN V_SONG_ID_ARRAY.COUNT+1..100 LOOP
                             V_SONG_ID_ARRAY(j) := null;
                        END LOOP;
                   END IF;
              /* pass a batch of 100 to cursor that get price information per SONG_ID and STOREFRONT_ID */
              FOR j IN C_get_music_price_data
                        V_SONG_ID_ARRAY(1) ,V_SONG_ID_ARRAY(2) ,V_SONG_ID_ARRAY(3) ,V_SONG_ID_ARRAY(4) ,V_SONG_ID_ARRAY(5) ,V_SONG_ID_ARRAY(6) ,V_SONG_ID_ARRAY(7) ,V_SONG_ID_ARRAY(8) ,V_SONG_ID_ARRAY(9) ,V_SONG_ID_ARRAY(10) ,
                        V_SONG_ID_ARRAY(11) ,V_SONG_ID_ARRAY(12) ,V_SONG_ID_ARRAY(13) ,V_SONG_ID_ARRAY(14) ,V_SONG_ID_ARRAY(15) ,V_SONG_ID_ARRAY(16) ,V_SONG_ID_ARRAY(17) ,V_SONG_ID_ARRAY(18) ,V_SONG_ID_ARRAY(19) ,V_SONG_ID_ARRAY(20) ,
                        V_SONG_ID_ARRAY(21) ,V_SONG_ID_ARRAY(22) ,V_SONG_ID_ARRAY(23) ,V_SONG_ID_ARRAY(24) ,V_SONG_ID_ARRAY(25) ,V_SONG_ID_ARRAY(26) ,V_SONG_ID_ARRAY(27) ,V_SONG_ID_ARRAY(28) ,V_SONG_ID_ARRAY(29) ,V_SONG_ID_ARRAY(30) ,
                        V_SONG_ID_ARRAY(31) ,V_SONG_ID_ARRAY(32) ,V_SONG_ID_ARRAY(33) ,V_SONG_ID_ARRAY(34) ,V_SONG_ID_ARRAY(35) ,V_SONG_ID_ARRAY(36) ,V_SONG_ID_ARRAY(37) ,V_SONG_ID_ARRAY(38) ,V_SONG_ID_ARRAY(39) ,V_SONG_ID_ARRAY(40) ,
                        V_SONG_ID_ARRAY(41) ,V_SONG_ID_ARRAY(42) ,V_SONG_ID_ARRAY(43) ,V_SONG_ID_ARRAY(44) ,V_SONG_ID_ARRAY(45) ,V_SONG_ID_ARRAY(46) ,V_SONG_ID_ARRAY(47) ,V_SONG_ID_ARRAY(48) ,V_SONG_ID_ARRAY(49) ,V_SONG_ID_ARRAY(50) ,
                        V_SONG_ID_ARRAY(51) ,V_SONG_ID_ARRAY(52) ,V_SONG_ID_ARRAY(53) ,V_SONG_ID_ARRAY(54) ,V_SONG_ID_ARRAY(55) ,V_SONG_ID_ARRAY(56) ,V_SONG_ID_ARRAY(57) ,V_SONG_ID_ARRAY(58) ,V_SONG_ID_ARRAY(59) ,V_SONG_ID_ARRAY(60) ,
                        V_SONG_ID_ARRAY(61) ,V_SONG_ID_ARRAY(62) ,V_SONG_ID_ARRAY(63) ,V_SONG_ID_ARRAY(64) ,V_SONG_ID_ARRAY(65) ,V_SONG_ID_ARRAY(66) ,V_SONG_ID_ARRAY(67) ,V_SONG_ID_ARRAY(68) ,V_SONG_ID_ARRAY(69) ,V_SONG_ID_ARRAY(70) ,
                        V_SONG_ID_ARRAY(71) ,V_SONG_ID_ARRAY(72) ,V_SONG_ID_ARRAY(73) ,V_SONG_ID_ARRAY(74) ,V_SONG_ID_ARRAY(75) ,V_SONG_ID_ARRAY(76) ,V_SONG_ID_ARRAY(77) ,V_SONG_ID_ARRAY(78) ,V_SONG_ID_ARRAY(79) ,V_SONG_ID_ARRAY(80) ,
                        V_SONG_ID_ARRAY(81) ,V_SONG_ID_ARRAY(82) ,V_SONG_ID_ARRAY(83) ,V_SONG_ID_ARRAY(84) ,V_SONG_ID_ARRAY(85) ,V_SONG_ID_ARRAY(86) ,V_SONG_ID_ARRAY(87) ,V_SONG_ID_ARRAY(88) ,V_SONG_ID_ARRAY(89) ,V_SONG_ID_ARRAY(90) ,
                        V_SONG_ID_ARRAY(91) ,V_SONG_ID_ARRAY(92) ,V_SONG_ID_ARRAY(93) ,V_SONG_ID_ARRAY(94) ,V_SONG_ID_ARRAY(95) ,V_SONG_ID_ARRAY(96) ,V_SONG_ID_ARRAY(97) ,V_SONG_ID_ARRAY(98) ,V_SONG_ID_ARRAY(99) ,V_SONG_ID_ARRAY(100)        
              LOOP
                   /* do stuff with data from Song and Pricing Database coming from the two
                        separate cursors, then continue processing more rows...
              END LOOP;
              /* commit after each batch of 100 SONG_IDs is processed */        
              COMMIT;
              EXIT WHEN C_CURRENT_MUSIC%NOTFOUND;  -- exit when there are no more rows to fetch from cursor
         END LOOP; -- bulk fetching loop
         CLOSE C_CURRENT_MUSIC; -- close cursor that was used in bulk collection
         /* commit rows */
         COMMIT; -- commit any remaining uncommitted data.
    END;

    I've got a problem when using passing VARRAY of numbers as parameter to remote cursor: it takes a super long time to run, sometimes doesn't finish even after an hour as passed.
    Continuing with my example in original entry, I replaced the bulk collect into PLSQL table collection with a VARRAY and i bulk collect into the VARRAY, this is fast and I know it works because I can DBMS_OUTPUT.PUT_LINE cells of VARRAY so I know it is getting populated correctly.  However, when I pass the VARRAY containing 100 cells populated with SONG_IDs as parameter to cursor, execution time is over an hour and when I am expecting a few seconds.
    Below code example strips the problem down to it's raw details, I skip the bulk collect and just manually populate a VARRAY with 100 SONG_ID values, then try to pass to as parameter to a cursor, but the execution time of cursor is unexpectedly long, over 30 minutes, sometime longer, when I am expecting seconds.
    IMPORTANT: If I take the same 100 SONG_IDs and place them directly in the cursor query's where IN clause, the SQL runs in under 5 seconds and returns result.  Also, if I pass the 100 SONG_IDs as individual cells of a PLSQL table collection, then it also runs fast.
    I thought that since the VARRAY is used via select subquery that is it queried locally, but the cursor is remote, and that I had a distribute problem on my hands, so I put in the DRIVING_SITE hint to attempt to force the result of query against VARRAY to go to remote server and rest of query will run there before returning result, but that didn't work either, still got slow response.
    Is something wrong with my code, or I am running into a Oracle problem that may require support to resolve?
    DECLARE
         /*  define a parameterized cursor that accepts XXX number of in SONG_IDs and
          retrieves required pricing information
         CURSOR C_get_music_price_data
      p_array_song_ids SYS.ODCInumberList              
         IS
         select  /*+DRIVING_SITE(pd) */
      count(distinct s.EVE_ID)
         from PRICE_DATA@PRICING_DB pd
         where pd.COUNTRY = 'USA'
         and pd.START_DATE <= sysdate
         and pd.END_DATE > sysdate
         and pd.SONG_ID IN
              select column_value from table(p_array_song_ids)
         group by
               pd.SONG_ID
              ,pd.STOREFRONT_ID
      V_ARRAY_SONG_IDS SYS.ODCInumberList := SYS.ODCInumberList();    
    BEGIN
    V_ARRAY_SONG_IDS.EXTEND(100);
    V_ARRAY_SONG_IDS(  1 ) := 31135  ;
    V_ARRAY_SONG_IDS(  2 ) := 31140   ;
    V_ARRAY_SONG_IDS(  3 ) := 31142   ;
    V_ARRAY_SONG_IDS(  4 ) := 31144   ;
    V_ARRAY_SONG_IDS(  5 ) := 31146   ;
    V_ARRAY_SONG_IDS(  6 ) := 31148   ;
    V_ARRAY_SONG_IDS(  7 ) := 31150   ;
    V_ARRAY_SONG_IDS(  8 ) := 31152   ;
    V_ARRAY_SONG_IDS(  9 ) := 31154   ;
    V_ARRAY_SONG_IDS( 10 ) := 31156   ;
    V_ARRAY_SONG_IDS( 11 ) := 31158   ;
    V_ARRAY_SONG_IDS( 12 ) := 31160   ;
    V_ARRAY_SONG_IDS( 13 ) := 33598   ;
    V_ARRAY_SONG_IDS( 14 ) := 33603   ;
    V_ARRAY_SONG_IDS( 15 ) := 33605   ;
    V_ARRAY_SONG_IDS( 16 ) := 33607   ;
    V_ARRAY_SONG_IDS( 17 ) := 33609   ;
    V_ARRAY_SONG_IDS( 18 ) := 33611   ;
    V_ARRAY_SONG_IDS( 19 ) := 33613   ;
    V_ARRAY_SONG_IDS( 20 ) := 33615   ;
    V_ARRAY_SONG_IDS( 21 ) := 33617   ;
    V_ARRAY_SONG_IDS( 22 ) := 33630   ;
    V_ARRAY_SONG_IDS( 23 ) := 33632   ;
    V_ARRAY_SONG_IDS( 24 ) := 33636   ;
    V_ARRAY_SONG_IDS( 25 ) := 33638   ;
    V_ARRAY_SONG_IDS( 26 ) := 33640   ;
    V_ARRAY_SONG_IDS( 27 ) := 33642   ;
    V_ARRAY_SONG_IDS( 28 ) := 33644   ;
    V_ARRAY_SONG_IDS( 29 ) := 33646   ;
    V_ARRAY_SONG_IDS( 30 ) := 33648   ;
    V_ARRAY_SONG_IDS( 31 ) := 33662   ;
    V_ARRAY_SONG_IDS( 32 ) := 33667   ;
    V_ARRAY_SONG_IDS( 33 ) := 33669   ;
    V_ARRAY_SONG_IDS( 34 ) := 33671   ;
    V_ARRAY_SONG_IDS( 35 ) := 33673   ;
    V_ARRAY_SONG_IDS( 36 ) := 33675   ;
    V_ARRAY_SONG_IDS( 37 ) := 33677   ;
    V_ARRAY_SONG_IDS( 38 ) := 33679   ;
    V_ARRAY_SONG_IDS( 39 ) := 33681   ;
    V_ARRAY_SONG_IDS( 40 ) := 33683   ;
    V_ARRAY_SONG_IDS( 41 ) := 33685   ;
    V_ARRAY_SONG_IDS( 42 ) := 33700   ;
    V_ARRAY_SONG_IDS( 43 ) := 33702   ;
    V_ARRAY_SONG_IDS( 44 ) := 33704   ;
    V_ARRAY_SONG_IDS( 45 ) := 33706   ;
    V_ARRAY_SONG_IDS( 46 ) := 33708   ;
    V_ARRAY_SONG_IDS( 47 ) := 33710   ;
    V_ARRAY_SONG_IDS( 48 ) := 33712   ;
    V_ARRAY_SONG_IDS( 49 ) := 33723   ;
    V_ARRAY_SONG_IDS( 50 ) := 33725   ;
    V_ARRAY_SONG_IDS( 51 ) := 33727   ;
    V_ARRAY_SONG_IDS( 52 ) := 33729   ;
    V_ARRAY_SONG_IDS( 53 ) := 33731   ;
    V_ARRAY_SONG_IDS( 54 ) := 33733   ;
    V_ARRAY_SONG_IDS( 55 ) := 33735   ;
    V_ARRAY_SONG_IDS( 56 ) := 33737   ;
    V_ARRAY_SONG_IDS( 57 ) := 33749   ;
    V_ARRAY_SONG_IDS( 58 ) := 33751   ;
    V_ARRAY_SONG_IDS( 59 ) := 33753   ;
    V_ARRAY_SONG_IDS( 60 ) := 33755   ;
    V_ARRAY_SONG_IDS( 61 ) := 33757   ;
    V_ARRAY_SONG_IDS( 62 ) := 33759   ;
    V_ARRAY_SONG_IDS( 63 ) := 33761   ;
    V_ARRAY_SONG_IDS( 64 ) := 33763   ;
    V_ARRAY_SONG_IDS( 65 ) := 33775   ;
    V_ARRAY_SONG_IDS( 66 ) := 33777   ;
    V_ARRAY_SONG_IDS( 67 ) := 33779   ;
    V_ARRAY_SONG_IDS( 68 ) := 33781   ;
    V_ARRAY_SONG_IDS( 69 ) := 33783   ;
    V_ARRAY_SONG_IDS( 70 ) := 33785   ;
    V_ARRAY_SONG_IDS( 71 ) := 33787   ;
    V_ARRAY_SONG_IDS( 72 ) := 33789   ;
    V_ARRAY_SONG_IDS( 73 ) := 33791   ;
    V_ARRAY_SONG_IDS( 74 ) := 33793   ;
    V_ARRAY_SONG_IDS( 75 ) := 33807   ;
    V_ARRAY_SONG_IDS( 76 ) := 33809   ;
    V_ARRAY_SONG_IDS( 77 ) := 33811   ;
    V_ARRAY_SONG_IDS( 78 ) := 33813   ;
    V_ARRAY_SONG_IDS( 79 ) := 33815   ;
    V_ARRAY_SONG_IDS( 80 ) := 33817   ;
    V_ARRAY_SONG_IDS( 81 ) := 33819   ;
    V_ARRAY_SONG_IDS( 82 ) := 33821   ;
    V_ARRAY_SONG_IDS( 83 ) := 33823   ;
    V_ARRAY_SONG_IDS( 84 ) := 33825   ;
    V_ARRAY_SONG_IDS( 85 ) := 33839   ;
    V_ARRAY_SONG_IDS( 86 ) := 33844   ;
    V_ARRAY_SONG_IDS( 87 ) := 33846   ;
    V_ARRAY_SONG_IDS( 88 ) := 33848   ;
    V_ARRAY_SONG_IDS( 89 ) := 33850   ;
    V_ARRAY_SONG_IDS( 90 ) := 33852   ;
    V_ARRAY_SONG_IDS( 91 ) := 33854   ;
    V_ARRAY_SONG_IDS( 92 ) := 33856   ;
    V_ARRAY_SONG_IDS( 93 ) := 33858   ;
    V_ARRAY_SONG_IDS( 94 ) := 33860   ;
    V_ARRAY_SONG_IDS( 95 ) := 33874   ;
    V_ARRAY_SONG_IDS( 96 ) := 33879   ;
    V_ARRAY_SONG_IDS( 97 ) := 33881   ;
    V_ARRAY_SONG_IDS( 98 ) := 33883   ;
    V_ARRAY_SONG_IDS( 99 ) := 33885   ;
    V_ARRAY_SONG_IDS(100 ) := 33889  ;
        /* do stuff with data from Song and Pricing Database coming from the two
      separate cursors, then continue processing more rows...
      FOR i IN C_get_music_price_data( v_array_song_ids ) LOOP
      . (this is the loop where I pass in v_array_song_ids
      .  populated with only 100 cells and it runs forever)
      END LOOP; 
    END;

  • Is there a way to BULK COLLECT with FOR UPDATE and not lock ALL the rows?

    Currently, we fetch a cursor on a few million rows using BULK COLLECT.
    In a FORALL loop, we update the rows.
    What is happening now, is that we run this procedure at the same time, and there is another session running a MERGE statement on the same table, and a DEADLOCK is created between them.
    I'd like to add to the cursor the FOR UPDATE clause, but from what i've read,
    it seems that this will cause ALL the rows in the cursor to become locked.
    This is a problem, as the other session is running MERGE statements on the table every few seconds, and I don't want it to fail with ORA-0054 (resource busy).
    What I would like to know is if there is a way, that only the rows in the
    current bulk will be locked, and all the other rows will be free for updates.
    To reproduce this problem:
    1. Create test table:
    create table TEST_TAB
    ID1 VARCHAR2(20),
    ID2 VARCHAR2(30),
    LAST_MODIFIED DATE
    2. Add rows to test table:
    insert into TEST_TAB (ID1, ID2, LAST_MODIFIED)
    values ('416208000770698', '336015000385349', to_date('15-11-2009 07:14:56', 'dd-mm-yyyy hh24:mi:ss'));
    insert into TEST_TAB (ID1, ID2, LAST_MODIFIED)
    values ('208104922058401', '336015000385349', to_date('15-11-2009 07:11:15', 'dd-mm-yyyy hh24:mi:ss'));
    insert into TEST_TAB (ID1, ID2, LAST_MODIFIED)
    values ('208104000385349', '336015000385349', to_date('15-11-2009 07:15:13', 'dd-mm-yyyy hh24:mi:ss'));
    3. Create test procedure:
    CREATE OR REPLACE PROCEDURE TEST_PROC IS
    TYPE id1_typ is table of TEST_TAB.ID1%TYPE;
    TYPE id2_typ is table of TEST_TAB.ID2%TYPE;
    id1_arr id1_typ;
    id2_arr id2_typ;
    CURSOR My_Crs IS
    SELECT ID1, ID2
    FROM TEST_TAB
    WHERE ID2 = '336015000385349'
    FOR UPDATE;
    BEGIN
    OPEN My_Crs;
    LOOP
    FETCH My_Crs bulk collect
    INTO id1_arr, id2_arr LIMIT 1;
    Forall i in 1 .. id1_arr.COUNT
    UPDATE TEST_TAB
    SET LAST_MODIFIED = SYSDATE
    where ID2 = id2_arr(i)
    and ID1 = id1_arr(i);
    dbms_lock.sleep(15);
    EXIT WHEN My_Crs%NOTFOUND;
    END LOOP;
    CLOSE My_Crs;
    COMMIT;
    EXCEPTION
    WHEN OTHERS THEN
    RAISE_APPLICATION_ERROR(-20000,
    'Test Update ' || SQLCODE || ' ' || SQLERRM);
    END TEST_PROC;
    4. Create another procedure to check if table rows are locked:
    create or replace procedure check_record_locked(p_id in TEST_TAB.ID1%type) is
    cursor c is
    select 'dummy'
    from TEST_TAB
    WHERE ID2 = '336015000385349'
    and ID1 = p_id
    for update nowait;
    e_resource_busy exception;
    pragma exception_init(e_resource_busy, -54);
    begin
    open c;
    close c;
    dbms_output.put_line('Record ' || to_char(p_id) || ' is not locked.');
    rollback;
    exception
    when e_resource_busy then
    dbms_output.put_line('Record ' || to_char(p_id) || ' is locked.');
    end check_record_locked;
    5. in one session, run the procedure TEST_PROC.
    6. While it's running, in another session, run this block:
    begin
    check_record_locked('208104922058401');
    check_record_locked('416208000770698');
    check_record_locked('208104000385349');
    end;
    7. you will see that all records are identified as locked.
    Is there a way that only 1 row will be locked, and the other 2 will be unlocked?
    Thanks,
    Yoni.

    I don't have database access on weekends (look at it as a template)
    suppose you
    create table help_iot
    (bucket number,
    id1    varchar2(20),
    constraint help_iot_pk primary key (bucket,id1)
    organization index;not very sure about the create table syntax above.
    declare
      maximal_bucket number := 10000; -- will update few hundred rows at a time if you must update few million rows
      the_sysdate date := sysdate;
    begin
      truncate table help_iot;
      insert into help_iot
      select ntile(maximal_bucket) over (order by id1) bucket,id1
        from test_tab
       where id2 = '336015000385349';
      for i in 1 .. maximal_bucket
      loop
        select id1,id2,last_modified
          from test_tab
         where id2 = '336015000385349'
           and id1 in (select id1
                         from help_iot
                        where bucket = i
           for update of last_modified;
        update test_tab
           set last_modified = the_sysdate
         where id2 = '336015000385349'
           and id1 in (select id1
                         from help_iot
                        where bucket = i
        commit;
        dbms_lock.sleep(15);
      end loop;
    end;Regards
    Etbin
    introduced the_sysdate if last_modified must be the same for all updated rows
    Edited by: Etbin on 29.11.2009 16:48

  • Help needed in bulk collect

    Hi,
    below procedure is throwing error like "invalid sql". i doubt problem is with insert statement inside the body of the procedure, please help me how to load table with individual columns in bulk collect
    CREATE OR REPLACE PROCEDURE subscriber_load
    IS
    TYPE r_subscriber_data IS RECORD
    ( acct_no      LPDADMIN.SUBSCRIBER.acct_no%TYPE,
         acct_status_cd           LPDADMIN.SUBSCRIBER.acct_status_cd%TYPE,
              connect_date                LPDADMIN.SUBSCRIBER.connect_date%TYPE,
              disconnect_date           LPDADMIN.SUBSCRIBER.disconnect_date%TYPE,
              bill_salutation_cd           LPDADMIN.SUBSCRIBER.bill_salutation_cd%TYPE,
              bill_first_name           LPDADMIN.SUBSCRIBER.bill_first_name%TYPE,
              bill_last_name                LPDADMIN.SUBSCRIBER.bill_last_name%TYPE,
              bill_addr_1                LPDADMIN.SUBSCRIBER.bill_addr_1%TYPE,
              bill_addr_2                LPDADMIN.SUBSCRIBER.bill_addr_2%TYPE,
              bill_city                     LPDADMIN.SUBSCRIBER.bill_city%TYPE,
              bill_postal_code           LPDADMIN.SUBSCRIBER.bill_postal_code%TYPE,
              bill_province_cd           LPDADMIN.SUBSCRIBER.bill_province_cd%TYPE,
              bill_cycle_day                LPDADMIN.SUBSCRIBER.bill_cycle_day%TYPE,
              home_phone                     LPDADMIN.SUBSCRIBER.home_phone%TYPE,
    business_phone                LPDADMIN.SUBSCRIBER.business_phone%TYPE,
    first_name                     LPDADMIN.SUBSCRIBER.first_name%TYPE,
    last_name                     LPDADMIN.SUBSCRIBER.last_name%TYPE,
    home_phone                     LPDADMIN.SUBSCRIBER.home_phone%TYPE,
    delql_status_cd           LPDADMIN.SUBSCRIBER.delql_status_cd%TYPE,
    service_address_1           LPDADMIN.SUBSCRIBER.service_address_1%TYPE,
    service_address_2           LPDADMIN.SUBSCRIBER.service_address_2%TYPE,
    service_city                LPDADMIN.SUBSCRIBER.service_city%TYPE,
    service_province_cd      LPDADMIN.SUBSCRIBER.service_province_cd%TYPE
    TYPE t_subscriber_data IS TABLE OF r_subscriber_data INDEX BY BINARY_INTEGER;
    table_subscriber_data t_subscriber_data;
    CURSOR c_subscriber_data IS
    SELECT s.acct_no
    ,lb.lob_status_cd
    ,s.connect_date
    ,s.disconnect_date
    ,s.bill_to_salutation_cd
    ,substr(s.bill_to_name,instr(bill_to_name,',',1)+1) bill_first_name
    ,substr(s.bill_to_name,1,instr(bill_to_name,',',1)-1) bill_last_name
    ,s.bill_to_addr_1
    ,s.bill_to_addr_2
    ,s.bill_to_city
    ,s.bill_to_postal_code
    ,s.bill_to_province_cd
    ,s.bill_create_day_of_month
    ,s.home_phone
    ,s.business_phone
    ,substr(s.name,instr(bill_to_name,',',1)+1) first_name
    ,substr(s.name,1,instr(bill_to_name,',',1)-1) last_name
    ,s.home_phone
    ,s.delq_status_cd
    ,h.addr_1
    ,h.addr_2
    ,h.city
    ,h.province_cd
    FROM ccsadmin.subscriber s
    inner join CCSADMIN.HOUSE h
    on s.HOUSE_KEY = h.HOUSE_NO
    left outer join CCSADMIN.LINE_OF_BUSINESS lb
    on h.HOUSE_NO = lb.HOUSE_NO
    WHERE lb.LOB_TYPE_CD ='C'
    AND lb.HOUSE_NO IS NOT NULL;
    BEGIN
    OPEN c_subscriber_data;
    LOOP
    FETCH c_subscriber_data BULK COLLECT INTO table_subscriber_data LIMIT 100000;
    EXIT WHEN table_subscriber_data.COUNT = 0;
    if table_subscriber_data.COUNT>0 then
    FOR idx IN table_subscriber_data.first..table_subscriber_data.last loop
    INSERT INTO LPDADMIN.SUBSCRIBER(acct_no
                                                      ,acct_status_cd
                                                      ,connect_date
                                                      ,disconnect_date
                                                      ,bill_salutation_cd
                                                      ,bill_first_name
                                                      ,bill_last_name
                                                      ,bill_addr_1
                                                      ,bill_addr_2
                                                      ,bill_city
                                                      ,bill_postal_code
                                                      ,bill_province_cd
                                                      ,bill_cycle_day
                                                      ,home_phone
                                            ,business_phone
                                                      ,first_name
                                                      ,last_name
                                                      ,home_phone
                                                      ,delql_status_cd
                                                      ,service_address_1
                                                      ,service_address_2
                                                      ,service_city
                                                      ,service_province_cd
         VALUES (table_subscriber_data(idx).acct_no
         ,table_subscriber_data(idx).acct_status_cd
         ,table_subscriber_data(idx).connect_date
                   ,table_subscriber_data(idx).disconnect_date      
                   ,table_subscriber_data(idx).bill_salutation_cd
                   ,table_subscriber_data(idx).bill_first_name      
                   ,table_subscriber_data(idx).bill_last_name      
                   ,table_subscriber_data(idx).bill_addr_1           
                   ,table_subscriber_data(idx).bill_addr_2           
                   ,table_subscriber_data(idx).bill_city           
                   ,table_subscriber_data(idx).bill_postal_code
                   ,table_subscriber_data(idx).bill_province_cd
                   ,table_subscriber_data(idx).bill_cycle_day      
                   ,table_subscriber_data(idx).home_phone           
         ,table_subscriber_data(idx).business_phone      
         ,table_subscriber_data(idx).first_name           
         ,table_subscriber_data(idx).last_name           
         ,table_subscriber_data(idx).home_phone           
         ,table_subscriber_data(idx).delql_status_cd      
         ,table_subscriber_data(idx).service_address_1
         ,table_subscriber_data(idx).service_address_2
         ,table_subscriber_data(idx).service_city      
         ,table_subscriber_data(idx).service_province_cd);
    END LOOP;
    end if;
    END subscriber_load;
    /

    no PL/SQL required
    INSERT INTO LPDADMIN.SUBSCRIBER(acct_no
    ,acct_status_cd
    ,connect_date
    ,disconnect_date
    ,bill_salutation_cd
    ,bill_first_name
    ,bill_last_name
    ,bill_addr_1
    ,bill_addr_2
    ,bill_city
    ,bill_postal_code
    ,bill_province_cd
    ,bill_cycle_day
    ,home_phone
    ,business_phone
    ,first_name
    ,last_name
    ,home_phone
    ,delql_status_cd
    ,service_address_1
    ,service_address_2
    ,service_city
    ,service_province_cd
    ) SELECT .....

  • Issue in using Cursor+Dynamic SQL+ Bulk collect +FORALL

    Hi,
    I have a dynamic query which I need to use as a cursor to fetch records that inturn need to be inserted into a staging table.
    The issue I am facing is I am not sure how to declare the variable to fetch the records into. Since I am using a dynamic cursor how do I declare it?
    My code looks something like this -
    TYPE c_details_tbl_type IS REF CURSOR;
    c_details c_details_tbl_type;
    TYPE c_det_tbl_type IS TABLE OF c_details%ROWTYPE INDEX BY PLS_INTEGER;
    c_det_tbl c_det_tbl_type; -- ???
    BEGIN
    v_string1 := 'SELECT....'
    v_string2 := ' UNION ALL SELECT....'
    v_string3 := 'AND ....'
    v_string := v_string1||v_string2||v_string3;
    OPEN c_details FOR v_string;
    LOOP
    FETCH c_details BULK COLLECT
    INTO c_det_tbl LIMIT 1000;
    IF (c_det_tbl.COUNT > 0) THEN
              DELETE FROM STG;
              FORALL i IN 1..c_det_tbl.COUNT
              INSERT INTO STG
              VALUES (c_det_tbl(i));
    END IF;
    EXIT WHEN c_details%NOTFOUND;
    END LOOP;
    CLOSE c_details;
    END
    Thanks

    Why the bulk collect? All that this does is slow down the read process (SELECT) and write process (INSERT).
    Data selected needs (as a collection) to be pushed into the PGA memory of the PL/SQL engine. And then that very same data needs to be pushed again by the PL/SQL engine back to the database to be inserted. Why?
    It is a lot faster, needs a lot less resources, with fewer moving parts, to simply instruct the SQL engine to do both these steps using a single INSERT..SELECT statement. And this can support parallel DML too for scalability when data volumes get large.
    It is also pretty easy to make a single SQL statement like this dynamic and even support bind variables.
    Simplicity is the ultimate form of elegance. Pushing data needlessly around is not simple and thus not a very elegant way to address the problem.

  • Bulk collect limit 1000 is looping only 1000 records out of 35000 records

    In below code I have to loop around 35000 records for every month of the year starting from Aug-2010 to Aug-2011.
    I am using bulk collect with limit clause but the problem is:
    a: Limit clause is returning only 1000 records.
    b: It is taking too much time to process.
    CREATE OR REPLACE PACKAGE BODY UDBFINV AS
    F UTL_FILE.FILE_TYPE;
    PV_SEQ_NO NUMBER(7);
    PV_REC_CNT NUMBER(7) := 0;
    PV_CRLF VARCHAR2(2) := CHR(13) || CHR(10);
    TYPE REC_PART IS RECORD(
    PART_NUM PM_PART_HARSH.PART_NUM%TYPE,
    ON_HAND_QTY PM_PART_HARSH.ON_HAND_QTY%TYPE,
    ENGG_PREFIX PM_PART_HARSH.ENGG_PREFIX%TYPE,
    ENGG_BASE PM_PART_HARSH.ENGG_BASE%TYPE,
    ENGG_SUFFIX PM_PART_HARSH.ENGG_SUFFIX%TYPE);
    TYPE TB_PART IS TABLE OF REC_PART;
    TYPE REC_DATE IS RECORD(
    START_DATE DATE,
    END_DATE DATE);
    TYPE TB_MONTH IS TABLE OF REC_DATE;
    PROCEDURE MAIN IS
    /* To be called in Scheduler Programs Action */
    BEGIN
    /* Initializing package global variables;*/
    IFMAINT.V_PROG_NAME := 'FULL_INVENTORY';
    IFMAINT.V_ERR_LOG_TAB := 'UDB_ERR_FINV';
    IFMAINT.V_HIST_TAB := 'UDB_HT_FINV';
    IFMAINT.V_UTL_DIR_NAME := 'UDB_SEND';
    IFMAINT.V_PROG_TYPE := 'S';
    IFMAINT.V_IF_TYPE := 'U';
    IFMAINT.V_REC_CNT := 0;
    IFMAINT.V_DEL_INS := 'Y';
    IFMAINT.V_KEY_INFO := NULL;
    IFMAINT.V_MSG := NULL;
    IFMAINT.V_ORA_MSG := NULL;
    IFSMAINT.V_FILE_NUM := IFSMAINT.V_FILE_NUM + 1;
    IFMAINT.LOG_ERROR; /*Initialize error log table, delete prev. rows*/
    /*End of initialization section*/
    IFMAINT.SET_INITIAL_PARAM;
    IFMAINT.SET_PROGRAM_PARAM;
    IFMAINT.SET_UTL_DIR_PATH;
    IFMAINT.GET_DEALER_PARAMETERS;
    PV_SEQ_NO := IFSMAINT.GENERATE_FILE_NAME;
    IF NOT CHECK_FILE_EXISTS THEN
    WRITE_FILE;
    END IF;
    IF IFMAINT.V_BACKUP_PATH_SEND IS NOT NULL THEN
    IFMAINT.COPY_FILE(IFMAINT.V_UTL_DIR_PATH,
    IFMAINT.V_FILE_NAME,
    IFMAINT.V_BACKUP_PATH_SEND);
    END IF;
    IFMAINT.MOVE_FILE(IFMAINT.V_UTL_DIR_PATH,
    IFMAINT.V_FILE_NAME,
    IFMAINT.V_FILE_DEST_PATH);
    COMMIT;
    EXCEPTION
    WHEN IFMAINT.E_TERMINATE THEN
    IFMAINT.V_DEL_INS := 'N';
    IFMAINT.LOG_ERROR;
    ROLLBACK;
    UTL_FILE.FCLOSE(F);
    IFMAINT.DELETE_FILE(IFMAINT.V_UTL_DIR_PATH, IFMAINT.V_FILE_NAME);
    RAISE_APPLICATION_ERROR(IFMAINT.V_USER_ERRCODE, IFMAINT.V_ORA_MSG);
    WHEN OTHERS THEN
    IFMAINT.V_DEL_INS := 'N';
    IFMAINT.V_MSG := 'ERROR IN MAIN PROCEDURE ||IFMAINT.V_PROG_NAME';
    IFMAINT.V_ORA_MSG := SUBSTR(SQLERRM, 1, 255);
    IFMAINT.V_USER_ERRCODE := -20101;
    IFMAINT.LOG_ERROR;
    ROLLBACK;
    UTL_FILE.FCLOSE(F);
    IFMAINT.DELETE_FILE(IFMAINT.V_UTL_DIR_PATH, IFMAINT.V_FILE_NAME);
    RAISE_APPLICATION_ERROR(IFMAINT.V_USER_ERRCODE, IFMAINT.V_ORA_MSG);
    END;
    PROCEDURE WRITE_FILE IS
    CURSOR CR_PART IS
    SELECT A.PART_NUM, ON_HAND_QTY, ENGG_PREFIX, ENGG_BASE, ENGG_SUFFIX
    FROM PM_PART_HARSH A;
    lv_cursor TB_PART;
    LV_CURR_MONTH NUMBER;
    LV_MONTH_1 NUMBER := NULL;
    LV_MONTH_2 NUMBER := NULL;
    LV_MONTH_3 NUMBER := NULL;
    LV_MONTH_4 NUMBER := NULL;
    LV_MONTH_5 NUMBER := NULL;
    LV_MONTH_6 NUMBER := NULL;
    LV_MONTH_7 NUMBER := NULL;
    LV_MONTH_8 NUMBER := NULL;
    LV_MONTH_9 NUMBER := NULL;
    LV_MONTH_10 NUMBER := NULL;
    LV_MONTH_11 NUMBER := NULL;
    LV_MONTH_12 NUMBER := NULL;
    lv_month TB_MONTH := TB_MONTH();
    BEGIN
    IF CR_PART%ISOPEN THEN
    CLOSE CR_PART;
    END IF;
    FOR K IN 1 .. 12 LOOP
    lv_month.EXTEND();
    lv_month(k).start_date := ADD_MONTHS(TRUNC(SYSDATE, 'MM'), - (K + 1));
    lv_month(k).end_date := (ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -K) - 1);
    END LOOP;
    F := utl_file.fopen(IFMAINT.V_UTL_DIR_NAME, IFMAINT.V_FILE_NAME, 'W');
    IF UTL_FILE.IS_OPEN(F) THEN
    /*FILE HEADER*/
    utl_file.put_line(F,
    RPAD('$CUD-', 5, ' ') ||
    RPAD(SUBSTR(IFMAINT.V_PANDA_CD, 1, 5), 5, ' ') ||
    RPAD('-136-', 5, ' ') || RPAD('000000', 6, ' ') ||
    RPAD('-REDFLEX-KA-', 13, ' ') ||
    RPAD('00000000-', 9, ' ') ||
    RPAD(IFMAINT.V_CDS_SPEC_REL_NUM, 5, ' ') ||
    RPAD('CD', 2, ' ') ||
    RPAD(TO_CHAR(SYSDATE, 'MMDDYY'), 6, ' ') ||
    LPAD(IFSMAINT.V_FILE_NUM, 2, 0) ||
    RPAD('-', 1, ' ') || RPAD(' ', 9, ' ') ||
    RPAD('-', 1, ' ') || RPAD(' ', 17, ' ') ||
    RPAD('CD230', 5, ' ') ||
    RPAD(TO_CHAR(SYSDATE, 'MMDDYY'), 6, ' ') ||
    LPAD(IFSMAINT.V_FILE_NUM, 2, 0) ||
    LPAD(PV_REC_CNT, 8, 0) || RPAD(' ', 5, ' ') ||
    RPAD('00000000', 8, ' ') || RPAD('CUD', 3, ' ') ||
    RPAD(IFMAINT.V_CDS_SPEC_REL_NUM, 5, ' ') ||
    RPAD(IFMAINT.V_GEO_SALES_AREA_CD, 3, ' ') ||
    RPAD(IFMAINT.V_FRANCHISE_CD, 2, ' ') ||
    RPAD(IFMAINT.V_DSP_REL_NUM, 9, ' ') ||
    RPAD('00136REDFLEX', 12, ' ') || RPAD(' ', 1, ' ') ||
    RPAD('KA', 2, ' ') || RPAD('000000', 6, ' ') ||
    RPAD('00D', 3, ' ') ||
    RPAD(IFMAINT.V_VENDOR_ID, 6, ' ') ||
    RPAD(IFSMAINT.V_FILE_TYPE, 1, ' ') ||
    RPAD('>', 1, ' ') || PV_CRLF);
    /*LINE ITEMS*/
    OPEN CR_PART;
    FETCH CR_PART BULK COLLECT
    INTO lv_cursor limit 1000;
    FOR I IN lv_cursor.FIRST .. lv_cursor.LAST LOOP
    SELECT SUM(A.BILL_QTY)
    INTO LV_CURR_MONTH
    FROM PD_ISSUE A, PH_ISSUE B
    WHERE A.DOC_TYPE IN ('CRI', 'RRI', 'RSI', 'CSI')
    AND A.DOC_NUM = B.DOC_NUM
    AND B.DOC_DATE BETWEEN TRUNC(SYSDATE, 'MM') AND SYSDATE
    AND A.PART_NUM = LV_CURSOR(i).PART_NUM;
    FOR J IN 1 .. 12 LOOP
    SELECT SUM(A.BILL_QTY)
    INTO LV_MONTH_1
    FROM PD_ISSUE A, PH_ISSUE B
    WHERE A.DOC_TYPE IN ('CRI', 'RRI', 'RSI', 'CSI')
    AND A.DOC_NUM = B.DOC_NUM
    AND B.DOC_DATE BETWEEN lv_month(J).start_date and lv_month(J)
    .end_date
    AND A.PART_NUM = LV_CURSOR(i).PART_NUM;
    END LOOP;
    utl_file.put_line(F,
    RPAD('IL', 2, ' ') ||
    RPAD(TO_CHAR(SYSDATE, 'RRRRMMDD'), 8, ' ') ||
    RPAD(LV_CURSOR(I).ENGG_PREFIX, 6, ' ') ||
    RPAD(LV_CURSOR(I).ENGG_BASE, 8, ' ') ||
    RPAD(LV_CURSOR(I).ENGG_SUFFIX, 6, ' ') ||
    LPAD(LV_CURSOR(I).ON_HAND_QTY, 7, 0) ||
    LPAD(NVL(LV_CURR_MONTH, 0), 7, 0) ||
    LPAD(LV_MONTH_1, 7, 0) || LPAD(LV_MONTH_2, 7, 0) ||
    LPAD(LV_MONTH_3, 7, 0) || LPAD(LV_MONTH_4, 7, 0) ||
    LPAD(LV_MONTH_5, 7, 0) || LPAD(LV_MONTH_6, 7, 0) ||
    LPAD(LV_MONTH_7, 7, 0) || LPAD(LV_MONTH_8, 7, 0) ||
    LPAD(LV_MONTH_9, 7, 0) || LPAD(LV_MONTH_10, 7, 0) ||
    LPAD(LV_MONTH_11, 7, 0) ||
    LPAD(LV_MONTH_12, 7, 0));
    IFMAINT.V_REC_CNT := IFMAINT.V_REC_CNT + 1;
    END LOOP;
    CLOSE CR_PART;
    /*TRAILER*/
    utl_file.put_line(F,
    RPAD('$EOF-', 5, ' ') || RPAD('320R', 4, ' ') ||
    RPAD(SUBSTR(IFMAINT.V_PANDA_CD, 1, 5), 5, ' ') ||
    RPAD(' ', 5, ' ') ||
    RPAD(IFMAINT.V_GEO_SALES_AREA_CD, 3, ' ') ||
    RPAD(TO_CHAR(SYSDATE, 'MM-DD-RR'), 6, ' ') ||
    LPAD(IFSMAINT.V_FILE_NUM, 2, 0) ||
    LPAD(IFMAINT.V_REC_CNT, 8, 0) || 'H' || '>' ||
    IFMAINT.V_REC_CNT);
    utl_file.fclose(F);
    IFMAINT.INSERT_HISTORY;
    END IF;
    END;
    FUNCTION CHECK_FILE_EXISTS RETURN BOOLEAN IS
    LB_FILE_EXIST BOOLEAN := FALSE;
    LN_FILE_LENGTH NUMBER;
    LN_BLOCK_SIZE NUMBER;
    BEGIN
    UTL_FILE.FGETATTR(IFMAINT.V_UTL_DIR_NAME,
    IFMAINT.V_FILE_NAME,
    LB_FILE_EXIST,
    LN_FILE_LENGTH,
    LN_BLOCK_SIZE);
    IF LB_FILE_EXIST THEN
    RETURN TRUE;
    END IF;
    RETURN FALSE;
    EXCEPTION
    WHEN OTHERS THEN
    RETURN FALSE;
    END;
    END;

    Try this:
    OPEN CR_PART;
    loop
    FETCH CR_PART BULK COLLECT
    INTO lv_cursor limit 1000;
    exit when CR_PART%notfound;
    FOR I IN lv_cursor.FIRST .. lv_cursor.LAST LOOP
    SELECT SUM(A.BILL_QTY)
    INTO LV_CURR_MONTH
    FROM PD_ISSUE A, PH_ISSUE B
    WHERE A.DOC_TYPE IN ('CRI', 'RRI', 'RSI', 'CSI')
    AND A.DOC_NUM = B.DOC_NUM
    AND B.DOC_DATE BETWEEN TRUNC(SYSDATE, 'MM') AND SYSDATE
    AND A.PART_NUM = LV_CURSOR(i).PART_NUM;
    FOR J IN 1 .. 12 LOOP
    SELECT SUM(A.BILL_QTY)
    INTO LV_MONTH_1
    FROM PD_ISSUE A, PH_ISSUE B
    WHERE A.DOC_TYPE IN ('CRI', 'RRI', 'RSI', 'CSI')
    AND A.DOC_NUM = B.DOC_NUM
    AND B.DOC_DATE BETWEEN lv_month(J).start_date and lv_month(J)
    .end_date
    AND A.PART_NUM = LV_CURSOR(i).PART_NUM;
    END LOOP;
    utl_file.put_line(F,
    RPAD('IL', 2, ' ') ||
    RPAD(TO_CHAR(SYSDATE, 'RRRRMMDD'), 8, ' ') ||
    RPAD(LV_CURSOR(I).ENGG_PREFIX, 6, ' ') ||
    RPAD(LV_CURSOR(I).ENGG_BASE, 8, ' ') ||
    RPAD(LV_CURSOR(I).ENGG_SUFFIX, 6, ' ') ||
    LPAD(LV_CURSOR(I).ON_HAND_QTY, 7, 0) ||
    LPAD(NVL(LV_CURR_MONTH, 0), 7, 0) ||
    LPAD(LV_MONTH_1, 7, 0) || LPAD(LV_MONTH_2, 7, 0) ||
    LPAD(LV_MONTH_3, 7, 0) || LPAD(LV_MONTH_4, 7, 0) ||
    LPAD(LV_MONTH_5, 7, 0) || LPAD(LV_MONTH_6, 7, 0) ||
    LPAD(LV_MONTH_7, 7, 0) || LPAD(LV_MONTH_8, 7, 0) ||
    LPAD(LV_MONTH_9, 7, 0) || LPAD(LV_MONTH_10, 7, 0) ||
    LPAD(LV_MONTH_11, 7, 0) ||
    LPAD(LV_MONTH_12, 7, 0));
    IFMAINT.V_REC_CNT := IFMAINT.V_REC_CNT + 1;
    END LOOP;
    end loop;
    CLOSE CR_PART;

Maybe you are looking for

  • IPod not recognized by itunes, driver device won't install?

    I've been at this for hours and I'm becoming rather frustrated. I've been using my 4g ipod touch since christmas and it's worked fine. I plug it into my new laptop, and it tells me that the device driver needs installed. I let it install, yet it's st

  • YouTube HD Export Preset (H.264)

    I've tried many different settings within this preset and every file stutters when played in Windows Media Player. Will it stutter when uploaded to YouTube?  I have not had the time to upload it yet but thought I would ask if anybody here has any exp

  • Events and Photos from DVD

    First let me say, as a former Windows user for many years, I'm am very happy to have made the change to iMac. Should have done it years ago. I was archiving photos on my old machine to a DVD and was copying them to my new iMac. I then imported them i

  • Exporting to a PDF from CR XI is different on different servers

    Post Author: gauravgupta2325 CA Forum: Deployment Hi, My application is installed at diffrent machines but reporting server is same for all the installed applications. The configuration of the First server is : - 1.  CrystalXI dot net runtime 2. Crys

  • Hyperion ERP Integrator training?

    I was browsing through the Oracle training courses available in the realm of data integration, specifically FDM's ERPI and was unable to locate anything. Does any such training exist? Or because it is a module/adapter of FDM there is no such specific