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.

Similar Messages

  • Workaround for opening a strongly typed cursor using native dynamic SQL

    Hi All,
    In reading the PL/SQL documentation for Oracle 9i, I noted that the OPEN-FOR
    statement with a dynamic SQL string only allows the use of weakly typed cursors.
    I have verified this limitation with my own experimentation as follows:
    DECLARE
    type rec_type is record(
    str     varchar2(40),
    num     number(22)
    type cur_type is ref cursor return rec_type;
    my_cur     cur_type;
    que     varchar2(100);
    tab     varchar2(40);
    BEGIN
    tab := 'dynamic_table_name';
    que := 'select key_name, key_value from ' || tab || ' where key_name like ''01%''';
    open my_cur for que;
    loop
    if my_cur%found then
    dbms_output.put_line('source_name: ' || my_cur.str || ', page_sn: ' || my_cur.num);
    exit;
    end if;
    end loop;
    close my_cur;
    END;
    Running the above trivial example in an anonymous sql block yields the following
    errors as expected:
    ORA-06550: line 10, column 8:
    PLS-00455: cursor 'MY_CUR' cannot be used in dynamic SQL OPEN statement
    ORA-06550: line 10, column 3:
    PL/SQL: Statement ignored
    ORA-06550: line 13, column 54:
    PLS-00487: Invalid reference to variable 'MY_CUR'
    ORA-06550: line 13, column 7:
    PL/SQL: Statement ignored
    Is there a workaround to the situation? Since I do not know the table name at run
    time, I must use Native Dynamic SQL. I have a long and complex record type
    that I wish to return through JDBC using the REFCURSOR Oracle type in order to
    avoid having to register an inordinate number of OUT parameters. Moreover, I
    would like to return potentially one or more results in a ResultSet. Using the
    standard method of registering native SQL types for the IN and OUT bindings
    can only return one result. Hence the reason I would like to return a strong
    cursor type. Also, the type of query I am doing is complex, and needs to be
    executed in a PL/SQL procedure for performance reasons. Therefore simply
    executing a SELECT query dynamically built up on the the JDBC client won't
    do the trick.
    If anybody has experience with a similar problem and would like to volunteer
    information on their workaround, I would really appreciate it.
    Best Regards,
    J. Metcalf

    We can use strongly-typed REF CURSORs in DNS, but the typing derives from a table e.g.
    TYPE EmpCurTyp IS REF CURSOR RETURN emp%ROWTYPE;
    so the problem is your use of "return rec_type" bit.
    Forgive my bluntness but I think you have misunderstood strong and weak typing. You actually want to be using weakly-typed cursors. I mean this:
    Moreover, I would like to return potentially one or more results in a ResultSet. suggests that the structure of your resultset may vary, which is precisely what a weakly-typed ref cursor allows us to do. Then we can use the JDBC metadata methods to interrogate the structure of the resultset, innit.
    so try this:
    DECLARE
    type cur_type is ref cursor;
    my_cur cur_type;
    que varchar2(100);
    tab varchar2(40);
    BEGIN
    tab := 'dynamic_table_name';
    que := 'select key_name, key_value from ' || tab || ' where key_name like ''01%''';
    open my_cur for que;
    loop
    if my_cur%found then
    dbms_output.put_line('source_name: ' || my_cur.str || ', page_sn: ' || my_cur.num);
    exit;
    end if;
    end loop;
    close my_cur;
    END;
    ras malai, APC
    Cheers, APC

  • PLS-00455: cursor 'CUR_1' cannot be used in dynamic SQL OPEN statement

    create or replace function f_my_test_func
    return refcur_pkg.refcur_t1
    is
    cur_1  refcur_pkg.refcur_t1;
    begin
    open cur_1
    for
    'select * from dept';
    return cur_1;
    exception
    when others
    then
    insert into ddl_log (SQLTEXT)
    values
    ('fucntion error'); 
    end;

    I would suggest that cur_1 refcur_pkg.refcur_t1 is a stongly typed ref cursor i.e. it has RETURN dept%ROWTYPE or something similar in the declaration. You can't use strongly typed ref cursors with dynamic SQL in this way. The declaration should be weakly typed or just use sys_refcursor.
    DTYLER_APP@pssdev2> DECLARE
      2
      3      TYPE t_Strong   IS REF CURSOR RETURN dual%ROWTYPE;
      4
      5      lc_Strong       t_Strong;
      6
      7  BEGIN
      8
      9      OPEN lc_Strong FOR
    10      'SELECT * FROM dual';
    11
    12  END;
    13  /
        OPEN lc_Strong FOR
    ERROR at line 9:
    ORA-06550: line 9, column 10:
    PLS-00455: cursor 'LC_STRONG' cannot be used in dynamic SQL OPEN statement
    ORA-06550: line 9, column 5:
    PL/SQL: Statement ignored
    DTYLER_APP@pssdev2>
    DTYLER_APP@pssdev2> DECLARE
      2
      3      TYPE t_Weak   IS REF CURSOR;
      4
      5      lc_Weak       t_Weak;
      6
      7  BEGIN
      8
      9      OPEN lc_Weak FOR
    10      'SELECT * FROM dual';
    11
    12  END;
    13  /
    PL/SQL procedure successfully completed.
    DTYLER_APP@pssdev2> DECLARE
      2
      3      lc_Weak       sys_refcursor;
      4
      5  BEGIN
      6
      7      OPEN lc_Weak FOR
      8      'SELECT * FROM dual';
      9
    10  END;
    11  /
    PL/SQL procedure successfully completed.
    DTYLER_APP@pssdev2>HTH
    David

  • 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 ;-)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               

  • How to use table type in bulk collect

    Hi experts,
    How to use table type in bulk collect see the procedure used( oracle 10g)
    and error is
    PLS-00597: expression 'REQ_REC' in the INTO list is of wrong type
    CREATE OR REPLACE PROCEDURE SAMPLE_SP IS
    TYPE TYP_A AS OBJECT
    ( COLMN1 TABLE1.COLM1%TYPE,
    COLMN2 TABLE1.COLM2%TYPE,
    COLMN3 TABLE1.COLM3%TYPE
    TYPE REC_A IS TABLE OF TYP_A;
    REQ_REC A_REC;
    CURSOR REQ_CUR IS SELECT COLM1,COLM2,COLM3 FROM TABLE1 WHERE <CONDITION>;
    BEGIN
    OPEN REQ_REC;
    LOOP
    EXIT WHEN REQ_REC%NOTFOUND;
    FETCH REQ_REC BULK COLLECT INTO REQ_REC LIMIT 1000;
    FOR I IN 1..REQ_REC.COUNT
    LOOP
    <insert statement>
    END LOOP;
    COMMIT;
    END LOOP;
    END SAMPLE_SP;
    Many thanks,
    Kalinga

    ok but that is not an issue..
    Hi experts,
    How to use table type in bulk collect see the procedure used( oracle 10g)
    and error is
    PLS-00597: expression 'REQ_REC' in the INTO list is of wrong type
    CREATE OR REPLACE PROCEDURE SAMPLE_SP IS
    TYPE TYP_A AS OBJECT
    ( COLMN1 TABLE1.COLM1%TYPE,
    COLMN2 TABLE1.COLM2%TYPE,
    COLMN3 TABLE1.COLM3%TYPE
    TYPE REC_A IS TABLE OF TYP_A;
    REQ_REC A_REC;
    CURSOR REQ_CUR IS SELECT COLM1,COLM2,COLM3 FROM TABLE1 WHERE <CONDITION>;
    BEGIN
    OPEN REQ_CUR;
    LOOP
    EXIT WHEN REQ_REC%NOTFOUND;
    FETCH REQ_REC BULK COLLECT INTO REQ_REC LIMIT 1000;
    FOR I IN 1..REQ_REC.COUNT
    LOOP
    <insert statement>
    END LOOP;
    COMMIT;
    END LOOP;
    END SAMPLE_SP;
    Many thanks,
    Kalinga
    Message was edited by:
    Kalinga

  • Exceptional handling using Bulk Collect FORALL

    Hi Members,
    Following are by DB details
    SELECT * FROM v$version;                 
    Oracle9i Enterprise Edition Release 9.2.0.7.0 - 64bit Production
    PL/SQL Release 9.2.0.7.0 - Production
    CORE     9.2.0.7.0     Production
    TNS for HPUX: Version 9.2.0.7.0 - Production
    NLSRTL Version 9.2.0.7.0 - ProductionI need to handle exception during Bulk Collect FORALL operation and update the table column with Status_flag as 'E' for given item name and extension id. Below is the code snippet for the same.
    declare
      k  NUMBER;
    cursor c_list_price
    IS
    SELECT  /*+ leading(a)  */    item_name,
                             'PUBLISH_TO_PRICE_CATALOG' ATTRIBUTE_NAME,
                             MAX(DECODE (attribute_name,
                                         'PUBLISH_TO_PRICE_CATALOG',
                                         attribute_value))
                                ATTRIBUTE_VALUE,
                             NULL GEOGRAPHY_LEVEL,
                             NULL GEOGRAPHY_VALUE,
                             NULL INCLUDE_GEOGRAPHY,
                             NULL EFFECTIVE_START_DATE,
                             NULL EFFECTIVE_TO_DATE,
                             EXTENSION_ID,
                             NULL PRICING_UNIT,
                             NULL ATTRIBUTE_FROM,
                             NULL ATTRIBUTE_TO,
                             NULL FIXED_BASE_PRICE,
                             NULL PARENT_ATTRIBUTE,
                             NULL DURATION_QUANTITY,
                             NULL ATTRIBUTE2,
                             NULL ATTRIBUTE3,
                             NULL ATTRIBUTE4,
                             NULL ATTRIBUTE5,
                             NULL ATTRIBUTE6,
                             NULL ATTRIBUTE7,
                             NULL ATTRIBUTE8,
                             NULL ATTRIBUTE9,
                             NULL ATTRIBUTE10,
                             NULL ATTRIBUTE11,
                             NULL ATTRIBUTE12,
                             NULL ATTRIBUTE13,
                             NULL ATTRIBUTE14,
                             NULL ATTRIBUTE15,
                             --ORG_CODE,
                             ITEM_CATALOG_CATEGORY ITEM_CATEGORY,
                             a.INVENTORY_ITEM_ID INVENTORY_ITEM_ID
                      FROM   XXCPD_ITM_SEC_UDA_DETAILS_TB a
                     WHERE   DECODE(attribute_group_name,'LIST_PRICE',DECODE(STATUS_FLAG,'E',1,'P',2,3)
                                                                                                       ,'XXITM_FORM_PRICING_HS',DECODE(STATUS_FLAG,'E',4,'P',5,6)
                                                                                                       ,'XXITM_FORM_PRICING_SB',DECODE(STATUS_FLAG,'E',4,'P',5,6)
                                                                                                       ,'XXITM_ADV_FORM_PRICING_HS',DECODE(STATUS_FLAG,'E',7,'P',8,9)
                                                                                                       ,'XXITM_ADV_FORM_PRICING_SB',DECODE(STATUS_FLAG,'E',7,'P',8,9)
                                                                                                       ,'XXITM_ADV_FORM_PRICING_HWSW',DECODE(STATUS_FLAG,'E',10,'P',11,12)
                                                                                                       ,'XXITM_ADV_FORM_PRICING_SWSUB',DECODE(STATUS_FLAG,'E',10,'P',11,12)
                                                                                                       ,'XXITM_ROUTE_TO_MARKET',DECODE(STATUS_FLAG,'E',13,'P',14,15)) in (1,2,3)
                             AND exists(select /*+ no_merge */  '1' from mtl_system_items_b b where a.inventory_item_id=b.inventory_item_id and b.organization_id=1)
                  GROUP BY   item_name,
                             extension_id,
                             ITEM_CATALOG_CATEGORY,
                             INVENTORY_ITEM_ID;
    TYPE myarray IS TABLE OF c_list_price%ROWTYPE;
    c_lp myarray;
    BEGIN
      OPEN c_list_price;
      LOOP
      FETCH  c_list_price BULK COLLECT INTO  c_lp
                                      LIMIT 50000;
      IF c_lp.count = 0 THEN
        EXIT;
      END IF;
      Begin
      FORALL i IN c_lp.FIRST..c_lp.LAST SAVE EXCEPTIONS
        INSERT /*+append*/ INTO XXCPD_ITEM_PRICING_ATTR_BKP2(
                                                                   line_id,
                                                                   ITEM_NAME,
                                                                   ATTRIBUTE_NAME,
                                                                   ATTRIBUTE_VALUE,
                                                                   GEOGRAPHY_LEVEL,
                                                                   GEOGRAPHY_VALUE,
                                                                   INCLUDE_GEOGRAPHY,
                                                                   EFFECTIVE_START_DATE,
                                                                   EFFECTIVE_TO_DATE,
                                                                   EXTENSION_ID,
                                                                   PRICING_UNIT,
                                                                   ATTRIBUTE_FROM,
                                                                   ATTRIBUTE_TO,
                                                                   FIXED_BASE_PRICE,
                                                                   PARENT_ATTRIBUTE,
                                                                   DURATION_QUANTITY,
                                                                   ATTRIBUTE2,
                                                                   ATTRIBUTE3,
                                                                   ATTRIBUTE4,
                                                                   ATTRIBUTE5,
                                                                   ATTRIBUTE6,
                                                                   ATTRIBUTE7,
                                                                   ATTRIBUTE8,
                                                                   ATTRIBUTE9,
                                                                   ATTRIBUTE10,
                                                                   ATTRIBUTE11,
                                                                   ATTRIBUTE12,
                                                                   ATTRIBUTE13,
                                                                   ATTRIBUTE14,
                                                                   ATTRIBUTE15,
                                                                   ITEM_CATEGORY,
                                                                   INVENTORY_ITEM_ID
                                                            VALUES
                                                                   xxcpd.xxcpd_if_prc_line_id_s.NEXTVAL
                                                                  ,c_lp(i).ITEM_NAME
                                                                  ,c_lp(i).ATTRIBUTE_NAME     
                                                                  ,c_lp(i).ATTRIBUTE_VALUE    
                                                                  ,c_lp(i).GEOGRAPHY_LEVEL    
                                                                  ,c_lp(i).GEOGRAPHY_VALUE    
                                                                  ,c_lp(i).INCLUDE_GEOGRAPHY  
                                                                  ,c_lp(i).EFFECTIVE_START_DATE
                                                                  ,c_lp(i).EFFECTIVE_TO_DATE  
                                                                  ,c_lp(i).EXTENSION_ID       
                                                                  ,c_lp(i).PRICING_UNIT       
                                                                  ,c_lp(i).ATTRIBUTE_FROM     
                                                                  ,c_lp(i).ATTRIBUTE_TO       
                                                                  ,c_lp(i).FIXED_BASE_PRICE  
                                                                  ,c_lp(i).PARENT_ATTRIBUTE   
                                                                  ,c_lp(i).DURATION_QUANTITY  
                                                                  ,c_lp(i).ATTRIBUTE2         
                                                                  ,c_lp(i).ATTRIBUTE3         
                                                                  ,c_lp(i).ATTRIBUTE4         
                                                                  ,c_lp(i).ATTRIBUTE5         
                                                                  ,c_lp(i).ATTRIBUTE6         
                                                                  ,c_lp(i).ATTRIBUTE7         
                                                                  ,c_lp(i).ATTRIBUTE8         
                                                                  ,c_lp(i).ATTRIBUTE9         
                                                                  ,c_lp(i).ATTRIBUTE10        
                                                                  ,c_lp(i).ATTRIBUTE11        
                                                                  ,c_lp(i).ATTRIBUTE12        
                                                                  ,c_lp(i).ATTRIBUTE13        
                                                                  ,c_lp(i).ATTRIBUTE14        
                                                                  ,c_lp(i).ATTRIBUTE15        
                                                                  ,c_lp(i).ITEM_CATEGORY      
                                                                  ,c_lp(i).INVENTORY_ITEM_ID
        EXCEPTION
        WHEN OTHERS THEN
        FOR j IN 1..SQL%bulk_exceptions.Count
            LOOP
                        UPDATE XXCPD_ITM_SEC_UDA_DETAILS_TB
                        SET status_flag = 'E',
                            last_updated_by = 1,
                            last_update_date = SYSDATE
                        WHERE item_name = c_lp(SQL%BULK_EXCEPTIONS(j).ERROR_INDEX).item_name
                        AND  extension_id=c_lp(SQL%BULK_EXCEPTIONS(j).ERROR_INDEX).extension_id;
                        COMMIT;
                 IF c_list_price%ISOPEN THEN
                      CLOSE c_list_price;
                 END IF;
                FND_FILE.put_line(FND_FILE.output,'********************Exception Occured*************:-- '||SYSTIMESTAMP);
            END LOOP;
         END;
      END LOOP;
      CLOSE  c_list_price;
        COMMIT;
    end;and I am getting following error
    ORA-06550: line 156, column 47:
    PL/SQL: ORA-00911: invalid character
    ORA-06550: line 152, column 21:
    PL/SQL: SQL Statement ignoredpointing to following lines in exception block for update clause.
    WHERE item_name = c_lp(SQL%BULK_EXCEPTIONS(j).ERROR_INDEX).item_name
                        AND  extension_id=c_lp(SQL%BULK_EXCEPTIONS(j).ERROR_INDEX).extension_id; can some one please help me out with the issue.
    Thanks in Advance

    Have re-written the code in the following manner
    declare
      lv_ITEM_NAME            DBMS_SQL.VARCHAR2S;
      lv_ITEM_CATEGORY        DBMS_SQL.VARCHAR2S;
      lv_INVENTORY_ITEM_ID    DBMS_SQL.NUMBER_TABLE;
      lv_ATTRIBUTE_NAME       DBMS_SQL.VARCHAR2S;
      lv_ATTRIBUTE_VALUE      DBMS_SQL.VARCHAR2S;
      lv_GEOGRAPHY_LEVEL      DBMS_SQL.VARCHAR2S;
      lv_GEOGRAPHY_VALUE      DBMS_SQL.VARCHAR2S;
      lv_INCLUDE_GEOGRAPHY    DBMS_SQL.VARCHAR2S;
      lv_EFFECTIVE_START_DATE DBMS_SQL.date_table;
      lv_EFFECTIVE_TO_DATE    DBMS_SQL.date_table;
      lv_EXTENSION_ID         DBMS_SQL.NUMBER_TABLE;
      lv_PRICING_UNIT         DBMS_SQL.VARCHAR2S;
      lv_ATTRIBUTE_FROM       DBMS_SQL.VARCHAR2S;
      lv_ATTRIBUTE_TO         DBMS_SQL.VARCHAR2S;
      lv_FIXED_BASE_PRICE     DBMS_SQL.NUMBER_TABLE;
      lv_PARENT_ATTRIBUTE     DBMS_SQL.VARCHAR2S;
      lv_DURATION_QUANTITY    DBMS_SQL.NUMBER_TABLE;
      lv_ATTRIBUTE2           DBMS_SQL.VARCHAR2S;
      lv_ATTRIBUTE3           DBMS_SQL.VARCHAR2S;
      lv_ATTRIBUTE4           DBMS_SQL.VARCHAR2S;
      lv_ATTRIBUTE5           DBMS_SQL.VARCHAR2S;
      lv_ATTRIBUTE6           DBMS_SQL.VARCHAR2S;
      lv_ATTRIBUTE7           DBMS_SQL.VARCHAR2S;
      lv_ATTRIBUTE8           DBMS_SQL.VARCHAR2S;
      lv_ATTRIBUTE9           DBMS_SQL.VARCHAR2S;
      lv_ATTRIBUTE10          DBMS_SQL.VARCHAR2S;
      lv_ATTRIBUTE11          DBMS_SQL.VARCHAR2S;
      lv_ATTRIBUTE12          DBMS_SQL.VARCHAR2S;
      lv_ATTRIBUTE13          DBMS_SQL.VARCHAR2S;
      lv_ATTRIBUTE14          DBMS_SQL.VARCHAR2S;
      lv_ATTRIBUTE15          DBMS_SQL.VARCHAR2S;
        l_item_name XXCPD_ITM_SEC_UDA_DETAILS_TB.item_name%TYPE;
        l_extension_id XXCPD_ITM_SEC_UDA_DETAILS_TB.extension_id%TYPE;
    cursor c_list_price
    IS
    SELECT  /*+ leading(a)  */    item_name,
                             'PUBLISH_TO_PRICE_CATALOG' ATTRIBUTE_NAME,
                             MAX(DECODE (attribute_name,
                                         'PUBLISH_TO_PRICE_CATALOG',
                                         attribute_value))
                                ATTRIBUTE_VALUE,
                             NULL GEOGRAPHY_LEVEL,
                             NULL GEOGRAPHY_VALUE,
                             NULL INCLUDE_GEOGRAPHY,
                             NULL EFFECTIVE_START_DATE,
                             NULL EFFECTIVE_TO_DATE,
                             EXTENSION_ID,
                             NULL PRICING_UNIT,
                             NULL ATTRIBUTE_FROM,
                             NULL ATTRIBUTE_TO,
                             NULL FIXED_BASE_PRICE,
                             NULL PARENT_ATTRIBUTE,
                             NULL DURATION_QUANTITY,
                             NULL ATTRIBUTE2,
                             NULL ATTRIBUTE3,
                             NULL ATTRIBUTE4,
                             NULL ATTRIBUTE5,
                             NULL ATTRIBUTE6,
                             NULL ATTRIBUTE7,
                             NULL ATTRIBUTE8,
                             NULL ATTRIBUTE9,
                             NULL ATTRIBUTE10,
                             NULL ATTRIBUTE11,
                             NULL ATTRIBUTE12,
                             NULL ATTRIBUTE13,
                             NULL ATTRIBUTE14,
                             NULL ATTRIBUTE15,
                             --ORG_CODE,
                             ITEM_CATALOG_CATEGORY ITEM_CATEGORY,
                             a.INVENTORY_ITEM_ID INVENTORY_ITEM_ID
                      FROM   XXCPD_ITM_SEC_UDA_DETAILS_TB a
                     WHERE   DECODE(attribute_group_name,'LIST_PRICE',DECODE(STATUS_FLAG,'E',1,'P',2,3)
                                                       ,'XXITM_FORM_PRICING_HS',DECODE(STATUS_FLAG,'E',4,'P',5,6)
                                                       ,'XXITM_FORM_PRICING_SB',DECODE(STATUS_FLAG,'E',4,'P',5,6)
                                                       ,'XXITM_ADV_FORM_PRICING_HS',DECODE(STATUS_FLAG,'E',7,'P',8,9)
                                                       ,'XXITM_ADV_FORM_PRICING_SB',DECODE(STATUS_FLAG,'E',7,'P',8,9)
                                                       ,'XXITM_ADV_FORM_PRICING_HWSW',DECODE(STATUS_FLAG,'E',10,'P',11,12)
                                                       ,'XXITM_ADV_FORM_PRICING_SWSUB',DECODE(STATUS_FLAG,'E',10,'P',11,12)
                                                       ,'XXITM_ROUTE_TO_MARKET',DECODE(STATUS_FLAG,'E',13,'P',14,15)) in (1,2,3)
                             AND exists(select /*+ no_merge */  '1' from mtl_system_items_b b where a.inventory_item_id=b.inventory_item_id and b.organization_id=1)
                  GROUP BY   item_name,
                             extension_id,
                             ITEM_CATALOG_CATEGORY,
                             INVENTORY_ITEM_ID;
    BEGIN
      OPEN c_list_price;
      LOOP
      lv_ITEM_NAME.delete;          
      lv_ITEM_CATEGORY.delete;      
      lv_INVENTORY_ITEM_ID.delete;  
      lv_ATTRIBUTE_NAME.delete;     
      lv_ATTRIBUTE_VALUE.delete;    
      lv_GEOGRAPHY_LEVEL.delete;    
      lv_GEOGRAPHY_VALUE.delete;    
      lv_INCLUDE_GEOGRAPHY.delete;  
      lv_EFFECTIVE_START_DATE.delete;
      lv_EFFECTIVE_TO_DATE.delete;  
      lv_EXTENSION_ID.delete;       
      lv_PRICING_UNIT.delete;       
      lv_ATTRIBUTE_FROM.delete;     
      lv_ATTRIBUTE_TO.delete;       
      lv_FIXED_BASE_PRICE.delete;   
      lv_PARENT_ATTRIBUTE.delete;   
      lv_DURATION_QUANTITY.delete;  
      lv_ATTRIBUTE2.delete;         
      lv_ATTRIBUTE3.delete;         
      lv_ATTRIBUTE4.delete;         
      lv_ATTRIBUTE5.delete;         
      lv_ATTRIBUTE6.delete;         
      lv_ATTRIBUTE7.delete;         
      lv_ATTRIBUTE8.delete;         
      lv_ATTRIBUTE9.delete;         
      lv_ATTRIBUTE10.delete;        
      lv_ATTRIBUTE11.delete;        
      lv_ATTRIBUTE12.delete;        
      lv_ATTRIBUTE13.delete;        
      lv_ATTRIBUTE14.delete;        
      lv_ATTRIBUTE15.delete;        
      FETCH  c_list_price BULK COLLECT INTO   lv_ITEM_NAME
                                             ,lv_ATTRIBUTE_NAME     
                                             ,lv_ATTRIBUTE_VALUE    
                                             ,lv_GEOGRAPHY_LEVEL    
                                             ,lv_GEOGRAPHY_VALUE    
                                             ,lv_INCLUDE_GEOGRAPHY  
                                             ,lv_EFFECTIVE_START_DATE
                                             ,lv_EFFECTIVE_TO_DATE  
                                             ,lv_EXTENSION_ID       
                                             ,lv_PRICING_UNIT       
                                             ,lv_ATTRIBUTE_FROM     
                                             ,lv_ATTRIBUTE_TO       
                                             ,lv_FIXED_BASE_PRICE   
                                             ,lv_PARENT_ATTRIBUTE   
                                             ,lv_DURATION_QUANTITY  
                                             ,lv_ATTRIBUTE2         
                                             ,lv_ATTRIBUTE3         
                                             ,lv_ATTRIBUTE4         
                                             ,lv_ATTRIBUTE5         
                                             ,lv_ATTRIBUTE6         
                                             ,lv_ATTRIBUTE7         
                                             ,lv_ATTRIBUTE8         
                                             ,lv_ATTRIBUTE9         
                                             ,lv_ATTRIBUTE10        
                                             ,lv_ATTRIBUTE11        
                                             ,lv_ATTRIBUTE12        
                                             ,lv_ATTRIBUTE13        
                                             ,lv_ATTRIBUTE14        
                                             ,lv_ATTRIBUTE15        
                                             ,lv_ITEM_CATEGORY      
                                             ,lv_INVENTORY_ITEM_ID
                                      LIMIT 50000;
      IF lv_INVENTORY_ITEM_ID.count = 0 THEN
        EXIT;
      END IF;
      Begin
      FORALL I IN 1..lv_INVENTORY_ITEM_ID.count SAVE EXCEPTIONS
        INSERT /*+append*/ INTO XXCPD_ITEM_PRICING_ATTR_BKP2(
                                                                   line_id,
                                                                   ITEM_NAME,
                                                                   ATTRIBUTE_NAME,
                                                                   ATTRIBUTE_VALUE,
                                                                   GEOGRAPHY_LEVEL,
                                                                   GEOGRAPHY_VALUE,
                                                                   INCLUDE_GEOGRAPHY,
                                                                   EFFECTIVE_START_DATE,
                                                                   EFFECTIVE_TO_DATE,
                                                                   EXTENSION_ID,
                                                                   PRICING_UNIT,
                                                                   ATTRIBUTE_FROM,
                                                                   ATTRIBUTE_TO,
                                                                   FIXED_BASE_PRICE,
                                                                   PARENT_ATTRIBUTE,
                                                                   DURATION_QUANTITY,
                                                                   ATTRIBUTE2,
                                                                   ATTRIBUTE3,
                                                                   ATTRIBUTE4,
                                                                   ATTRIBUTE5,
                                                                   ATTRIBUTE6,
                                                                   ATTRIBUTE7,
                                                                   ATTRIBUTE8,
                                                                   ATTRIBUTE9,
                                                                   ATTRIBUTE10,
                                                                   ATTRIBUTE11,
                                                                   ATTRIBUTE12,
                                                                   ATTRIBUTE13,
                                                                   ATTRIBUTE14,
                                                                   ATTRIBUTE15,
                                                                   ITEM_CATEGORY,
                                                                   INVENTORY_ITEM_ID
                                                            VALUES
                                                                   xxcpd.xxcpd_if_prc_line_id_s.NEXTVAL
                                                                  ,lv_ITEM_NAME(i)
                                                                  ,lv_ATTRIBUTE_NAME(i)     
                                                                  ,lv_ATTRIBUTE_VALUE(i)    
                                                                  ,lv_GEOGRAPHY_LEVEL(i)    
                                                                  ,lv_GEOGRAPHY_VALUE(i)    
                                                                  ,lv_INCLUDE_GEOGRAPHY(i)  
                                                                  ,lv_EFFECTIVE_START_DATE(i)
                                                                  ,lv_EFFECTIVE_TO_DATE(i)  
                                                                  ,lv_EXTENSION_ID(i)       
                                                                  ,lv_PRICING_UNIT(i)       
                                                                  ,lv_ATTRIBUTE_FROM(i)     
                                                                  ,lv_ATTRIBUTE_TO(i)       
                                                                  ,lv_FIXED_BASE_PRICE(i)  
                                                                  ,lv_PARENT_ATTRIBUTE(i)   
                                                                  ,lv_DURATION_QUANTITY(i)  
                                                                  ,lv_ATTRIBUTE2(i)         
                                                                  ,lv_ATTRIBUTE3(i)         
                                                                  ,lv_ATTRIBUTE4(i)         
                                                                  ,lv_ATTRIBUTE5(i)         
                                                                  ,lv_ATTRIBUTE6(i)         
                                                                  ,lv_ATTRIBUTE7(i)         
                                                                  ,lv_ATTRIBUTE8(i)         
                                                                  ,lv_ATTRIBUTE9(i)         
                                                                  ,lv_ATTRIBUTE10(i)        
                                                                  ,lv_ATTRIBUTE11(i)        
                                                                  ,lv_ATTRIBUTE12(i)        
                                                                  ,lv_ATTRIBUTE13(i)        
                                                                  ,lv_ATTRIBUTE14(i)        
                                                                  ,lv_ATTRIBUTE15(i)        
                                                                  ,lv_ITEM_CATEGORY(i)      
                                                                  ,lv_INVENTORY_ITEM_ID(i)
        EXCEPTION
        WHEN OTHERS THEN
        ROLLBACK;
        FOR j IN 1..SQL%bulk_exceptions.Count
            LOOP
            l_item_name:=lv_ITEM_NAME(SQL%BULK_EXCEPTIONS(j).ERROR_INDEX);
            l_extension_id:=lv_EXTENSION_ID(SQL%BULK_EXCEPTIONS(j).ERROR_INDEX);
                        UPDATE XXCPD_ITM_SEC_UDA_DETAILS_TB
                        SET status_flag = 'E',
                            last_updated_by = 1,
                            last_update_date = SYSDATE
                        WHERE item_name = l_item_name
                        AND  extension_id=l_extension_id;
                        COMMIT;
                FND_FILE.put_line(FND_FILE.output,'********************Exception Occured*************:-- '||SYSTIMESTAMP);
            END LOOP;
         END;
      END LOOP;
      CLOSE  c_list_price;
        COMMIT;
    end;

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

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

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

  • Need help with Bulk Collect ForAll Update

    Hi - I'm trying to do a Bulk Collect/ForAll Update but am having issues.
    My declarations look like this:
         CURSOR cur_hhlds_for_update is
            SELECT hsh.household_id, hsh.special_handling_type_id
              FROM compas.household_special_handling hsh
                 , scr_id_lookup s
             WHERE hsh.household_id = s.id
               AND s.scr = v_scr
               AND s.run_date = TRUNC (SYSDATE)
               AND effective_date IS NULL
               AND special_handling_type_id = 1
               AND created_by != v_user;
         TYPE rec_hhlds_for_update IS RECORD (
              household_id  HOUSEHOLD_SPECIAL_HANDLING.household_id%type,
              spec_handl_type_id HOUSEHOLD_SPECIAL_HANDLING.SPECIAL_HANDLING_TYPE_ID%type
         TYPE spec_handling_update_array IS TABLE OF rec_hhlds_for_update;
         l_spec_handling_update_array  spec_handling_update_array;And then the Bulk Collect/ForAll looks like this:
           OPEN cur_hhlds_for_update;
           LOOP
            FETCH cur_hhlds_for_update BULK COLLECT INTO l_spec_handling_update_array LIMIT 1000;
            EXIT WHEN l_spec_handling_update_array.count = 0;
            FORALL i IN 1..l_spec_handling_update_array.COUNT
            UPDATE compas.household_special_handling
               SET effective_date =  TRUNC(SYSDATE)
                 , last_modified_by = v_user
                 , last_modified_date = SYSDATE
             WHERE household_id = l_spec_handling_update_array(i).household_id
               AND special_handling_type_id = l_spec_handling_update_array(i).spec_handl_type_id;
              l_special_handling_update_cnt := l_special_handling_update_cnt + SQL%ROWCOUNT;         
          END LOOP;And this is the error I'm receiving:
    ORA-06550: line 262, column 31:
    PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND table of records
    ORA-06550: line 262, column 31:
    PLS-00382: expression is of wrong type
    ORA-06550: line 263, column 43:
    PL/SQL: ORA-22806: not an object or REF
    ORA-06550: line 258, column 9:
    PL/SQL: SQMy problem is that the table being updated has a composite primary key so I have two conditions in my where clause. This the the first time I'm even attempting the Bulk Collect/ForAll Update and it seems like it would be straight forward if I was only dealing with a single-column primary key. Can anyone please help advise me as to what I'm missing here or how I can accomplish this?
    Thanks!
    Christine

    You cannot reference a column inside a record when doin a for all. You need to refer as a whole collection . So you will need two collections.
    Try like this,
    DECLARE
       CURSOR cur_hhlds_for_update
       IS
          SELECT hsh.household_id, hsh.special_handling_type_id
            FROM compas.household_special_handling hsh, scr_id_lookup s
           WHERE hsh.household_id = s.ID
             AND s.scr = v_scr
             AND s.run_date = TRUNC (SYSDATE)
             AND effective_date IS NULL
             AND special_handling_type_id = 1
             AND created_by != v_user;
       TYPE arr_household_id IS TABLE OF HOUSEHOLD_SPECIAL_HANDLING.household_id%TYPE
                                   INDEX BY BINARY_INTEGER;
       TYPE arr_spec_handl_type_id IS TABLE OF HOUSEHOLD_SPECIAL_HANDLING.SPECIAL_HANDLING_TYPE_ID%TYPE
                                         INDEX BY BINARY_INTEGER;
       l_household_id_col         arr_household_id;
       l_spec_handl_type_id_col   arr_spec_handl_type_id;
    BEGIN
       OPEN cur_hhlds_for_update;
       LOOP
          FETCH cur_hhlds_for_update
            BULK COLLECT INTO l_household_id_col, l_spec_handl_type_id_col
          LIMIT 1000;
          EXIT WHEN cur_hhlds_for_update%NOTFOUND;
          FORALL i IN l_household_id_col.FIRST .. l_household_id_col.LAST
             UPDATE compas.household_special_handling
                SET effective_date = TRUNC (SYSDATE),
                    last_modified_by = v_user,
                    last_modified_date = SYSDATE
              WHERE household_id = l_household_id_col(i)
                AND special_handling_type_id = l_spec_handl_type_id_col(i);
       --l_special_handling_update_cnt := l_special_handling_update_cnt + SQL%ROWCOUNT; -- Not sure what this does.
       END LOOP;
    END;G.

  • Bulk collect / forall which collection type?

    Hi I am trying to speed up the query below using bulk collect / forall:
    SELECT h.cust_order_no AS custord, l.shipment_set AS sset
    FROM info.tlp_out_messaging_hdr h, info.tlp_out_messaging_lin l
    WHERE h.message_id = l.message_id
    AND h.contract = '12384'
    AND l.shipment_set IS NOT NULL
    AND h.cust_order_no IS NOT NULL
    GROUP BY h.cust_order_no, l.shipment_set
    I would like to extract the 2 fields selected above into a new table as quickly as possible, but I’m fairly new to Oracle and I’m finding it difficult to sort out the best way to do it. The query below does not work (no doubt there are numerous issues) but hopefully it is sufficiently developed to shows the sort of thing I am trying to achieve:
    DECLARE
    TYPE xcustord IS TABLE OF info.tlp_out_messaging_hdr.cust_order_no%TYPE;
    TYPE xsset IS TABLE OF info.tlp_out_messaging_lin.shipment_set%TYPE;
    TYPE xarray IS TABLE OF tp_a1_tab%rowtype INDEX BY BINARY_INTEGER;
    v_xarray xarray;
    v_xcustord xcustord;
    v_xsset xsset;
    CURSOR cur IS
    SELECT h.cust_order_no AS custord, l.shipment_set AS sset
    FROM info.tlp_out_messaging_hdr h, info.tlp_out_messaging_lin l
    WHERE h.message_id = l.message_id
    AND h.contract = '1111'
    AND l.shipment_set IS NOT NULL
    AND h.cust_order_no IS NOT NULL;
    BEGIN
    OPEN cur;
    LOOP
    FETCH cur
    BULK COLLECT INTO v_xarray LIMIT 10000;
    EXIT WHEN v_xcustord.COUNT() = 0;
    FORALL i IN 1 .. v_xarray.COUNT
    INSERT INTO TP_A1_TAB (cust_order_no, shipment_set)
    VALUES (v_xarray(i).cust_order_no,v_xarray(i).shipment_set);
    commit;
    END LOOP;
    CLOSE cur;
    END;
    I am running on Oracle 9i release 2.

    Well I suppose I can share the whole query as it stands for context and information (see below).
    This is a very ugly piece of code that I am trying to improve. The advantage it has currently is
    that it works, the disadvantage it has is that it's very slow. My thoughts were that bulk collect
    and forall might be useful tools here as part of the re-write hence my original question, but perhaps not.
    So on a more general note any advice on how best speed up this code would be welcome:
    CREATE OR REPLACE VIEW DLP_TEST AS
    WITH aa AS
    (SELECT h.cust_order_no AS c_ref,l.shipment_set AS shipset,
    l.line_id, h.message_id, l.message_line_no,
    l.vendor_part_no AS part, l.rqst_quantity AS rqst_qty, l.quantity AS qty,
    l.status AS status, h.rowversion AS allocation_date
    FROM info.tlp_in_messaging_hdr h
    LEFT JOIN  info.tlp_in_messaging_lin l
    ON h.message_id = l.message_id
    WHERE h.contract = '12384'
    AND h.cust_order_no IS NOT NULL
    UNION ALL
    SELECT ho.cust_order_no AS c_ref, lo.shipment_set AS shipset,
    lo.line_id, ho.message_id, lo.message_line_no,
    lo.vendor_part_no AS part,lo.rqst_quantity AS rqst_qty, lo.quantity AS qty,
    lo.status AS status, ho.rowversion AS allocation_date
    FROM info.tlp_out_messaging_hdr ho, info.tlp_out_messaging_lin lo
    WHERE ho.message_id = lo.message_id
    AND ho.contract = '12384'
    AND ho.cust_order_no IS NOT NULL),
    a1 AS
    (SELECT h.cust_order_no AS custord, l.shipment_set AS sset
    FROM info.tlp_out_messaging_hdr h, info.tlp_out_messaging_lin l
    WHERE h.message_id = l.message_id
    AND h.contract = '12384'
    AND l.shipment_set IS NOT NULL
    AND h.cust_order_no IS NOT NULL
    GROUP BY h.cust_order_no, l.shipment_set),
    a2 AS
    (SELECT ho.cust_order_no AS c_ref, lo.shipment_set AS shipset
    FROM info.tlp_out_messaging_hdr ho, info.tlp_out_messaging_lin lo
    WHERE ho.message_id = lo.message_id
    AND ho.contract = '12384'
    AND ho.message_type = '3B13'
    AND lo.shipment_set IS NOT NULL
    GROUP BY ho.cust_order_no, lo.shipment_set),
    a3 AS
    (SELECT a1.custord, a1.sset, CONCAT('SHIPSET',a1.sset) AS ssset
    FROM a1
    LEFT OUTER JOIN a2
    ON a1.custord = a2.c_ref AND a1.sset = a2.shipset
    WHERE a2.c_ref IS NULL),
    bb AS
    (SELECT so.contract, so.order_no, sr.service_request_no AS sr_no, sr.reference_no,
    substr(sr.part_no,8) AS shipset,
    substr(note_text,1,instr(note_text,'.',1,1)-1) AS Major_line,
    note_text AS CISCO_line,ma.part_no,
    (Select TO_DATE(TO_CHAR(TO_DATE(d.objversion,'YYYYMMDDHH24MISS'),'YYYY-MM-DD HH24:MI:SS'),'YYYY-MM-DD HH24:MI:SS')
    FROM ifsapp.document_text d WHERE so.note_id = d.note_id AND so.contract = '12384') AS Print_Date,
    ma.note_text
    FROM (ifsapp.service_request sr
    LEFT OUTER JOIN ifsapp.work_order_shop_ord ws
    ON sr.service_request_no = ws.wo_no
    LEFT OUTER JOIN ifsapp.shop_ord so
    ON ws.order_no = so.order_no)
    LEFT OUTER JOIN ifsapp.customer_order co
    ON sr.reference_no = co.cust_ref
    LEFT OUTER JOIN ifsapp.shop_material_alloc ma
    ON so.order_no = ma.order_no
    JOIN a3
    ON a3.custord = sr.reference_no AND a3.sset = substr(sr.part_no,8)
    WHERE sr.part_contract = '12384'
    AND so.contract = '12384'
    AND co.contract = '12384'
    AND sr.reference_no IS NOT NULL
    AND ma.part_no NOT LIKE 'SHIPSET%'),
    cc AS
    (SELECT 
    bb.reference_no,
    bb.shipset,
    bb.order_no,
    bb.cisco_line,
    aa.message_id,
    aa.allocation_date,
    row_number() over(PARTITION BY bb.reference_no, bb.shipset, aa.allocation_date
    ORDER BY bb.reference_no, bb.shipset, aa.allocation_date, aa.message_id DESC) AS selector
    FROM bb
    LEFT OUTER JOIN aa
    ON  bb.reference_no = aa.c_ref AND bb.shipset = aa.shipset
    WHERE aa.allocation_date <= bb.print_date
    OR aa.allocation_date IS NULL
    OR bb.print_date IS NULL),
    dd AS
    (SELECT
    MAX(reference_no) AS reference_no,
    MAX(shipset) AS shipset,
    order_no,
    MAX(allocation_date) AS allocation_date
    FROM cc
    WHERE selector = 1                                   
    GROUP BY order_no, selector),
    ee AS
    (SELECT
    smx.order_no,
    SUM(smx.qty_assigned) AS total_allocated,
    SUM(smx.qty_issued) AS total_issued,
    SUM(smx.qty_required) AS total_required
    FROM ifsapp.shop_material_alloc smx
    WHERE smx.contract = '12384'
    AND smx.part_no NOT LIKE 'SHIPSET%'
    GROUP BY smx.order_no),
    ff AS
    (SELECT
    dd.reference_no,
    dd.shipset,
    dd.order_no,
    MAX(allocation_date) AS last_allocation,
    MAX(ee.total_allocated) AS total_allocated,
    MAX(ee.total_issued) AS total_issued,
    MAX(ee.total_required) AS total_required
    FROM dd
    LEFT OUTER JOIN ee
    ON dd.order_no = ee.order_no
    GROUP BY dd.reference_no, dd.shipset, dd.order_no),
    base AS
    (SELECT x.order_no, x.part_no, z.rel_no, MIN(x.dated) AS dated, MIN(y.cust_ref) AS cust_ref, MIN(z.line_no) AS line_no,
    MIN(y.state) AS state, MIN(y.contract) AS contract, MIN(z.demand_order_ref1) AS demand_order_ref1
    FROM ifsapp.inventory_transaction_hist x, ifsapp.customer_order y, ifsapp.customer_order_line z
    WHERE x.contract = '12384'
    AND x.order_no = y.order_no
    AND y.order_no = z.order_no
    AND x.transaction = 'REP-OESHIP'
    AND x.part_no = z.part_no
    AND TRUNC(x.dated) >= SYSDATE - 8
    GROUP BY x.order_no, x.part_no, z.rel_no)
    SELECT
    DISTINCT
    bb.contract,
    bb.order_no,
    bb.sr_no,
    CAST('-' AS varchar2(40)) AS Usr,
    CAST('-' AS varchar2(40)) AS Name,
    CAST('01' AS number) AS Operation,
    CAST('Last Reservation' AS varchar2(40)) AS Action,
    CAST('-' AS varchar2(40)) AS Workcenter,
    CAST('-' AS varchar2(40)) AS Next_Workcenter_no,
    CAST('Print SO' AS varchar2(40)) AS Next_WC_Description,
    ff.total_allocated,
    ff.total_issued,
    ff.total_required,
    ff.shipset,
    ff.last_allocation AS Action_date,
    ff.reference_no
    FROM ff
    LEFT OUTER JOIN bb
    ON bb.order_no = ff.order_no
    WHERE bb.order_no IS NOT NULL
    UNION ALL
    SELECT
    c.contract AS Site, c.order_no AS Shop_Order, b.wo_no AS SR_No,
    CAST('-' AS varchar2(40)) AS UserID,
    CAST('-' AS varchar2(40)) AS User_Name,
    CAST('02' AS number) AS Operation,
    CAST('SO Printed' AS varchar2(40)) AS Action,
    CAST('SOPRINT' AS varchar2(40)) AS Workcenter,
    CAST('PKRPT' AS varchar2(40)) AS Next_Workcenter_no,
    CAST('Pickreport' AS varchar2(40)) AS Next_WC_Description,
    CAST('0' AS number) AS Total_Allocated,
    CAST('0' AS number) AS Total_Issued,
    CAST('0' AS number) AS Total_Required,
    e.part_no AS Ship_Set,
    TO_DATE(TO_CHAR(TO_DATE(d.objversion,'YYYYMMDDHH24MISS'),'YYYY-MM-DD HH24:MI:SS'),'YYYY-MM-DD HH24:MI:SS')AS Action_Date,
    f.cust_ref AS cust_ref
    FROM ifsapp.shop_ord c
    LEFT OUTER JOIN ifsapp.work_order_shop_ord b
    ON b.order_no = c.order_no
    LEFT OUTER JOIN ifsapp.document_text d
    ON d.note_id = c.note_id
    LEFT OUTER JOIN ifsapp.customer_order_line e
    ON e.demand_order_ref1 = TRIM(to_char(b.wo_no))
    LEFT OUTER JOIN ifsapp.customer_order f
    ON f.order_no = e.order_no
    JOIN a3
    ON a3.custord = f.cust_ref AND a3.ssset = e.part_no
    WHERE c.contract = '12384'
    AND e.contract = '12384'
    AND d.objversion IS NOT NULL
    UNION ALL
    SELECT
    a.site AS Site, a.order_no AS Shop_Order, b.wo_no AS SR_No, a.userid AS UserID,
    a.user_name AS Name, a.operation_no AS Operation, a.action AS Action,
    a.workcenter_no AS Workcenter, a.next_work_center_no AS Next_Workcenter_no,
    (SELECT d.description  FROM ifsapp.work_center d WHERE a.next_work_center_no = d.work_center_no AND a.site = d.contract)
    AS Next_WC_Description,
    CAST('0' AS number) AS Total_Allocated,
    CAST('0' AS number) AS Total_Issued,
    CAST('0' AS number) AS Total_Required,
    e.part_no AS Ship_set,
    a.action_date AS Action_Date, f.cust_ref AS cust_ref
    FROM ifsapp.shop_ord c
    LEFT OUTER JOIN ifsapp.work_order_shop_ord b
    ON b.order_no = c.order_no
    LEFT OUTER JOIN ifsapp.customer_order_line e
    ON e.demand_order_ref1 = to_char(b.wo_no)
    LEFT OUTER JOIN ifsapp.customer_order f
    ON f.order_no = e.order_no
    LEFT OUTER JOIN info.tp_hvt_so_op_hist a
    ON a.order_no = c.order_no
    JOIN a3
    ON a3.custord = f.cust_ref AND a3.ssset = e.part_no
    WHERE a.site = '12384'
    AND c.contract = '12384'
    AND e.contract = '12384'
    AND f.contract = '12384'
    UNION ALL
    SELECT so.contract AS Site, so.order_no AS Shop_Order_No, sr.service_request_no AS SR_No,
    CAST('-' AS varchar2(40)) AS "User",
    CAST('-' AS varchar2(40)) AS "Name",
    CAST('999' AS number) AS "Operation",
    CAST('Shipped' AS varchar2(40)) AS "Action",
    CAST('SHIP' AS varchar2(40)) AS "Workcenter",
    CAST('-' AS varchar2(40)) AS "Next_Workcenter_no",
    CAST('-' AS varchar2(40)) AS "Next_WC_Description",
    CAST('0' AS number) AS Total_Allocated,
    CAST('0' AS number) AS Total_Issued,
    CAST('0' AS number) AS Total_Required,
    so.part_no AS ship_set, base.dated AS Action_Date,
    sr.reference_no AS CUST_REF
    FROM base
    LEFT OUTER JOIN ifsapp.service_request sr
    ON base.demand_order_ref1 = sr.service_request_no
    LEFT OUTER JOIN ifsapp.work_order_shop_ord ws
    ON sr.service_request_no = ws.wo_no
    LEFT OUTER JOIN ifsapp.shop_ord so
    ON ws.order_no = so.order_no
    WHERE base.contract = '12384';

  • DBMS_OUTPUT within BULK COLLECT FORALL

    Hi,
    I am trying to figure out how I can output using DBMS_OUTPUT.PUT_LINE within a BULK COLLECT/ FORALL Update?
    Example:
    FETCH REF_CURSOR BULK COLLECT INTO l_productid,l_qty
    forall indx in l_productid.first..l_productid.last
    Update products aa
    Set aa.LastInventorySent = l_qty(indx)
    Where aa.productid = l_productid(indx);
    DBMS_OUTPUT.PUT_LINE('ProductID: ' || l_productid(indx)|| ' QTY: ' || l_qty(indx);
    Is this possible? If so how can I accomlish this?
    Thanks,
    S

    FETCH REF_CURSOR BULK COLLECT INTO l_productid,l_qty
    forall indx in l_productid.first..l_productid.last
    Update products aa
    Set aa.LastInventorySent = l_qty(indx)
    Where aa.productid = l_productid(indx);
    for indx in 1..l_qty.count loop
    DBMS_OUTPUT.PUT_LINE('ProductID: ' || l_productid(indx)|| ' QTY: ' || l_qty(indx);
    end loop;SY.

  • Bulk collect forall vs single merge statement

    I understand that a single DML statement is better than using bulk collect for all having intermediate commits. My only concern is if I'm loading a large amount of data like 100 million records into a 800 million record table with foreign keys and indexes and the session gets killed, the rollback might take a long time which is not acceptable. Using bulk collect forall with interval commits is slower than a single straight merge statement, but in case of dead session, the rollback time won't be as bad and a reload of the not yet committed data will not be as bad. To design a recoverable data load that may not be affected as badly, is bulk collect + for all the right approach?

    1. specifics about the actual data available
    2. the location/source of the data
    3. whether NOLOGGING is appropriate
    4. whether PARALLEL is an option
    1. I need to transform the data before, so I can build the staging tables to match to be the same structure as the tables I'm loading to.
    2. It's in the same database (11.2)
    3. Cannot use NOLOGGING or APPEND because I need to allow DML in the target table and I can't use NOLOGGING because I cannot afford to lose the data in case of failure.
    4. PARALLEL is an option. I've done some research on DBMS_PARALLEL_EXECUTE and it sounds very cool. Can this be used to load to two tables? I have a parent child tables. I can chunk the data and load these two tables separately, but the only requirement would be that I need to commit together. I cannot load a chunk into the parent table and commit before I load the corresponding chunk into its child table. Can this be done using DBMS_PARALLEL_EXECUTE? If so, I think this would be the perfect solution since it looks like it's exactly what I'm looking for. However, if this doesn't work, is bulk collect + for all the best option I am left with?
    What is the underlying technology of DBMS_PARALLEL_EXECUTE?

  • Using Native Dynamic SQL in Forms

    Can Native Dynamic SQL be used in Forms 5.0 or Forms 6.0? (Database 8.1.6.0.0)
    I have tried the following code (examples below) from the PL/SQL User's Guide and Reference Release 8.1.6 and the Metalinks Note: 62592.1 and the trigger/procedure (in Forms) will not compile. I appreciate any help given.
    Example1:
    (I have a table named temp_jane with a column named companies and a value 'Hello'. When compiling, I receive the error: 'Error 103 at line 8, column 11 Encountered the symbol ''IMMEDIATE" when expecting one of the following :=.(@%; ')
    declare
    str varchar2( 200 );
    val varchar2( 20 );
    ret temp_jane%rowtype;
    begin
    str := 'select company from temp_jane where company = :b1';
    val := 'Hello';
    execute immediate str into ret using val;
    message('Value fetched from table: '&#0124; &#0124;ret.company);
    end;
    Example2:
    (Here is the real issue, I don't know what the select statement, so I need to be able to assign a variable. When compiling, I receive the error: 'Error 103 at line 28, column 21 Encountered the symbol "VSQLSTATEMENT" when expecting one of the following: select ').
    declare
    type ItemsControlCurTyp is ref cursor;
    ItemsCur ItemsControlCurTyp;
    ItemsRec Items%rowtype;
    vSQLStatement varchar2( 5000 );
    vExecuteSQL varchar2( 5000 );
    vNumRows integer;
    vValue varchar2( 2000 );
    vFirstOne varchar2( 1 ) := 'Y';
    vRetval varchar2( 2000 );
    begin
    -- Display the column prompts with the right text.
    set_item_property( 'ITEMS_AVAILABLE.NDB_VALUE', PROMPT_TEXT, :ITEMS_CONTROL.AVAILABLE_LABEL );
    set_item_property( 'ITEMS_CHOSEN.NDB_VALUE', PROMPT_TEXT, :ITEMS_CONTROL.CHOSEN_LABEL );
    -- Save the original version of CHOSEN_STRING in case the user reverts or cancels.
    :ITEMS_CONTROL.CHOSEN_STRING_ORIG := :ITEMS_CONTROL.CHOSEN_STRING;
    vSQLStatement := :ITEMS_CONTROL.SELECT_STATEMENT;
    vExecuteSQL := vSQLStatement;
    -- Open the cursor
    open ItemsCur for vSQLStatement;

    Hi JTaylor
    You cannot use NDS in Client side (Developer). You have to use DBMS_SQL only.
    Regards
    A K Srinivasan
    Oracle.

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

  • Security risk of ref cursor & dynamic sql

    Hi guys,
    I am using Ref Cursor to execute a dynamic sql in my stored procedure. Inputs to the dynamic SQL are passed in as parameters. My code fragments:
    parameters:
    CREATE PROCEDURE mm_select(
    aaa     IN VARCHAR2,
    bbb     IN VARCHAR2 )
    in the code:
    sqlstmt := 'SELECT * FROM dbaivoc.mm ' ||
    'WHERE b in (' || role_id_list || ') ' ||
    'AND c = '|| application_fn_id_list ;
    OPEN RC1 FOR sqlstmt;
    My question is, is it possible for anyone to pass in a malicious SQL like drop table xxx into the parameter list eg. exec mm_select(1,'1; drop table aa;')
    I've tried but it doesn't seem to work. I'm just asking for confirmation. Thanks for any help!
    rgds,
    mas

    I don't see in your small pieces of code what the input parameters aaa and bbb are used for.
    If your statement is always
    sqlstmt := 'select ....'
    then I don't see how this can be changed to 'drop table ...'.
    It would be something different if you have something like this in your procedure:
    execute immediate bbb;

  • Passing values dynamically in bulk collect

    1. hi for ex 5 account number in a table packages each account number is having of 30 records with the column aol and new(values are in 0 or 1)
    i need to copare fro old column and new column values and return if 0 and 1 means return 1 0 and 0 means 0 1and 1 means 1 1and 0 means 0
    for all days 30 days. for all account number and ouptut should be as follows
    account number value
    1 0
    2 1
    3 1
    4 0
    and this values should update in another table;
    i wrote a sample query for a single account but i need for all accounts.
    as given below please help me to solve the issues
    DECLARE
         CURSOR C1 is select rowid,old_family,new_family,OLD_SPORTS,NEW_SPORTS,OLD_DYNASTY,NEW_DYNASTY from packages where account_no='86240331';
         Type C1_type is table of C1%rowtype;
         Rec1                          c1_type;
         New_value1                     number;
         New_value2                    number;
    New_value3                    number;
    Begin
         Open C1;
              Loop
                   Fetch C1 Bulk collect into Rec1;
                   For i in 1..Rec1.count Loop
    -------- TO GET FAMILY PACKAGES VALUES-----------------------------------------------------------------------------------------------
                        If           (Rec1(i).old_family= '0' and Rec1(i).new_family ='1' ) or
                             (Rec1(i).old_family= '1' and Rec1(i).new_family ='1' )
                   then
                                  new_value1:='1';
                   Else
                        new_value1:='0';
                   End if;
    -------- TO GET SPORTS PACKAGES VALUES-----------------------------------------------------------------------------------------------
                        If           (Rec1(i).old_SPORTS= '0' and Rec1(i).new_SPORTS ='1' ) or
                             (Rec1(i).old_SPORTS= '1' and Rec1(i).new_SPORTS ='1' )
                   then
                                  new_value2:='1';
                   Else
                        new_value2:='0';
                   End if;
    ------------TO GET DYNASTY PACKAGES VALUES ------------------------------------------------------------------------------------------
                        If           (Rec1(i).old_DYNASTY= '0' and Rec1(i).new_DYNASTY ='1' ) or
                             (Rec1(i).old_DYNASTY= '1' and Rec1(i).new_DYNASTY ='1' )
                   then
                                  new_value3:='1';
                   Else
                        new_value3:='0';
                   End if;
                        End loop;
                   ---------------------------     update statement------------
                   Exit when c1%notfound;
              End loop;
    End;
    Edited by: 841719 on Mar 6, 2011 8:01 PM

    1. hi for ex 5 account number in a table packages each account number is having of 30 records with the column aol and new(values are in 0 or 1)
    i need to copare fro old column and new column values and return if 0 and 1 means return 1 0 and 0 means 0 1and 1 means 1 1and 0 means 0
    for all days 30 days. for all account number and ouptut should be as follows
    account number value
    1 0
    2 1
    3 1
    4 0
    and this values should update in another table;
    i wrote a sample query for a single account but i need for all accounts.
    as given below please help me to solve the issues
    DECLARE
    CURSOR C1 is select rowid,old_family,new_family,OLD_SPORTS,NEW_SPORTS,OLD_DYNASTY,NEW_DYNASTY from packages where account_no='86240331';
    Type C1_type is table of C1%rowtype;
    Rec1 c1_type;
    New_value1 number;
    New_value2 number;
    New_value3 number;
    Begin
    Open C1;
    Loop
    Fetch C1 Bulk collect into Rec1;
    For i in 1..Rec1.count Loop
    TO GET FAMILY PACKAGES VALUES-----------------------------------------------------------------------------------------------
    If (Rec1(i).old_family= '0' and Rec1(i).new_family ='1' ) or
    (Rec1(i).old_family= '1' and Rec1(i).new_family ='1' )
    then
    new_value1:='1';
    Else
    new_value1:='0';
    End if;
    TO GET SPORTS PACKAGES VALUES-----------------------------------------------------------------------------------------------
    If (Rec1(i).old_SPORTS= '0' and Rec1(i).new_SPORTS ='1' ) or
    (Rec1(i).old_SPORTS= '1' and Rec1(i).new_SPORTS ='1' )
    then
    new_value2:='1';
    Else
    new_value2:='0';
    End if;
    ------------TO GET DYNASTY PACKAGES VALUES
    If (Rec1(i).old_DYNASTY= '0' and Rec1(i).new_DYNASTY ='1' ) or
    (Rec1(i).old_DYNASTY= '1' and Rec1(i).new_DYNASTY ='1' )
    then
    new_value3:='1';
    Else
    new_value3:='0';
    End if;
    End loop; update statement------------
    Exit when c1%notfound;
    End loop;
    End;

Maybe you are looking for