Associative array related problem

Hi All,
When I am trying to use assotiative array in a select statement I recieve the following error:
ORA-06550: line 9, column 22:
PLS-00201: identifier 'COL1' must be declared
ORA-06550: line 9, column 22:
PLS-00201: identifier 'COL1' must be declared
ORA-06550: line 9, column 10:
PL/SQL: ORA-00904: : invalid identifier
ORA-06550: line 9, column 3:
PL/SQL: SQL Statement ignored
Here is the example
--create table MyTable (col1 varchar2(255), col2 varchar2(255))
declare
  type m_ttMyTable
    is table of MyTable%rowtype index by MyTable.col1%type;
  m_tMyTable                   m_ttMyTable;
  m_sCol2 varchar2(255);
begin
  select m_tMyTable (col1).col2  /* works with ocntant: select m_tMyTable */('col1').col2
    into m_sCol2
  from MyTable
  where rownum = 1;
end;
--drop table MyTableAny ideas how to workaround this?
Thanks

The only collection types SQL can query are ones defined in SQL using CREATE TYPE. That excludes associative arrays, as they are PL/SQL-only constructs. I'd recommend a nested table collection.
Some more suggestions:
www.williamrobertson.net/documents/collection-types.html

Similar Messages

  • Associative Array (Object) problems

    Here is the function i'm dealing with
    i'm reading in a delimited string and using indexed arrays to
    break them up and assign the keys and values to an associative
    array in a loop.
    i'm using variables in the loop and the array loads as
    expected in the loop
    but outside the loop, the only key is the variable name and
    the value is undefined
    this is true using dot or array notation, as well as literal
    strings for the keys
    any help is appreciated
    watchSuspendData = function (id, oldval, newval):String {
    //the incoming suspendData string is delimited by the
    semicolon;
    //newval is: firstValue=Yes;captivateKey=1
    var listSuspendData:Array = newval.split(";"); // convert it
    to a list of key/value pairs
    if (listSuspendData.length > 0){
    //line 123: listSuspendData.length is: 2
    for (i=0; i < listSuspendData.length; i++){ //for each
    key/value pair
    var keyValArray:Array = new Array();
    var myNameValue:String = listSuspendData
    //line 127: listSuspendData is: firstValue=Yes
    keyValArray = myNameValue.split("="); // split 'em on the
    equal sign
    var myKey:String = keyValArray[0];
    var myVal:String = keyValArray[1];
    //keyValArray[0] is: firstValue
    //keyValArray[1] is: Yes
    // store the key and the value in associative array
    suspendDataArray.myKey = myVal;
    trace("line 134: suspendDataArray is: " +
    suspendDataArray.myKey);
    // trace is line 134: suspendDataArray is: Yes on the first
    pass and 1 on the second
    //the below loop always returns one array key: myKey and the
    value as undefined
    for(x in suspendDataArray){
    trace("x is: " + x); //x is: myKey
    trace("the val is: " + suspendDataArray.x); //the val is:
    undefined
    } //end for
    return newval;

    on lines 12-13 i assign the key=value pair to string
    variables
    then on lines 17-18 i assign those values to the associative
    array using dot notation
    the trace seems to work there
    the problem is that when the procedure exits the for loop,
    the associative array only has one key (myKey) and no value
    (undefined)
    all the documentation i've read shows using these types of
    arrays with either non-quoted property names like:
    myAssocArray.myKey = "somevalue";
    or
    myAssocArray[myKey] = "somevalue";
    i tried assigning the key/value pairs directly from the
    indexed arrays, but the result was always undefined
    like this:
    suspendDataArray.keyValArray[0] = keyValArray[1]
    or
    suspendDataArray[keyValArray[0]] = keyValArray[1]
    i even tried building a string in the loop and trying to
    assign all the pairs at once using the curly brace
    this is pretty wierd behavior for actionscript or i'm missing
    something basic here
    thanks for looking

  • Associative Array problem in Oracle Procedure

    Hi,
    I've searched through the internet and this forum and haven't been able to resolve a problem using associative array values within an IN clause. Everything I've read states that I can't use the associative array directly in the SQL statement. I have to convert it to a table and then I can use it. Unfortunately, I'm receiving an "ORA-21700: object does not exist or is marked for delete" error when trying to access the table I've populated from the array. Please note that I have verified the table is actually being populated during the loop. I'm catching the error when referencing it in the SELECT statement.
    I've declared the following in the ARCHIVE package specification:
    TYPE RSType IS REF CURSOR;
    TYPE integer_aat IS TABLE OF INTEGER INDEX BY PLS_INTEGER;
    TYPE integer_table IS TABLE OF INTEGER;
    The procedure is as follows:
    PROCEDURE SEL_SEARCH_RESULTS (v_term IN VARCHAR2,
    v_categories IN ARCHIVE.integer_aat,
    rs OUT RSType)
    AS
    /* PURPOSE: Return Search Results for the Category and Keyword Provided
    VARIABLES:
    v_categories = Document Categories array
    v_term = Keyword entered
    rs = Result Set
    tbl_cat ARCHIVE.integer_table := ARCHIVE.integer_table();
    BEGIN
    FOR i IN 1 .. v_categories.COUNT
    LOOP
    tbl_cat.EXTEND(1);
    tbl_cat(i) := v_categories(i);
    END LOOP;
    OPEN rs FOR
    SELECT A.ID,
    B.CATEGORY,
    A.FILENAME,
    A.DISPLAY_NAME,
    A.COMMENTS
    FROM TBL_ARCHIVE_DOCUMENTS A,
    TBL_ARCHIVE_DOC_CAT B,
    TBL_ARCHIVE_DOC_KEYWORDS C
    WHERE A.ID = B.ID
    AND A.ID = C.ID
    AND B.CATEGORY IN (SELECT * FROM TABLE(tbl_cat))
    AND C.KEYWORD = v_term
    ORDER BY A.ID;
    END SEL_SEARCH_RESULTS;
    Any help would be greatly appreciated and thanks in advance,
    Matt

    Thank you for the quick response. I looked at the example you suggested and made the following changes. Now I'm receiving an "Invalid datatype" error on the "SELECT column_value FROM TABLE(CAST(tbl_cat AS tbl_integer))" statement. I must be missing something simple and I just can't put my finger on it.
    PROCEDURE SEL_SEARCH_RESULTS (v_term IN VARCHAR2,
    v_categories IN ARCHIVE.integer_aat,
    rs OUT RSType)
    AS
    /* PURPOSE: Return Search Results for the Category and Keyword Provided
    VARIABLES:
    v_categories = Document Categories array entered
    v_term = Keyword entered
    rs = Result Set
    TYPE tbl_integer IS TABLE OF INTEGER;
    tbl_cat tbl_integer;
    BEGIN
    FOR i IN 1 .. v_categories.COUNT
    LOOP
    tbl_cat.EXTEND(1);
    tbl_cat(i) := v_categories(i);
    END LOOP;
    OPEN rs FOR
    SELECT A.ID,
    B.CATEGORY,
    A.FILENAME,
    A.DISPLAY_NAME,
    A.COMMENTS
    FROM TBL_ARCHIVE_DOCUMENTS A,
    TBL_ARCHIVE_DOC_CAT B,
    TBL_ARCHIVE_DOC_KEYWORDS C
    WHERE A.ID = B.ID
    AND A.ID = C.ID
    AND B.CATEGORY IN (SELECT column_value FROM TABLE(CAST(tbl_cat AS tbl_integer)))
    AND C.KEYWORD = v_term
    ORDER BY A.ID;
    END SEL_SEARCH_RESULTS;

  • Would PL/SQL Associative Arrays solve my problem

    Hi guys,
    I'm new to PL/SQL development really, although i have some limited knowledge that i've relied on for the last couple of years to get by. Anyway, i'll try my best to describe my problem and how i'd like to solution it ...........
    I have a table of information that holds a column for decscriptive names of payments and another column holding a difference value, for example :
    employee_number | payment_name | difference
    00001           | salary       | 200.20
    00001           | shift        | 20.21
    00002           | salary       | 10.01
    00002           | shift        | 5.02
    00003           | salary       | 15.02
    00003           | shift        | 4.00I'd like to manipulate the way this data is presented, via DBMS_OUTPUT in a summary fashion counting the number of differences between ranges, for example :
    payment_name | 0.00 to 10.00 | 10.01 to 100.00 | 100.01 to 99999.99
    salary       |               | 2               | 1
    shift        | 2             | 1               |I thought it might be possible to use an approach in PL/SQL to mimic this table structure and populate it via a cursor looping through my initial recordset and posting the total count in the associated columns as required. Once the cursor had finished populating the PL/SQL table / array etc i could base my DBMS_OUTPUT on this data.
    Or am i completely barking up the wrong tree, would there be a better, more efficient way to solution the problem. I've been reading up on PL/SQL Collections http://docs.oracle.com/cd/B10501_01/appdev.920/a96624/05_colls.htm#19661 but can't really determine is this is a) the correct approach or b) should i try using an associative array, nested table or varray?
    Thanks in advance guys, just need a pointer in the right direction.

    It sounds like you can just pivot the data
    SELECT payment_name,
           SUM( CASE WHEN difference BETWEEN 0 and 10 THEN 1 ELSE 0 END ) "0.00 to 10.00",
           SUM( CASE WHEN difference BETWEEN 10.01 and 100 THEN 1 ELSE 0 END ) "10.01 to 100.00",
           SUM( CASE WHEN difference BETWEEN 100.01 and 99999.99 THEN 1 ELSE 0 END ) "100.01 to 99999.99"
      FROM table_name
    GROUP BY payment_nameYou can then do whatever you want with the data this query returns.
    Justin

  • Associative Array with subsripts(Index) as Varchar2

    Hi All,     
    I m using Oracle Version 10.1.0.2.0 - Production     
    I have the following requirement:     
    The Associative array which holds the value with the subscripts(Index) as database table column.
    Create table Period_master
    Period_code_c Varchar2(10),
    Period_frm_dt Date,
    Period_to_dt Date,
    Year_code_c     Varchar2(10)
    Insert into period_master values ('10',to_date('01/01/2012','dd/mm/rrrr'),to_date('31/01/2012','dd/mm/rrrr'),'2011-2012');
    Insert into period_master Values ('11',to_date('01/02/2012','dd/mm/rrrr'),to_date('29/02/2012','dd/mm/rrrr'),'2011-2012');
    Insert into period_master Values ('12',to_date('01/03/2012','dd/mm/rrrr'),to_date('31/03/2012','dd/mm/rrrr'),'2011-2012');
    Insert into period_master Values ('13',to_date('01/04/2012','dd/mm/rrrr'),to_date('30/04/2012','dd/mm/rrrr'),'2012-2013');
    Insert into period_master Values ('14',to_date('01/05/2012','dd/mm/rrrr'),to_date('31/05/2012','dd/mm/rrrr'),'2012-2013');
    Commit;
    SQL > Select * from Period_Master;
    Period_code --- Period_frm_dt --- Period_to_dt ---- Year_code_c
    10     ---     01/01/2012 ---     31/01/2012     --- 2011-2012
    11     ---     01/02/2012 ---     29/02/2012     --- 2011-2012
    12     ---     01/03/2012 ---     31/03/2012     --- 2011-2012
    13     ---     01/04/2012 ---     30/04/2012     --- 2012-2013
    14     ---     01/05/2012 ---     31/05/2012     --- 2012-2013     
    My Requirement is get the Period_frm_dt,period_end_dt and yearcode based on period_code (which is input parameters from my procedure) by using Collections.
    I have to create one PLSQL table type which having the subscripts(Index) as period_code which is Varchar2 type;
    I have written follwing code ,but it's not giving the desired output:
    Declare
    iv_period Varchar2(10);
    Cursor cur_prd(cp_period Varchar2) is select * from Period_Master Where Period_code_c = cp_period;
    TYPE PRD_REC_TY IS TABLE OF cur_prd%ROWTYPE INDEX BY PLS_INTEGER;
    lv_prd_data prd_rec_ty;
    lv_prd PERIOD_MASTER.period_code_c%TYPE ;
    lv_frm_dt PERIOD_MASTER.Period_frm_dt%TYPE ;
    lv_to_dt PERIOD_MASTER.Period_to_dt%TYPE ;
    lv_yr_code PERIOD_MASTER.Year_code_c%TYPE ;
    Begin
    iv_period := :period;
    Open Cur_prd(iv_period);
    Loop
    Fetch cur_prd BULK COLLECT into lv_prd_data;
    EXIT WHEN cur_prd%NOTFOUND;
    End Loop;
    Close Cur_Prd;
    If lv_prd_data.COUNT > 0 THEN
    For i IN lv_prd_data.FIRST .. lv_prd_data.LAST
    LOOP
    lv_prd := lv_prd_data(i).pERIOD_cODE_C;
    lv_frm_dt := lv_prd_data(i).Period_frm_dt;
    lv_to_dt := lv_prd_data(i).Period_to_dt;
    lv_yr_code := lv_prd_data(i).Year_Code_c;
    Dbms_output.Put_line('For Period code : '||lv_prd||' the Year code is : '||lv_yr_code);
    Dbms_output.Put_line('For Period code : '||lv_prd||' the Period_from_dt is : '||lv_frm_dt);
    Dbms_output.Put_line('For Period code : '||lv_prd||' the Period_to_dt is : '||lv_to_dt);
    END LOOP;
    End if;
    Exception
    When Others Then
    Dbms_output.Put_line('Here Error Found: '||SQLERRM);
    End;
    But My requirement is to get the FRM_DT,TO_DT and YEAR CODE as per the following:
    For Period Code :*11* -- the YearCode is --- *2011-2012*
    For Period Code :*11* -- the From Dt is --- *01/02/2012*
    For Period Code :*11* -- the To Dt is --- *29/02/2012*
    for Period Code : *14* -- the Yearcode is --- *2012-2013*
    For Period Code : *14* -- the From Dt is --- *01/05/2012*
    For Period Code : *14* -- the To Dt is --- *31/05/2012*
    So on...
    Like:
    lv_yr_code := lv_period_data(iv_period).Year_code_c;
    lv_frm_dt := lv_period_data(iv_period).Period_frm_dt;
    lv_to_dt := lv_period_data(iv_period).Period_to_dt;
    Dbms_output.Put_line('For Period code : '||iv_period||' the Year code is : '||lv_yr_code);
    Dbms_output.Put_line('For Period code : '||iv_period||' the Period_from_dt is : '||lv_frm_dt);
    Dbms_output.Put_line('For Period code : '||iv_period||' the Period_to_dt is : '||lv_to_dt);
    How do i resolve the above scenario.Please help me to resove the above scenario.
    Regards,
    Prasanta

    Hi, Pransanta,
    Prasanta wrote:
    ... My Requirement is get the Period_frm_dt,period_end_dt and yearcode based on period_code (which is input parameters from my procedure) by using Collections.Sorry, I don't understand.
    What is the porocedure you mentioned? Do you mean the anonymous block that you posted? If not, post the procedure. How is it related to the anonymous block? E.g., does the anonymous block need to call the procedure?
    I have to create one PLSQL table type which having the subscripts(Index) as period_code which is Varchar2 type;
    I have written follwing code ,but it's not giving the desired output:
    Declare
    iv_period Varchar2(10);Please format your code, and use \ tags to keep the formatting when you post it on this site.
    See the forum FAQ {message:id=9360002}
    Cursor cur_prd(cp_period Varchar2) is select * from Period_Master Where Period_code_c = cp_period;You're only looking for a single given period_code_c.  If you want to get all rows, lose the WHERE clause.  If you want to multiple rows, but not all rows, then use an appropriate WHERE clause.
    TYPE PRD_REC_TY IS TABLE OF cur_prd%ROWTYPE INDEX BY PLS_INTEGER;
    lv_prd_data prd_rec_ty;
    lv_prd PERIOD_MASTER.period_code_c%TYPE ;
    lv_frm_dt PERIOD_MASTER.Period_frm_dt%TYPE ;
    lv_to_dt PERIOD_MASTER.Period_to_dt%TYPE ;
    lv_yr_code PERIOD_MASTER.Year_code_c%TYPE ;
    Begin
    iv_period := :period;Post the code that declares and sets :period.
    Open Cur_prd(iv_period);
    Loop
    Fetch cur_prd BULK COLLECT into lv_prd_data;
    EXIT WHEN cur_prd%NOTFOUND;
    End Loop;
    Close Cur_Prd;
    If lv_prd_data.COUNT > 0 THEN
    For i IN lv_prd_data.FIRST .. lv_prd_data.LAST
    LOOP
    lv_prd := lv_prd_data(i).pERIOD_cODE_C;
    lv_frm_dt := lv_prd_data(i).Period_frm_dt;
    lv_to_dt := lv_prd_data(i).Period_to_dt;
    lv_yr_code := lv_prd_data(i).Year_Code_c;If the block is just supposed to do what it's doing now; then you don't need all these local variables.  It's simpler just to teference lv_prd_data.
    If you're planning to add some other code to the block later, then the local variables could be useful.
    Dbms_output.Put_line('For Period code : '||lv_prd||' the Year code is : '||lv_yr_code);
    Dbms_output.Put_line('For Period code : '||lv_prd||' the Period_from_dt is : '||lv_frm_dt);
    Dbms_output.Put_line('For Period code : '||lv_prd||' the Period_to_dt is : '||lv_to_dt);
    END LOOP;
    End if;
    Exception
    When Others Then
    Dbms_output.Put_line('Here Error Found: '||SQLERRM);Only use an EXCEPTION section when you need to.  The EXCEPTION section above is only hiding some information about the error.
    End;
    But My requirement is to get the FRM_DT,TO_DT and YEAR CODE as per the following:
    For Period Code :*11* -- the YearCode is --- *2011-2012*
    For Period Code :*11* -- the From Dt is --- *01/02/2012*
    For Period Code :*11* -- the To Dt is --- *29/02/2012*
    for Period Code : *14* -- the Yearcode is --- *2012-2013*
    For Period Code : *14* -- the From Dt is --- *01/05/2012*
    For Period Code : *14* -- the To Dt is --- *31/05/2012*
    So on...
    Like:
    lv_yr_code := lv_period_data(iv_period).Year_code_c;
    lv_frm_dt := lv_period_data(iv_period).Period_frm_dt;
    lv_to_dt := lv_period_data(iv_period).Period_to_dt;
    Dbms_output.Put_line('For Period code : '||iv_period||' the Year code is : '||lv_yr_code);
    Dbms_output.Put_line('For Period code : '||iv_period||' the Period_from_dt is : '||lv_frm_dt);
    Dbms_output.Put_line('For Period code : '||iv_period||' the Period_to_dt is : '||lv_to_dt);
    How do i resolve the above scenario.Please help me to resove the above scenario.
    Regards,
    PrasantaIf the problem is that you need to show all period_code_cs, not just one, then you can do this:DECLARE
    CURSOR cur_prd
    IS SELECT *
         FROM     period_master
         ORDER BY period_code_c;
    TYPE prd_rec_ty IS TABLE OF cur_prd%ROWTYPE INDEX BY PLS_INTEGER;
    lv_prd_data prd_rec_ty;
    BEGIN
    OPEN cur_prd;
    FETCH cur_prd BULK COLLECT into lv_prd_data;
    CLOSE cur_prd;
    IF lv_prd_data.COUNT > 0
    THEN
    FOR i IN lv_prd_data.FIRST .. lv_prd_data.LAST
         LOOP
         dbms_output.put_line ( 'For Period code : '
                        || lv_prd_data(i).period_code_c
                        || ' the Year code is : '
                        || lv_prd_data(i).year_code_c
         dbms_output.Put_line ( 'For Period code : '
                        || lv_prd_data(i).period_code_c
                        || ' the Period_from_dt is : '
                        || lv_prd_data(i).period_frm_dt
         dbms_output.put_line ( 'For Period code : '
                        || lv_prd_data(i).period_code_c
                        || ' the Period_to_dt is : '
                        || lv_prd_data(i).period_to_dt
         END LOOP;
    END IF;
    END;

  • Parsing XMLType into an associative array

    I'm try to build a procedure that can take an XMLType as a parameter. What I would like to do be able to extract both the node names and the string values from each tag of the XML and put them into basically a key --> value associative array.
    Ex:
    <envelope>
    <node1>value1</node1>
    <node2>value2</node2>
    </envelope>
    Would be put into an array structured like: array['node1'] = 'value1', array['node2'] = 'value2', etc.
    I'm not entirely sure how I go about looping through the XMLType and extracting each node name and its value. I'm not worried about repeating tag names.. I know that will not be an issue in any of the XMLTypes that I'm using.
    Would anyone be able to offer any suggestions? If not how to go about doing exactly that, then at least some insight as to how I can loop through and extract nodes and/or values without specifying the specific XPaths?
    Thanks in advance!

    Hi Roger,
    This is a good description of your process. Just add your Oracle DB Version somewhere. Want you want is a method to map your XML to a relationship design (some special variant of object-relational-modelling).
    I still see two choices:
    The programmatic approach (as you described):
    Have multiple procedures where you input an XML. Each procedure is reflecting a different part of the transformation process. So it depends from the Message which procedure you will call.
    Example
    SQL*Plus: Release 9.2.0.2.0 - Production on Thu Aug 14 17:53:25 2008
    Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.
    Connected to:
    Oracle9i Enterprise Edition Release 9.2.0.8.0 - 64bit Production
    With the Partitioning, OLAP and Oracle Data Mining options
    JServer Release 9.2.0.8.0 - Production
    SQL> create table testtab (username varchar2(100));
    Table created.
    /* the following insert part should be in some packaged procedure, */
    /* this just don't work on my 9i version, but should in 10g  */
    SQL> insert into testtab (username)
      2  select substr(extractvalue(column_value,'*/text()'),1,100)
      3  from table(xmlsequence(extract( xmltype('<envelope>'||
      4               '<username>Roger</username>'||
      5               '<username>Sven</username>'||
      6               '</envelope>'),'envelope/username')));
    2 rows created.
    SQL> select * from testtab;
    USERNAME
    Roger
    Sven
    SQL> The declarative approach:
    Insert the XML into a SchemaBased Table. The XML Schema will provide the mapping to your relational tables automagically. Problem here is the writing, handling and evolving of the XML Schema (Sub schemas are allowed too).

  • Associative Array our only option?

    Hello,
    I'm having a problem accepting associative arrays as the only option I have for getting data from a stored procedure. I have a good reason for not wanting to use ref cursors as I am using the stored procedure to manipulate data which I in turn would like to pass back to VB through the stored procedure and would rather not have to insert he data into a table just to re-select it for a ref cursor.
    My main concern is that with associative arrays I am expected to define the number of return results before I even generate the data. Also from what I can see I am required to set the data length for each and every item in said array one at a time. All this overhead seems like more work than what I would have to do to utilizer a reference cursor. Is there a right way to do this? I would really like to do the most straight forward way I can without the extra processing.

    Hi,
    Here's a blog post of mine that illustrates using pipelined functions and PL/SQL to return results:
    http://oradim.blogspot.com/2007/10/odpnet-tip-using-pipelined-functions.html
    Not sure if that will be helpful in your case, but perhaps it might be a place to start anyway.
    - Mark

  • Associative array comparison and INSERT upon IF condition

    Hi Guys,
    I have written this pl sql code to identify non existing sellers and insert their sales channel information into the dimension table (dimensional table update).
    Somehow,......nothing is inserted and this script runs for 12 hours+ without any result. the sql autotrace shows no result and the explain plan (button on sql developer throws upon clicking "missing keyword". I have no
    information what is going on/wrong. Does anyone spot an error?
    UNDEFINE DimSales;
    UNDEFINE FactTable;
    DEFINE DimSales = 'testsales';
    DEFINE FactTable = 'testfact';
    DECLARE
    v_SellerNo VarChar(9);
    v_error_code T_ERRORS.v_error_code%TYPE;
    v_error_message T_ERRORS.v_error_message%TYPE;
    TYPE assoc_array_str_type1 IS TABLE OF VARCHAR2(32) INDEX BY PLS_INTEGER;
         v1 assoc_array_str_type1;
    TYPE assoc_array_str_type2 IS TABLE OF VARCHAR2(32) INDEX BY PLS_INTEGER;
         v2 assoc_array_str_type2;
    BEGIN
    --Collect all distinct SellerNo into associative array (hash table)
    select distinct SellerNo bulk collect into v1 from &FactTable;
    select distinct seller_id bulk collect into v2 from &DimSales;
    v_SellerNo := v1.first;
    loop
    exit when v1 is null;
    --1 Check if v_SellerNo already exists in DIM_Sales (if NOT/FALSE, its a new seller and we can insert all records for that seller
    if (v2.exists(v_SellerNo)=false) THEN
    INSERT INTO &DimSales (K_Sales,REG,BVL,DS, VS,RS,GS,VK)
    (SELECT DISTINCT trim(leading '0' from RS||GS) ,REG BVL,DS,VS,RS,GS,VK from &FactTable where SellerNo =v_SellerNo);
    --ELSE
    end if;
    v_SellerNo := v1.next(v_SellerNo);
    end loop;
    EXCEPTION
    WHEN OTHERS THEN
    ROLLBACK;
    --v_error_code := SQLCODE
    --v_error_message := SQLERRM
    --INSERT INTO t_errors VALUES ( v_error_code, v_error_message);
    END;
    ---------------------------------------------------------------

    Distinct clause requires a sort. Sorts can be very expensive.
    Bulk collects that are not constrained in fetch size, can potentially fetch millions of rows - requiring that data to be wholly read into server memory. I have seen how this can degrade performance so badly that the kernel reboots the server.
    Using PL/SQL loops to process and insert/update/delete data is often problematic due to its row-by-row approach - also called slow-by-slow approach. It is far more scalable letting SQL do the "loop" processing, by using joins, sub-selects and so on.
    Where the conditional processing is too complex for SQL to handle, then PL/SQL is obviously an alternative to use. Ideally one should process data sets as oppose to rows in PL//SQL. Reduce context switching by using bulk fetches and bulk binds.
    But PL/SQL cannot execute in parallel as the SQL it fires off can. If after all the optimisation, the PL/SQL process still needs to hit a million rows to process, it will be slow irrespective of how optimal that PL/SQL approach and design - simply because of the number of rows and the processing overheads per row.
    In that case, the PL/SQL code itself need to be parallelised. There are a number of ways to approach this problem - the typical one is to create unique and distinct ranges of rows to process, spawn multiple P/SQL processes, and provide each with a unique range of rows to process. In parallel.
    So you need to look close at what you are trying to achieve, what the workloads are, and how to effectively decrease the workloads and increase the processing time of a workload.
    For example - finding distinct column values. You can pay for that workload when wanting that distinct list. And each time afterward repeat that workload when wanting that distinct list. Or you can pay for that workload up-front with the DML that creates/updates those values - and use (for example) a materialised view to maintain a ready to use distinct list of values.
    Same workload in essence - but paying once for it and up-front as oppose to each time you execute your code that needs to dynamically build that distinct list.
    Kent Crotty did tests and showed stunning performance improvements with bulk collect and forall, up to 30x faster:Bulk processing is not a magical silver bullet. It is a tool. And when correctly use, the tool does exactly what it was designed to do.
    The problem is using a hammer to drive in screws - instead of a screwdriver. There's nothing "stunning" about using a screwdriver. It is all about using the correct tool.
    If the goal of the swap daemon is to free up "idle" chunks of memory, and try to use that memory for things like file cache instead, what does that have to do with bulk processing?The swap daemon reads virtual memory pages from swap space into memory, and writes virtual pages from memory to swap space.
    What does it have to do with bulk processing? A bulk fetch reads data from the SGA (buffer cache) into the PGA (private process memory space). The larget the fetch, the more memory is required. If for example 50% of server memory is required for a bulk collection that is 2GB in size, then that will force in-use pages from memory to swap space.. only to be swapped back again as it is needed, thereby forcing other in-use pages to swap. The swap daemon will consume almost all the CPU time swapping hot pages continually in and out of memory.

  • Associative array Basics

    I have a SELECT query like
    SELECT ename, sal from emp;
    I want the ename column values from the output of the above query to be populated into an Associative array. So i did the following steps
    DECLARE
    TYPE ename_type IS TABLE OF VARCHAR2(10) INDEX BY PLS_INTEGER;
    v_ename ename_type;
    What is the next step by which i could populate the v_ename variable with the ename column values from the above query?

    One slight problem.
    The ename is derived from a large SELECT query joining three tables. The SELECT query looks like
    SELECT ename,max(sal) from ...............;
    I only need ename values from this SELECT query to be populated to the Assosiative array (v_ename). But I cannot exclude max(sal) from the query due to aggregate function's technical reasons(GROUP BY and so on).
    So when i try to populate the associative array v_ename by issuing the following command:
    SELECT ename BULK COLLECT INTO v_ename FROM (SELECT ename,max(sal) from ...............) ;
    The max(sal) value in the SELECT query is going to be a problem. How do i solve this?

  • Associative array two variable comparison :update table error

    Hi,
    i am using associative array to update the version number of table
    -i declare two associative array to compare the column from two table (temp,main tables)values in loop
    -if id's of both variable(for temp and main table) are equal and column of either of table not matching then it should update the version no of temp table
    -if id's not equal i.e record only exists temp table then update null version number annd increment it by 1
    -following is the structure and procedure --it shows the matching and non matching records but for the update statement it not giving expected output i.e it updates all records irrespective of the condition provided
    -i tried to put condition in update as well as in the  if statement but it updates all record
    ....suggestion and help highly appreciate. thankx in advance !!!
    /*--table structure and data--*/
    CREATE TABLE "TEMP_TABLE"
       ( "ID" NUMBER NOT NULL ENABLE,
      "COL1" VARCHAR2(20 BYTE),
      "COL2" VARCHAR2(20 BYTE),
      "VERSION" NUMBER
       INSERT INTO TEMP_TABLE VALUES (101,'A','B',NULL);
       INSERT INTO TEMP_TABLE VALUES (102,'x','y',NULL);
       INSERT INTO TEMP_TABLE VALUES (103,'r','t',NULL);
       CREATE TABLE "MAIN_TABLE"
       ( "ID" NUMBER NOT NULL ENABLE,
      "COL1" VARCHAR2(20 BYTE),
      "COL2" VARCHAR2(20 BYTE),
      "VERSION" NUMBER
       INSERT INTO MAIN_TABLE VALUES (101,'A','B',1);
    /*------update version procedure----------*/
    DECLARE
      TYPE T_tmp_table IS TABLE OF tmp_table %ROWTYPE INDEX BY PLS_INTEGER;
      TYPE T_main_table IS TABLE OF main_table%ROWTYPE INDEX BY PLS_INTEGER;
      l_tmp_table T_tmp_table;
      l_main_table T_main_table;
      BEGIN
        SELECT * BULK COLLECT INTO l_tmp_table FROM tmp_table;
        SELECT * BULK COLLECT INTO l_main_table FROM main_table;
        FOR i IN 1 .. l_tmp_table.count
        LOOP
          FOR j IN 1 .. l_main_table.count
         LOOP
      if(l_tmp_table(i).ID = l_main_table(j).ID AND l_tmp_table(i).VERSION IS NULL) then     
      ---this first if loop updates temp table version irrespective of l_tmp_table.ID=l_main_table.ID orl_tmp_table. ID<>l_main_table.ID  .it display proper matching and non-matching records.
       dbms_output.put_line('matching ids from tmp and main are :'||l_tmp_table(i).ID||'  '||l_main_table(j).ID);
       UPDATE tmp_table SET VERSION = l_tmp_table(i).version +1;
       --where l_tmp_table(i).ID = l_main_table(j).ID     --
       end if;
      if (l_tmp_table(i).ID <> l_main_table(j).ID) then
       dbms_output.put_line('non matching ids from tmp and main are :'||l_tmp_table(i).ID||'  '||l_main_table(j).ID);
       UPDATE tmp_table SET VERSION = l_tmp_table(i).version +1;
       --where l_tmp_table(i).ID <> l_main_table(j).ID    
        end if;
              END LOOP;
              END LOOP;
        EXCEPTION
        WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('OTHER');
    END;

    Hello user8937641
    I think there is a problem with the logic of your SQL-Code.
    But maybe in this formatted structure you can see where your problem is. -> I can not say it because I do not know what is the requirement.
    I hope it helps...
    /*------update version procedure----------*/
    DECLARE
      TYPE T_tmp_table IS TABLE OF tmp_table %ROWTYPE INDEX BY PLS_INTEGER;
      TYPE T_main_table IS TABLE OF main_table%ROWTYPE INDEX BY PLS_INTEGER;
      l_tmp_table T_tmp_table;
      l_main_table T_main_table;
      BEGIN
        SELECT * BULK COLLECT INTO l_tmp_table FROM tmp_table;
        SELECT * BULK COLLECT INTO l_main_table FROM main_table;
        FOR i IN 1 .. l_tmp_table.count
        LOOP
          FOR j IN 1 .. l_main_table.count
          LOOP
            IF     l_tmp_table(i).ID = l_main_table(j).ID
               AND l_tmp_table(i).VERSION IS NULL
             THEN
                 ---this first if loop updates temp table version irrespective of l_tmp_table.ID=l_main_table.ID orl_tmp_table. ID<>l_main_table.ID  .it display proper matching and non-matching records.
                 dbms_output.put_line('matching ids from tmp and main are :'||l_tmp_table(i).ID||'  '||l_main_table(j).ID);
                 UPDATE tmp_table
                    SET version = l_tmp_table(i).version +1;
                  WHERE id = l_tmp_table(i).ID
            END IF;
            IF l_tmp_table(i).ID <> l_main_table(j).ID
             THEN
               dbms_output.put_line('non matching ids from tmp and main are :'||l_tmp_table(i).ID||'  '||l_main_table(j).ID);
               -- Maybe you do not need this update:
               UPDATE tmp_table
                  SET version = l_tmp_table(i).version +1;
                WHERE id =  l_tmp_table(i).ID
            END IF;
            COMMIT;
           END LOOP;
        END LOOP;
      EXCEPTION WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('Error at Executing the PLSQL-Block - ' || SQLERRM);
    END;

  • How to share an associative array throughout the entire instance?

    Hi all,
    I have an associative array with much data, and it would barely change, I want to keep it in the memory and share it throughout the entire instance, and make sure all sessions of all users get the same associative array, is it possible?
    Thanks in advanced.

    >
    I want to keep it in the memory and share it throughout the entire instance, and make sure all sessions of all users get the same associative array, is it possible?
    Why do you want to keep it in memory?
    Will using a table for that, which being accessed frequently, will practically always be in the buffer cache, cause performance problems for you?
    The only other way to keep data in memory globally accesable to all database sessions is to use the global application context feature. With that you can store [name;value] pairs in memory and easily access (read) them using the SYS_CONTEXT built-in.
    Toon

  • How to use Associative Array in sql query?

    Hello,
    I have a problem on using Associative Array variable on query; and my query is similar to the one below;
    TYPE OTHERGENERICS IS TABLE OF NUMBER(10) INDEX BY BINARY_INTEGER;
    othersGenerics OTHERGENERICS;
    CURSOR cursor_othersGenerics IS
    select master.GENERICCODEID
    from ASMTRG_ARTICLEMASTER master
    join ASMTRG_ARTICLEMAP map on MAP.ARTICLECODEID = MASTER.ID
    group by MASTER.GENERICCODEID
    minus
    select FGG.GENERICCODEID
    from asmtrg_icfocusgroup fg
    join asmtrg_icfocusgrpchannel fgc on FGC.GROUPID = FG.ID and fgc.isactive=1
    join asmtrg_icfocusgengroup fgg on FGG.GROUPID = FG.ID and FGg.ISACTIVE=1
    where fgc.channelid=1 and fg.isactive = 1
    group by FGG.GENERICCODEID;
    BEGIN
    OPEN cursor_othersGenerics;
    FETCH cursor_othersGenerics BULK COLLECT INTO othersGenerics;
    CLOSE cursor_othersGenerics;
    SELECT icfrd.*,
    CASE
    WHEN EXISTS(select ta.genericcodeid from <???XXX???> ta where ta.genericcodeid = icfgrp.genericcodeid) THEN -1
    ELSE icfrd.icfgroupid
    END CLASSIFICATION
    FROM ASMTRGVIW_ICFOCUSREPORTDATA icfrd
    LEFT JOIN ASMTRG_ICFOCUSGROUP icfgrp on icfrd.ICFGROUPID = icfgrp.ID
    WHERE (channelId IS NULL OR icfrd.CHANNELID = channelId)
    AND (asmCodeId IS NULL OR icfrd.ASMCODEID = asmCodeId)
    AND (yearId IS NULL OR icfrd.YEARID = yearId)
    AND (monthId IS NULL OR icfrd.MONTHID = monthId)
    END;
    By the way this is a part of my function.
    The "othersGenerics" is my associative array variable and <???XXX???> is the place where I need to use my "othersGenerics" array to check. So far I've tried
    "select ta.genericcodeid from table(cast(otherGenerics as OTHERGENERICS)) ta where ta.genericcodeid = icfgrp.genericcodeid",
    "select ta.genericcodeid from table(otherGenerics) ta where ta.genericcodeid = icfgrp.genericcodeid",
    "select ta.genericcodeid from otherGenerics ta where ta.genericcodeid = icfgrp.genericcodeid"
    and these are not working.
    What is your suggestions?

    Your type will have to be created as an independent object in your schema. So CREATE TYPE cannot be in your function declaration, it has to be outside it. (And then the line inside your declaration that defines the type will have to be removed.)
    But now I can see that you use this array as a kind of "temporary lookup table" - you populate the array and then use it for lookup in your select statement. An alternative way of doing this could be like this completely without arrays:
    with othergenerics as (
      select master.GENERICCODEID
      from ASMTRG_ARTICLEMASTER master
      join ASMTRG_ARTICLEMAP map on MAP.ARTICLECODEID = MASTER.ID
      group by MASTER.GENERICCODEID
      minus
      select FGG.GENERICCODEID
      from asmtrg_icfocusgroup fg
      join asmtrg_icfocusgrpchannel fgc on FGC.GROUPID = FG.ID and fgc.isactive=1
      join asmtrg_icfocusgengroup fgg on FGG.GROUPID = FG.ID and FGg.ISACTIVE=1
      where fgc.channelid=1 and fg.isactive = 1
      group by FGG.GENERICCODEID
    SELECT icfrd.*,
    CASE
    WHEN EXISTS(select ta.genericcodeid from othergenerics ta where ta.genericcodeid = icfgrp.genericcodeid) THEN -1
    ELSE icfrd.icfgroupid
    END CLASSIFICATION
    FROM ASMTRGVIW_ICFOCUSREPORTDATA icfrd
    LEFT JOIN ASMTRG_ICFOCUSGROUP icfgrp on icfrd.ICFGROUPID = icfgrp.ID
    WHERE (channelId IS NULL OR icfrd.CHANNELID = channelId)
    AND (asmCodeId IS NULL OR icfrd.ASMCODEID = asmCodeId)
    AND (yearId IS NULL OR icfrd.YEARID = yearId)
    AND (monthId IS NULL OR icfrd.MONTHID = monthId)
    ...The with clause (subquery factoring) you can think of as a kind of temp table called othergenerics created "on-the-fly".
    The optimizer may decide to actually create a temp table for you and use in the lookup, or it may decide to rewrite the query into suitable joins or nested loops or hashing - whatever the optimizer decides will be the optimal way of doing things :-)
    So unless you use your array other places in your function, I would recommend dropping the array completely, skip populating an array, and instead use a with clause for your temporary lookup.

  • Associative Array error

    I am using a couple associative arrays in my code and comparing the data in one, and if it is an asterisk, I change it to use the data in the other. Here is the meat of my code. I am running into an error at the bolded line saying I have too many values, which I don't understand because the code is the exact same as the block of code right before it where I populate the first array. FYI, the table it is pulling from only has one row. The error is listed below the code.
    Code
    DECLARE
    TYPE refresh_file_t IS TABLE OF test.loading_dock%ROWTYPE ;
    refresh_data refresh_file_t ;
    prospect_data refresh_file_t ;
    TYPE CV_TYPE IS REF CURSOR ;
    c_id CV_TYPE ;
    v_id NUMBER(10) ;
    v_phone VARCHAR2(10) ;
    v_project VARCHAR2(10) ;
    BEGIN
    OPEN c_id FOR
    'SELECT id
    FROM test.loading_dock
    WHERE rownum = 1' ;
    LOOP
    FETCH c_id INTO v_id ;
    EXIT WHEN c_id%NOTFOUND ;
    SELECT * BULK COLLECT
    INTO refresh_data
    FROM test.loading_dock
    WHERE id = v_id ;
    SELECT * BULK COLLECT
    INTO prospect_data
    FROM test.prospects
    WHERE id_number = v_id ;
    IF refresh_data(1).home_phone = '*' THEN
    v_phone := prospect_data(1).phone ;
    ELSE
    v_phone := refresh_data(1).home_phone ;
    END IF ;
    DBMS_OUTPUT.PUT_LINE(v_phone) ;
    END LOOP ;
    CLOSE c_id ;
    END ;
    Error
    ORA-06550: line 29, column 13:
    PL/SQL: ORA-00913: too many values
    ORA-06550: line 27, column 13:
    PL/SQL: SQL Statement ignored
    ORA-06550: line 34, column 46:
    PLS-00302: component 'PHONE' must be declared
    ORA-06550: line 34, column 13:
    PL/SQL: Statement ignored
    06550. 00000 - "line %s, column %s:\n%s"

    Collection prospect_data is of type refresh_file_t, which is a table of records of test.loading_dock%TYPE. Most likely tables test.loading_dock and test.prospects have different structure - test.prospects has fewer columns. So when you try to fetch from test.prospects into prospect_data you get the error Try replacing
    prospect_data refresh_file_t ;with
    TYPE prospect_data_t IS TABLE OF test.prospects%ROWTYPE ;
    prospect_data prospect_data_t ;SY.

  • Associative Array Question

    Hi All,
    I've searched through this forum trying to find information I'm needing on associative arrays with a varchar2 index without luck. What I'm looking for is a way to get the index or "key" values of the array without knowing what they are. Meaning, I wouldn't have to know the index value when designing the array but would be able to utilize them values at runtime. For those familiar with Java it would be like calling the keySet() method from a Map object.
    So, if I have an array of TYPE COLUMN_ARRAY IS TABLE OF VARCHAR2(4000) INDEX BY VARCHAR2(100) is there any way to dynamically get the index values without knowing what they are?
    Any help is appreciated.
    Thanks

    Thanks for the response.
    I am aware of using FIRST and NEXT for iterating the array but can I extract the index value of the current element into a variable when I don't know what the index value is at runtime ?
    Thanks

  • Associative Array vs Table Scan

    Still new to PL/SQL, but very keen to learn. I wondered if somebody could advise me whether I should use a collection (such as an associative array) instead of repeating a table scan within a loop for the example below. I need to read from an input table of experiment data and if the EXPERIMENT_ID does not already exist in my EXPERIMENTS table, then add it. Here is the code I have so far. My instinct is that it my code is inefficient. Would it be more efficient to scan the EXPERIMENTS table only once and store the list of IDs in a collection, then scan the collection within the loop?
    -- Create any new Experiment IDs if needed
    open CurExperiments;
    loop
    -- Fetch the explicit cursor
    fetch CurExperiments
    into vExpId, dExpDate;
    exit when CurExperiments%notfound;
    -- Check to see if already exists
    select count(id)
    into iCheckExpExists
    from experiments
    where id = vExpId;
    if iCheckExpExists = 0 then
    -- Experiment ID is not already in table so add a row
    insert into experiments
    (id, experiment_date)
    values(vExpId, dExpDate);
    end if;
    end loop;

    Except that rownum is assigned after the result set
    is computed, so the whole table will have to be
    scanned.really?
    SQL> explain plan for select * from i;
    Explained.
    SQL> select * from table( dbms_xplan.display );
    PLAN_TABLE_OUTPUT
    Plan hash value: 1766854993
    | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT  |      |   910K|  4443K|   630   (3)| 00:00:08 |
    |   1 |  TABLE ACCESS FULL| I    |   910K|  4443K|   630   (3)| 00:00:08 |
    8 rows selected.
    SQL> explain plan for select * from i where rownum=1;
    Explained.
    SQL> select * from table( dbms_xplan.display );
    PLAN_TABLE_OUTPUT
    Plan hash value: 2766403234
    | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT   |      |     1 |     5 |     2   (0)| 00:00:01 |
    |*  1 |  COUNT STOPKEY     |      |       |       |            |          |
    |   2 |   TABLE ACCESS FULL| I    |     1 |     5 |     2   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       1 - filter(ROWNUM=1)
    14 rows selected.

Maybe you are looking for

  • Email Notification not working Oracle BPEL 10.1.3.1.0

    I'm not able to send out email notification using Email process activity from Component Palette. These are the steps that I've followed: 1. Email/SMTP server configuration details entered in the <SOA_oracle_home>\bpel\system\services\config\ns_emails

  • How to add convert traditional chinese / simplied chinese button?

    After installing Microsoft Office 2010 Proofing Tools Kit Service Pack 1 (SP1), the button of Traditional Chinese to Simplied Chinese or vice versa still cannot be seen in the "Review" of Word.  How can I install it?

  • SWF at 100 % width and proportional height

    I have a SWF that I would like to use in an XHTML 1.0 Strict document. My need is that the flash must: - Be 100% width - Grow / shrink proportionally in height (depending on width) - The flash may not be cropped or distorted - I must be able to to pu

  • Suggestions for TM+CCC in a 160GB external disk

    Hi, I am new to macs and to this wonderful discussion foruns. Just to make sure I will have no surprises in the future, I wanted to run in a newly purchased 160GB USB external disk both Time Machine and a bootable clone of the system (size is about 5

  • ALV : How to activate List - Export - Spreadsheet

    Hi all, I have tried to search this forum n google regarding on the above problem but couldn't find any answer. Therefore, i have decided to post this question here. I have ALV report but somehow i couldn't Export -> spreadsheet directly. It was disa