Forall ...........loop

Hi All,
I am using forall loop as below
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CREATE TYPE coords AS object(x NUMBER,y NUMBER);
CREATE TABLE a_temp (
n NUMBER NULL,
cr COORDS NULL
DECLARE
TYPE cur1 IS TABLE OF a_temp%ROWTYPE;
cur_var1 cur1;
BEGIN
SELECT * BULK COLLECT INTO cur_var1 FROM a_temp;
/*FOR i IN cur_var1.first..cur_var1.last LOOP
Dbms_Output.put_line(cur_var1(i).n||'-'||cur_var1(i).cr.x||','||cur_var1(i).cr.y);
END LOOP;*/
FORALL i IN cur_var1.first..cur_var1.last
INSERT INTO C_TEMP(n) VALUES(cur_var1(i).n);
END;
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
but geting below error:
ORA-06550: line 13, column 32:
PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND table of records
ORA-06550: line 13, column 32:
PLS-00382: expression is of wrong type
ORA-06550: line 13, column 32:
PL/SQL: ORA-22806: not an object or REF
ORA-06550: line 13, column 3:
PL/SQL: SQL Statement ignored
Please comment.......................
Thanks
Harry

Yes that we are able to do what is given in the link but what I am doing is ...
create a object type and using that in my table as column and then want to insert that data in another table that is giving error..
complete code is given as I am doing........
Please suggest in that code ...what is going wrong????
Thanks,
harry

Similar Messages

  • Whay FORALL loop is not Working.....

    hi Guys,
    I have created a procedure with Object as Argument.......
    CREATE OR Replace PROCEDURE Object_Student1(p student_detail1)
    AS
    BEGIN
    FORi in p.first .. p.last loop
    INSERT INTO Sample_mix VALUES (p(i));
    end loop;
    COMMIT;
    END Object_Student1;
    This above was not working..........After I have changed the PL/SQL in the INSERT statement....
    CREATE OR Replace PROCEDURE Object_Student1(p student_detail1)
    AS
    BEGIN
    FOR i in p.first .. p.last loop
    INSERT INTO Sample_mix VALUES (p(i).roll,P(i).SALARY,P(i).ADDRESS,P(i).Name,P(i).mobile);
    end Loop;
    COMMIT;
    END Object_Student1;
    now This is Running Successfully.... But After I changed From FOR Loop TO FORALL loop..
    CREATE OR Replace PROCEDURE Object_Student1(p student_detail1)
    AS
    BEGIN
    FORALL i in p.first .. p.last
    INSERT INTO Sample_mix VALUES (p(i).roll,P(i).SALARY,P(i).ADDRESS,P(i).Name,P(i).mobile);
    COMMIT;
    END Object_Student1;
    The Above Code is Not working..... giving the folloing ERRORS...
    LINE/COL ERROR
    5/32 PLS-00436: implementation restriction: cannot reference fields of
    BULK In-BIND table of records
    5/42 PLS-00436: implementation restriction: cannot reference fields of
    BULK In-BIND table of records
    5/54 PLS-00436: implementation restriction: cannot reference fields of
    BULK In-BIND table of records
    5/67 PLS-00436: implementation restriction: cannot reference fields of
    BULK In-BIND table of records
    LINE/COL ERROR
    Could anybody tell me why should This ForALL loop is not Working....??

    Yes Suresgh I tried.... But I got Same Error..... given below...
    1 CREATE OR REPLACE PROCEDURE ObjectPassing2(p student_detail1)
    2 AS
    3 BEGIN
    4 FORALL i in 1 .. p.Count
    5 INSERT INTO Sample_mix VALUES(p(i).Roll,p(i).Salary,p(i).Address,p(i).Name,p(i).Mobile);
    6 COMMIT;
    7* END ObjectPassing2;
    SQL> /
    Warning: Procedure created with compilation errors.
    SQL> sho err;
    Errors for PROCEDURE OBJECTPASSING2:
    LINE/COL ERROR
    5/33 PLS-00436: implementation restriction: cannot reference fields of
    BULK In-BIND table of records
    5/43 PLS-00436: implementation restriction: cannot reference fields of
    BULK In-BIND table of records
    5/55 PLS-00436: implementation restriction: cannot reference fields of
    BULK In-BIND table of records
    5/68 PLS-00436: implementation restriction: cannot reference fields of
    BULK In-BIND table of records
    LINE/COL ERROR
    5/78 PLS-00436: implementation restriction: cannot reference fields of
    BULK In-BIND table of records

  • Not woking FORALL loop in  Procedure related to OCCI

    hi Guys,
    I have created a procedure with Object as Argument....... give below details...
    My requirement is:
    Create a Userdefined type which is collection of Attribute e.g (Roll,Salary,Address,Name,Mobile)
    Create Index table OR Varray of Userdefined Type....
    Create a pocedure argument is Object of Type Varray Or IndexTable......
    FORALL.... Loop
    Insert Statement
    This procedure is Calling in OCCI.....
    PROCEDURE
    CREATE OR Replace PROCEDURE Object_Student(p student_detail)
    AS
    BEGIN
    FORi in p.first .. p.last loop
    INSERT INTO Sample_mix VALUES (p(i));
    end loop;
    COMMIT;
    END Object_Student;
    This above was not working..........
    ERROR:Not enough values....
    After that I changed the PL/SQL in the INSERT statement....
    CREATE OR Replace PROCEDURE Object_Student(p student_detail)
    AS
    BEGIN
    FOR i in p.first .. p.last loop
    INSERT INTO Sample_mix VALUES (p(i).roll,P(i).SALARY,P(i).ADDRESS,P(i).Name,P(i).mobile);
    end Loop;
    COMMIT;
    END Object_Student;
    This is Running Successfully....
    Result: Reading Records taking too much time.... OCCI
    Terefore , I changed From FOR Loop TO FORALL loop..
    CREATE OR Replace PROCEDURE Object_Student(p student_detail)
    AS
    BEGIN
    FORALL i in p.first .. p.last
    INSERT INTO Sample_mix VALUES (p(i));
    COMMIT;
    END Object_Student;
    ERROR: Not Enough values......
    then modified the procedure
    CREATE OR Replace PROCEDURE Object_Student(p student_detail)
    AS
    BEGIN
    FORALL i in p.first .. p.last
    INSERT INTO Sample_mix VALUES (p(i).roll,P(i).SALARY,P(i).ADDRESS,P(i).Name,P(i).mobile);
    COMMIT;
    END Object_Student;
    The Above Code is Not working..... giving the following ERRORS...
    LINE/COL ERROR
    5/32 PLS-00436: implementation restriction: cannot reference fields of
    BULK In-BIND table of records
    5/42 PLS-00436: implementation restriction: cannot reference fields of
    BULK In-BIND table of records
    5/54 PLS-00436: implementation restriction: cannot reference fields of
    BULK In-BIND table of records
    5/67 PLS-00436: implementation restriction: cannot reference fields of
    BULK In-BIND table of records
    LINE/COL ERROR
    Could anybody tell me why here ForALL loop is not Working....??
    Everything is successed... Only FORALL loop is not Working in the Procedure....
    Is there any Other way .... Please reply me ASAP
    Advance thanx for them....
    Sanjay

    I alreary added with same structure.....
    Still giving the Same Error
    I searched and got some help........inserted Like below example....
    CREATE OR Replace PROCEDURE emp_Proc(p emp_arr)
    AS
    BEGIN
    forall i in p.first .. p.last
    INSERT INTO emp VALUES p(i);
    COMMIT;
    END emp_Proc;
    LINE/COL ERROR
    5/2 PL/SQL: SQL Statement ignored
    5/2 PL/SQL: ORA-00932: inconsistent datatypes: expected - got -
    Is there any solve of folling Error....

  • LOOP inside FORALL in bulk binding

    Can I use a loop inside forall in bulk bind updates?
    as I understand, forall statement strictly loops through the length of the bulk limit size for the immediately following statement only.
    I am attempting to use a loop there to update more than one table.
    cursor c is select id from temp where dt_date > sysdate-30;
    BEGIN
    loop
    fetch c into v_id;
    limit 1000;
    forall i in 1..v_id.count
    UPDATE table_one set new_id = v_id(i);
    exit when C%NOTFOUND;
    end loop;
    end;
    I want to update another table table_two also immediately after updating table_one like this:
    forall i in 1..v_id.count
    UPDATE table_one set new_id = v_id(i);
    BEGIN select nvl(code,'N/A') into v_code from T_CODES where ID_NO = v_id(i); EXCEPTION WHEN NO_DATA_FOUND v_code='N/A'; END;
    UPDATE table_two set new_code =v_code;
    exit when C% not found.
    This is not working and when I run it, I get an error saying encountered BEGIN when one of the following is expected.
    I got around this by having another FOR loop just to set up the values in another array variable and using that value in another second forall loop to update table_two.
    Is there any way to do this multiple table udpates in bulkbinding under one forall loop that would enable to do some derivation/calculation if needed among variables [not array variables, regular datatype variables].
    Can we have like
    forall j in 1.. v_id.count
    LOOP
    update table 1;
    derive values for updating table 2;
    update table 2;
    END LOOP;
    Thank You.

    Well, without questioning reasions why do you want this, you are confusing bulk select and forall. You need:
    begin
        loop
          fetch c bulk collect into v_id limit 1000;
          exit when v_id.count = 0;
          forall i in 1..v_id.count
            UPDATE table_one set new_id = v_id(i);
        end loop;
    end;
    /SY.

  • PLS-00435: DML statement without BULK In-BIND cannot be used inside FORALL

    See code below: Have googled the error but not sure how to fix the code. ANy help would be most greatful.
    DECLARE
    CURSOR c1
    IS
    SELECT /*+ parallel(tr,8)*/ DISTINCT tr.ACC ACC, tr.MET_ID METID, to_char(max(TRUNC(PKG_LSR_IMPOSITION.convertXXMMDDToDate(tr.DATETR0))),'YYYY') dt
    FROM CTTR0FIL_CDC tr
    JOIN transaction_action_sd sd on (sd.TRANSACTION_CODE = tr.RESULT)
    WHERE sd.ACTION_TYPE = 'PAYMENT'
    and to_char(TRUNC(PKG_LSR_IMPOSITION.convertXXMMDDToDate(tr.DATETR0)),'YYYY') = '1987'
    GROUP BY tr.ACC, tr.MET_ID, to_char(TRUNC(PKG_LSR_IMPOSITION.convertXXMMDDToDate(tr.DATETR0)),'YYYY');
    SUBTYPE PAY_DATES IS c1%ROWTYPE;
    TYPE TMP_TABLE IS TABLE OF PAY_DATES INDEX BY PLS_INTEGER;
    TBROWS TMP_TABLE;
    temp VARCHAR2(100);
    Begin
    DBMS_OUTPUT.ENABLE(10000);
    OPEN c1;
    LOOP
    FETCH c1 BULK COLLECT INTO TBROWS LIMIT 1000;
    FORALL i IN 1..TBROWS.COUNT
    SELECT /*+ parallel(da,8)*/ da.ACC INTO temp
              FROM CTDA0FIL_CDC da
    WHERE da.ACC = TBROWS(i).ACC AND da.MET_ID = TBROWS(i).MET_ID AND da.ACC = '07000006P' AND da.MET_ID = 4;
         DBMS_OUTPUT.PUT_LINE('inside');
    EXIT WHEN c1%notfound;
    END LOOP;
    CLOSE c1;
    END;
    Thanks
    Simon

    I tried using a normal for loop instead of a forall loop (see code below). But this came up the error also see below. Or can I not use selects in this way???
    OPEN c1;
    LOOP
    FETCH c1 BULK COLLECT INTO tbrows LIMIT 1000;
    FOR i IN TBROWS.FIRST .. TBROWS.LAST
         LOOP
              SELECT /*+ parallel(da,8)*/ da.ACC INTO temp
              FROM CTDA0FIL_CDC da WHERE da.ACC = TBROWS(i).ACC AND da.MET_ID = TBROWS(i).MET_ID AND da.ACC = '07000006P' AND da.MET_ID = 4;
         DBMS_OUTPUT.PUT_LINE('inside');
    EXIT WHEN c1%notfound;
    END LOOP;
    END LOOP;
    CLOSE c1;
    END;
    Error:
    DECLARE
    ERROR at line 1:
    ORA-06502: PL/SQL: numeric or value error
    ORA-06512: at line 24

  • How to convert the following FORALL Update to direct SQL UPDATE statement

    I have a FORALL loop to update a table. It is taking too long. I want to rewrite the code to a direct UPDATE sql. Also, any other tips or hints which can help run this proc faster?
    CURSOR cur_bst_tm IS
    SELECT listagg(tm, ' ') WITHIN GROUP(ORDER BY con_addr_id) best_time,
           con_addr_id
       FROM   (select Trim(Upper(con_addr_id)) con_addr_id,
                      ||decode(Initcap(start_day),
                                      'Monday', 'm',
                                    'Tuesday', 'tu',
                                    'Wednesday', 'w',
                                    'Thursday', 'th',
                                    'Friday', 'f',
                                     Initcap(start_day))
                      ||'='
                      ||trunc(( ( TO_DATE(start_tm,'HH12:MI:SS PM') - trunc(TO_DATE(start_tm,'HH12:MI:SS PM')) ) * 24 * 60 ))
                      ||','
                      ||trunc(( ( TO_DATE(end_tm,'HH12:MI:SS PM') - trunc(TO_DATE(end_tm,'HH12:MI:SS PM')) ) * 24 * 60 )) tm
               FROM   (SELECT DISTINCT * FROM ODS_IDL_EDGE_OFFC_BST_TM)
                 WHERE con_addr_id is not null)
      GROUP  BY con_addr_id
      ORDER BY con_addr_id;
    TYPE ARRAY IS TABLE OF cur_bst_tm%ROWTYPE;
    l_data ARRAY;
    BEGIN
    OPEN cur_bst_tm;
         LOOP
        FETCH cur_bst_tm BULK COLLECT INTO l_data LIMIT 1000;
        FORALL i IN 1..l_data.COUNT
          UPDATE ODS_CONTACTS_ADDR tgt
          SET best_times = l_data(i).best_time,
          ODW_UPD_BY = 'IDL - MASS MARKET',
           ODW_UPD_DT = SYSDATE,
          ODW_UPD_BATCH_ID = '0'
          WHERE Upper(edge_id) = l_data(i).con_addr_id
           AND EXISTS (SELECT 1 FROM ods_idl_edge_cont_xref src
                       WHERE tgt.contacts_odw_id = src.contacts_odw_id
                          AND src.pc_flg='Y')  
        EXIT WHEN cur_bst_tm%NOTFOUND;
        END LOOP;
      CLOSE cur_bst_tm;Record count:-
    select count(*) from
    ODS_IDL_EDGE_OFFC_BST_TM;
    140,000
    SELECT count(*)
    FROM ods_idl_edge_cont_xref src
    WHERE src.pc_flg='Y';
    118,000
    SELECT count(*)
    FROM ODS_CONTACTS_ADDR;
    671,925
    Database version 11g.
    Execution Plan for the update:
    Operation     Object Name     Rows     Bytes     Cost     Object Node     In/Out     PStart     PStop
    UPDATE STATEMENT Optimizer Mode=ALL_ROWS          6 K          8120                     
    UPDATE     ODW_OWN2.ODS_CONTACTS_ADDR                                   
    HASH JOIN SEMI          6 K     256 K     8120                     
    TABLE ACCESS FULL     ODW_OWN2.ODS_CONTACTS_ADDR     6 K     203 K     7181                     
    TABLE ACCESS FULL     ODW_OWN2.ODS_IDL_EDGE_CONT_XREF     118 K     922 K     938
    Edited by: user10566312 on May 14, 2012 1:07 AM

    The code tag should be in lower case like this {noformat}{noformat}. Otherwise your code format will be lost.
    Here is a update statementupdate ods_contacts_addr tgt
    set (
              best_times, odw_upd_by, odw_upd_dt, odw_upd_batch_id
         ) =
              select best_time, odw_upd_by, odw_upd_dt, odw_upd_batch_id
              from (
                   select listagg(tm, ' ') within group(order by con_addr_id) best_time,
                        'IDL - MASS MARKET' odw_upd_by,
                        sysdate odw_upd_dt,
                        '0' odw_upd_batch_id,
                        con_addr_id
                   from (
                             select Trim(Upper(con_addr_id)) con_addr_id,
                                  ||decode(Initcap(start_day), 'Monday', 'm', 'Tuesday', 'tu', 'Wednesday', 'w', 'Thursday', 'th', 'Friday', 'f', Initcap(start_day))
                                  ||'='
                                  ||trunc(((TO_DATE(start_tm,'HH12:MI:SS PM')-trunc(TO_DATE(start_tm,'HH12:MI:SS PM')))*24*60 ))
                                  ||','
                                  ||trunc(((TO_DATE(end_tm,'HH12:MI:SS PM')-trunc(TO_DATE(end_tm,'HH12:MI:SS PM')))*24*60)) tm
                             FROM (
                                  select distinct * from ods_idl_edge_offc_bst_tm
                             WHERE con_addr_id is not null
                   group
                   by con_addr_id
              where upper(tgt.edge_id) = con_addr_id
    where exists
              SELECT 1
              FROM ods_idl_edge_cont_xref src
              WHERE tgt.contacts_odw_id = src.contacts_odw_id
              AND src.pc_flg='Y'
    and exists
              select null
              from (
                   SELECT listagg(tm, ' ') WITHIN GROUP(ORDER BY con_addr_id) best_time,
                        'IDL - MASS MARKET' odw_upd_by,
                        SYSDATE odw_upd_dt,
                        '0' odw_upd_batch_id,
                        con_addr_id
                   FROM (
                             select Trim(Upper(con_addr_id)) con_addr_id,
                                  ||decode(Initcap(start_day), 'Monday', 'm', 'Tuesday', 'tu', 'Wednesday', 'w', 'Thursday', 'th', 'Friday', 'f', Initcap(start_day))
                                  ||'='
                                  ||trunc(((TO_DATE(start_tm,'HH12:MI:SS PM')-trunc(TO_DATE(start_tm,'HH12:MI:SS PM')))*24*60 ))
                                  ||','
                                  ||trunc(((TO_DATE(end_tm,'HH12:MI:SS PM')-trunc(TO_DATE(end_tm,'HH12:MI:SS PM')))*24*60)) tm
                             FROM (
                                  SELECT DISTINCT * FROM ODS_IDL_EDGE_OFFC_BST_TM
                             WHERE con_addr_id is not null
                   GROUP
                   BY con_addr_id
              where upper(tgt.edge_id) = con_addr_id
    This is an untested code. If there is any syntax error then please fix it and try.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               

  • PLS-00801: internal error with FORALL

    I have the following procedure that I am trying to compile but I am getting an error:
    <pre>
    PROCEDURE procedure_1 AS
    cursor cur_1 is
    select column1 || column2 || column3 || column4 || column5 ||
    column6 || column7 || column8 as concat_column
    from table_1
    for update wait 5;
    type type_table_1 is table of varchar2(100);
    tab_1 type_table_1;
    bulk_error EXCEPTION;
    PRAGMA EXCEPTION_INIT(bulk_error, -24381);
    BEGIN
    open cur_1;
    loop
    fetch cur_1 bulk collect into tab_1 limit 100;
    exit when tab_1.COUNT = 0;
    forall ctr in 1 .. tab_1.COUNT save exceptions
    update table_1
    set column_20 = array_line(tab_1(ctr).concat_column);
    end loop;
    close cur_1;
    EXCEPTION
    when bulk_error then
    for i in 1 .. sql%bulk_exceptions.count loop
    NULL;
    end loop;
    END procedure_1;
    Error(622,21): PLS-00801: internal error [*** ASSERT at file pdw4.c, line 3572; Can't handle Object = -2147476152 in D_S_ED -2147476153.;
    The offending line seems to be the update statement inside the forall loop. I cannot tell why I am getting this error though as everything seems ok to me.
    Please help.
    Thanks

    And what are you trying to do? You are updating column20 in all rows in table_1 over and over. And what is array_line? Type type_table_1 is not a table of objects, so what is tab_1(ctr).concat_column? Without questioning code logic (although I already did :) ), remove that ".concat_column":
    set column_20 = array_line(tab_1(ctr));SY.

  • How to use BULK COLLECT, FORALL and TREAT

    There is a need to read match and update data from and into a custom table. The table would have about 3 millions rows and holds key numbers. BAsed on a field value of this custom table, relevant data needs to be fetched from joins of other tables and updated in the custom table. I plan to use BULK COLLECT and FORALL.
    All examples I have seen, do an insert into a table. How do I go about reading all values of a given field and fetching other relevant data and then updating the custom table with data fetched.
    Defined an object with specifics like this
    CREATE OR REPLACE TYPE imei_ot AS OBJECT (
    recid NUMBER,
    imei VARCHAR2(30),
    STORE VARCHAR2(100),
    status VARCHAR2(1),
    TIMESTAMP DATE,
    order_number VARCHAR2(30),
    order_type VARCHAR2(30),
    sku VARCHAR2(30),
    order_date DATE,
    attribute1 VARCHAR2(240),
    market VARCHAR2(240),
    processed_flag VARCHAR2(1),
    last_update_date DATE
    Now within a package procedure I have defined like this.
    type imei_ott is table of imei_ot;
    imei_ntt imei_ott;
    begin
    SELECT imei_ot (recid,
    imei,
    STORE,
    status,
    TIMESTAMP,
    order_number,
    order_type,
    sku,
    order_date,
    attribute1,
    market,
    processed_flag,
    last_update_date
    BULK COLLECT INTO imei_ntt
    FROM (SELECT stg.recid, stg.imei, cip.store_location, 'S',
    co.rtl_txn_timestamp, co.rtl_order_number, 'CUST',
    msi.segment1 || '.' || msi.segment3,
    TRUNC (co.txn_timestamp), col.part_number, 'ZZ',
    stg.processed_flag, SYSDATE
    FROM custom_orders co,
    custom_order_lines col,
    custom_stg stg,
    mtl_system_items_b msi
    WHERE co.header_id = col.header_id
    AND msi.inventory_item_id = col.inventory_item_id
    AND msi.organization_id =
    (SELECT organization_id
    FROM hr_all_organization_units_tl
    WHERE NAME = 'Item Master'
    AND source_lang = USERENV ('LANG'))
    AND stg.imei = col.serial_number
    AND stg.processed_flag = 'U');
    /* Update staging table in one go for COR order data */
    FORALL indx IN 1 .. imei_ntt.COUNT
    UPDATE custom_stg
    SET STORE = TREAT (imei_ntt (indx) AS imei_ot).STORE,
    status = TREAT (imei_ntt (indx) AS imei_ot).status,
    TIMESTAMP = TREAT (imei_ntt (indx) AS imei_ot).TIMESTAMP,
    order_number = TREAT (imei_ntt (indx) AS imei_ot).order_number,
    order_type = TREAT (imei_ntt (indx) AS imei_ot).order_type,
    sku = TREAT (imei_ntt (indx) AS imei_ot).sku,
    order_date = TREAT (imei_ntt (indx) AS imei_ot).order_date,
    attribute1 = TREAT (imei_ntt (indx) AS imei_ot).attribute1,
    market = TREAT (imei_ntt (indx) AS imei_ot).market,
    processed_flag =
    TREAT (imei_ntt (indx) AS imei_ot).processed_flag,
    last_update_date =
    TREAT (imei_ntt (indx) AS imei_ot).last_update_date
    WHERE recid = TREAT (imei_ntt (indx) AS imei_ot).recid
    AND imei = TREAT (imei_ntt (indx) AS imei_ot).imei;
    DBMS_OUTPUT.put_line ( TO_CHAR (SQL%ROWCOUNT)
    || ' rows updated using Bulk Collect / For All.'
    EXCEPTION
    WHEN NO_DATA_FOUND
    THEN
    DBMS_OUTPUT.put_line ('No Data: ' || SQLERRM);
    WHEN OTHERS
    THEN
    DBMS_OUTPUT.put_line ('Other Error: ' || SQLERRM);
    END;
    Now for the unfortunate part. When I compile the pkg, I face an error
    PL/SQL: ORA-00904: "LAST_UPDATE_DATE": invalid identifier
    I am not sure where I am wrong. Object type has the last update date field and the custom table also has the same field.
    Could someone please throw some light and suggestion?
    Thanks
    uds

    I suspect your error comes from the »bulk collect into« and not from the »forall loop«.
    From a first glance you need to alias sysdate with last_update_date and some of the other select items need to be aliased as well :
    But a simplified version would be
    select imei_ot (stg.recid,
                    stg.imei,
                    cip.store_location,
                    'S',
                    co.rtl_txn_timestamp,
                    co.rtl_order_number,
                    'CUST',
                    msi.segment1 || '.' || msi.segment3,
                    trunc (co.txn_timestamp),
                    col.part_number,
                    'ZZ',
                    stg.processed_flag,
                    sysdate
    bulk collect into imei_ntt
      from custom_orders co,
           custom_order_lines col,
           custom_stg stg,
           mtl_system_items_b msi
    where co.header_id = col.header_id
       and msi.inventory_item_id = col.inventory_item_id
       and msi.organization_id =
                  (select organization_id
                     from hr_all_organization_units_tl
                    where name = 'Item Master' and source_lang = userenv ('LANG'))
       and stg.imei = col.serial_number
       and stg.processed_flag = 'U';
    ...

  • How to bypass FORALL in SELECT .. BULK COLLECT

    Using Oracle 8.1.7
    I developed a stored procedure LOT
    TYPE TIds IS Table of Integer;
    TYPE TFloats IS Table of Float;
    procedure LOT(Ids TIds) ....
    is
    Prices TFloats;
    Quantities TFloats;
    begin
    for I in 1..Ids.Count loop
    SELECT ...
    BULK COLLECT INTO Prices, Quantities, ...
    WHERE ... = Ids(I)
    end loop;
    end;
    For each Id from IDS collection my procedure SELECTs several
    rows (avg. 2 or 3 rows). IDS contains about 1000 - 10000 items.
    Productivity is very low.
    Because is the many context switches
    between SQL engine and PL/SQL engine.
    The point is to collect all data by single 'huge' SELECT instead
    of numerous 'short' SELECTs.
    I. e. I need somethng like
    FORALL I in 1..Ids.Count
    SELECT ...
    BULK COLLECT INTO Prices, Quantities, ...
    WHERE ... = Ids(I)
    or like this
    FORALL I in 1..Ids.Count
    SELECT ...
    WHERE ... = Ids(I) RETURNING ... BULK COLLECT INTO ...
    I know it's invalid syntax because PL/SQL doesn't support BULK
    COLLECT clause for SELECT in FORALL loop.
    How should I bypass the problem?
    Is a proper way to use temporary table as storehouse for IDS collection?
    Something else?
    Regards,
    Piter Elagin (AlienZzzz)

    Hi Ivan,
       the problem is that the port is configurable at installation time.  On a NetWeaver 04 portal, I believe the default was 50000.  That should get you to one of the servers.  You may try 50100, 50200, etc. 
    You can also ask who ever did the installation.  the other place to look is the webdispatcher configuration file.  It would have to know the server and port to dispatch to.
    Hope that helps.
    John

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

  • Forall exception rollback

    Hi Guys,
    I have a forall statement that I want to continue processing if it hits an exception, and rollback anything it fails on. I have limits set so I am only lifting 300 records at a time, but if only one record fails in the forall, then i want the other 299 to process and commit, and only rollback that one failure..is it possible? This is using oracle 10g.
    Example snippet below, the "dots" are just were I have removed unneeded code for this example. I want to know if I can add a rollback in the EXCEPTION that will rollback the forall failure for the one saved exception, and the "commit" will commit the remaining 299 that were success?
    BEGIN
    LOOP
    FETCH cursor1
    BULK COLLECT INTO table1 LIMIT 300;
    IF table1.COUNT > 0
    THEN
    BEGIN
    FORALL i IN 1 .. table1.COUNT SAVE EXCEPTIONS
    END IF;
    EXIT WHENtable1.COUNT = 0;
    table1.DELETE;
    END LOOP;
    CLOSE cursor1;
    COMMIT;
    EXCEPTION
    WHEN OTHERS
    THEN
    ROLLBACK;
    END;
    Edited by: fixxxer on 13-Oct-2011 01:36

    You can not do INSERT and DELETE using same FORALL statelemt. For that you have to create seperate copy of Collection.
    If you want to ROLLBACK everything thnen omit the SAVE EXCEPTION statement in FORALL.
    You can gothrough below FORALL restriction...
    Restrictions
    The following restrictions apply to the FORALL statement:
    •You cannot loop through the elements of an associative array that has a string type for the key.
    •Within a FORALL loop, you cannot refer to the same collection in both the SET clause and the WHERE clause of an UPDATE statement. You might need to make a second copy of the collection and refer to the new name in the WHERE clause.
    •You can use the FORALL statement only in server-side programs, not in client-side programs.
    •The INSERT, UPDATE, or DELETE statement must reference at least one collection. For example, a FORALL statement that inserts a set of constant values in a loop raises an exception.
    •When you specify an explicit range, all collection elements in that range must exist. If an element is missing or was deleted, you get an error.
    •When you use the INDICES OF or VALUES OF clauses, all the collections referenced in the DML statement must have subscripts matching the values of the index variable. Make sure that any DELETE, EXTEND, and so on operations are applied to all the collections so that they have the same set of subscripts. If any of the collections is missing a referenced element, you get an error. If you use the SAVE EXCEPTIONS clause, this error is treated like any other error and does not stop the FORALL statement.
    •You cannot refer to individual record fields within DML statements called by a FORALL statement. Instead, you can specify the entire record with the SET ROW clause in an UPDATE statement, or the VALUES clause in an INSERT statement.
    •Collection subscripts must be just the index variable rather than an expression, such as i rather than i+1.
    •The cursor attribute %BULK_ROWCOUNT cannot be assigned to other collections, or be passed as a parameter to subprograms.

  • FORALL and TRUNC

    Hi All
    I am having an issue in my FORALL loop and I am thinking that I might not understand this properly.
    Basically I am just updating a date in a table but the dates have timestamps. I trunc the date but the column always ends up as null.
    code is simple
    cursor list is select date from table1;
    open list
    fetch list bulk collect into l_date
    forall i in 1.. 100
    update table2 set date = trunc(l_date(i)) where id = id(i);
    end loop
    close list
    notice the trunc inside my forall loop. it seems to null this value.
    Is this behaviour correct?
    Thanks in advance

    clueless wrote:
    The code was just to show what I was doing.
    I understand using the word date is bad practice. What I am after is why the value in the FORALL loop ends up being null.
    Outside the FORALL loop the trunc(date) would just round to the nearest day.
    cursor list is select id, effdate from table1;
    open list
    fetch list bulk collect into l_effdateI believe this is not the real code.
    what is l_effdate type ?
    forall i in 1.. 100
    update table2 set effdate = trunc(l_effdate(i)) where id = id(i);
    end loop
    close list
    have you make sure the value of (l_effdate(i)) is not null? try to show with dbms_output.put_line
    change your forall with for loop if you want to run debug for testing.
    if your fetch is correct, it will give you exact same result

  • Two DML operations in one FORALL?

    Hi all,
    In 11g is it possible to make two dml operations in one Forall loop?
    For example:
    SQL> create table xx_test (col1 number, col2 number, col3 number);
    Table created
    SQL> create table xx_test1 (col1 number, col2 number, col3 number);
    Table created
    SQL> insert into xx_test values(1,2,3);
    1 row inserted
    SQL>  insert into xx_test values(1,2,3);
    1 row inserted
    SQL>  insert into xx_test values(4,5,6);
    1 row inserted
    SQL>  insert into xx_test1 values(6,7,8);
    1 row inserted
    SQL> declare
      2  cursor c is select col1, col2, col3 from xx_test;
      3  type t is table of c%rowtype;
      4  v t;
      5  begin
      6   open c;
      7  loop
      8  fetch c bulk collect into v limit 1000;
      9   forall i in 1..v.count
    10   update xx_test1
    11  set col1 = v(i).col2;
    12 
    13  insert into xx_test1(col1,col2,col3) values(v(i).col1,v(i).col2,v(i).col3);
    14 
    15  exit when c%notfound;
    16  end loop;
    17 
    18  end;
    ORA-06550: line 14, column 50:
    PLS-00201: identifier 'I' must be declared
    ORA-06550: line 14, column 50:
    PLS-00201: identifier 'I' must be declared
    ORA-06550: line 14, column 48:
    PL/SQL: ORA-00904: : invalid identifier
    ORA-06550: line 14, column 4:
    PL/SQL: SQL Statement ignoredany ideas? I know that this can be achieved by processing row by row but in my case the cursor retrieves a lot of rows...
    Thanks in advance,
    Alexander.

    Stew, a bulk bind from an OCI client looks as follows:
    OCIStmtPrepare()
    OCIBindByName()/OCIBindByPos() (binding a host array)
    while some-condition loop
      fill host array
      OCIStmtExecute()  (specify the number of elements in array via the iters param)
    end loopThe statement is executed once for each array element - according to the OCI guide. So in the case of sending a 100 elements, the statement will be executed (iterated) by Oracle, a 100 times. It however is not exactly clear on how the server-side deals with this execution.
    The issue you raised with cursor execution counts, seems to be whether the statement is single statement, or single statement with nested statements.
    I have written an OCI client doing the exact same tests as were done in PL/SQL using FORALL in this thread.
    If the SQL statement executed is SQL, the cursor that is created is executed only "once" (not exactly true as multiple rows are inserted using a single row DML).
    If the statement is PL/SQL, the cursor that is created, is executed "once". So pretty much the same behaviour. However, as this statement contains "nested" SQLs (the actual DML statements), these also need to be parsed and executed as cursors. In which case you see these as being executed a 100 times (once per element in for the bind array).
    The issue is whether or not the FORALL DML statement is executed once (as it would appear from the executions column), or not?
    It would seem that there is some funky happening (some kind of call optimisation perhaps?) when Oracle deals with an array bind - as the cursor seems to be executed once. But that in fact is not the case as that cursor only inserts a single row. And multiple rows are inserted.
    E.g. simplistic example to see how many times the FORALL DML statement is executed:
    SQL> create sequence emp_id_seq
      2          start with 1
      3          increment by 1
      4          nocycle
      5          nomaxvalue;
    Sequence created.
    SQL> --// add a PL/SQL user function wrapper for the sequence
    SQL> create or replace function GetNextEmpID return number is
      2          id      number;
      3  begin
      4          select emp_id_seq.NextVal into id from dual;  --// explicit SQL statement
      5          return( id );
      6  end;
      7  /
    Function created.
    SQL>
    SQL> declare
      2          cursor c is
      3          select empno, ename, job from emp;
      4 
      5          type TBuffer is table of c%RowType;
      6          buffer  TBuffer;
      7  begin
      8          open c;
      9          loop
    10                  fetch c bulk collect into buffer limit 100;
    11 
    12                  forall i in 1..buffer.Count
    13                          insert into tab1 values( GetNextEmpID(), buffer(i).ename );
    14                  exit when c%NotFound;
    15          end loop;
    16          close c;
    17  end;
    18  /
    PL/SQL procedure successfully completed.
    SQL>
    SQL> select
      2          executions,
      3          sql_text
      4  from       v$sql
      5  where      sql_text like 'INSERT INTO TAB1%'
      6  or sql_text like 'SELECT EMP_ID_SEQ%';
    EXECUTIONS SQL_TEXT
            14 SELECT EMP_ID_SEQ.NEXTVAL FROM DUAL
             1 INSERT INTO TAB1 VALUES( GETNEXTEMPID(), :B1So the insert seems to have been executed once. However, the wrapper was called 14 times and its SQL statement was called 14 times. Once per bind array value.
    So there do seem to be some kind of optimisation on the Oracle side - however, it does not mean that the FORALL statement is not using bulk/array binding. It is. And that is what the FORALL statement is designed to do.

  • Can we use dbms_output.put_line package with forall statement

    Hello Everybody
    Can we use dbms_output.put_line package with forall or can we use insert,update and delete only
    declare
    type emp_rec is table of emp%rowtype
    index by binary_integer;
    t emp_rec;
    begin
    select * bulk collect into t from emp;
    forall i in t.first..t.last
    dbms_output.put_line(t(i).name);
    end;Thanks & Regards
    peeyush
    Edited by: Peeyush on Nov 25, 2010 11:45 PM

    MichaelS wrote:
    Well as the docs explain (though not very clear and detailed, I admit) you can use a dynamic sql statement (execute immediate) with FORALL.You got me interested in the performance side doing this Michael - running PL/SQL code via a FORALL loop.
    It is faster than using a normal FOR loop to execute dynamic PL/SQL - a bit surprising as I expected another context switch to be in there. But seems like the PL/SQL engine is a more clever at optimisation than what I originally credited it with.. ;-)
    Of course - pre-compiled/static PL/SQL code in a FOR loop is the fastest, as expected.
    SQL> declare
      2          type TNumbers is table of number;
      3 
      4          type TTimes is record(
      5                  for_all number,
      6                  for_dynamic number,
      7                  for_static number
      8          );
      9 
    10          type TTimesTable is table of TTimes;
    11 
    12          MAX_ITERATIONS  constant number := 10;
    13 
    14          plBlock         varchar2(1000) :=
    15          'declare i number;
    16          begin i:= :var / 10; end;';
    17 
    18          performance     TTimesTable;
    19          t1              number;
    20          bindVar         TNumbers;
    21          n               number;
    22  begin
    23          select
    24                  level bulk collect into bindVar
    25          from    dual
    26          connect by level <= 10000;
    27 
    28          dbms_output.put_line( 'Iterations: '||bindVar.Count||' for loop cycle(s)' );
    29 
    30          performance := new TTimesTable();
    31          performance.Extend( MAX_ITERATIONS );
    32 
    33          for j in 1..MAX_ITERATIONS
    34          loop
    35                  t1 := dbms_utility.get_time;
    36                  forall i in 1..bindVar.Count
    37                          execute immediate plBlock using bindVar(i);
    38                  performance(j).for_all := dbms_utility.get_time-t1;
    39 
    40                  t1 := dbms_utility.get_time;
    41                  for i in 1..bindVar.Count
    42                  loop
    43                          execute immediate plBlock using bindVar(i);
    44                  end loop;
    45                  performance(j).for_dynamic := dbms_utility.get_time-t1;
    46 
    47                  t1 := dbms_utility.get_time;
    48                  for i in 1..bindVar.Count
    49                  loop
    50                          n := bindVar(i) / 10;
    51                  end loop;
    52                  performance(j).for_static := dbms_utility.get_time-t1;
    53          end loop;
    54 
    55          dbms_output.put_line( 'Times in 100th of a second' );
    56          dbms_output.put_line( rpad('for all',15) || rpad('for dynamic',15) || rpad('for static',15) );
    57          for i in 1..performance.Count
    58          loop
    59                  dbms_output.put_line(
    60                          rpad( performance(i).for_all, 15 )||' '||
    61                          rpad( performance(i).for_dynamic, 15 )||' '||
    62                          rpad( performance(i).for_static, 15)
    63                  );
    64          end loop;
    65 
    66  end;
    67  /
    Iterations: 10000 for loop cycle(s)
    Times in 100th of a second
    for all        for dynamic    for static
    10              72              0
    6               37              0
    6               37              0
    6               37              0
    6               36              0
    6               37              1
    5               37              0
    5               37              0
    6               37              1
    5               37              0
    PL/SQL procedure successfully completed.
    SQL>

  • How to view errors if bulk collect has thrown errors

    Hi,
    I have few questions.
    1.How to view error whether bulk collect is successful or not
    2.What is identified & unidentified relationships in ERWIN
    3.How to see the errors whether the sql loder is successful or not
    and how to open the log file.Is there any specific command in UNIX
    which tells loader is successful or thrown error
    4.When executing the pl/sql procedure from UNIX.how to check for errors.
    Please provide the answers for this
    Thanks

    Use SAVE EXCEPTIONS clause in your FORALL loop.
    Is this for homework/test?

Maybe you are looking for