Elements order in Nested Tables

In PL/SQL when I am adding element to a nested table of objects one by one(in order), and then trying to insert that nested table type to a physical table , the order of element changes. how can I prevent this behavior?

Your example is incomplete and has errors. Oracle does not guarantee the order of anything unless you use an order by clause. So, if you expect the following to produce rows in some order:
Open cur1 for select * from another_table;
then you need to add an order by clause, such as:
Open cur1 for select * from another_table order by id;
The following does minimal correction, completion, and provides sample data to demonstrate:
SCOTT@orcl_11gR2> create or replace TYPE coord AS OBJECT
  2    (id  number,
  3       x   number,
  4       y   number);
  5  /
Type created.
SCOTT@orcl_11gR2> create or replace TYPE coord_tab AS TABLE OF coord;
  2  /
Type created.
SCOTT@orcl_11gR2> create table demo_table
  2    (id     number,
  3       coords     coord_tab)
  4  NESTED TABLE coords STORE AS coords_tabb
  5  /
Table created.
SCOTT@orcl_11gR2> create table another_table
  2    (id  number,
  3       x   number,
  4       y   number)
  5  /
Table created.
SCOTT@orcl_11gR2> insert into another_table values (10, 20, 30)
  2  /
1 row created.
SCOTT@orcl_11gR2> insert into another_table values (60, 50, 40)
  2  /
1 row created.
SCOTT@orcl_11gR2> DECLARE
  2    type cur is ref cursor;
  3    cur1 cur;
  4    type rec_type is record
  5        (id  number,
  6         x   number,
  7         y   number);
  8    record_type rec_type;
  9    coords_tab coord_tab := coord_tab();
10    idx number := 1;
11  BEGIN
12    Open cur1 for select * from another_table order by id desc;
13    LOOP
14        fetch cur1 into record_type;
15        exit when cur1%notfound;
16        coords_tab.extend() ;
17        coords_tab(idx) := coord(record_type.id, record_type.x , record_type.y);
18        idx := idx + 1;
19    End LOOP;
20  --  EXECUTE IMMEDIATE 'insert into demo_table values (1,:1)' USING coords_tab ;
21    insert into demo_table values (1,coords_tab);
22  End;
23  /
PL/SQL procedure successfully completed.
SCOTT@orcl_11gR2> select * from demo_table
  2  /
        ID
COORDS(ID, X, Y)
         1
COORD_TAB(COORD(60, 50, 40), COORD(10, 20, 30))
1 row selected.
SCOTT@orcl_11gR2>

Similar Messages

  • Severe Pro*C / nested table error

    I am experiencing a nasty error which involves Pro*C accessing nested table columns. I am running Oracle 9.2.0.1.0 on Solaris 2.8 and using the GNU gcc compiler.
    In my examples, I will use the sample data which comes with Pro*C ($ORACLE_HOME/precomp/demo/sql/coldemo1.sql).
    This defines the following types and table (and also populates the table with sample data):
    CREATE TYPE city_t AS OBJECT (name CHAR(30), population NUMBER);
    CREATE TYPE citytbl_t AS TABLE OF city_t;
    CREATE TABLE county_tbl (name CHAR(30), cities citytbl_t)
    NESTED TABLE cities STORE AS citytbl_t_tbl;
    I have no problems running the sample program ($ORACLE_HOME/precomp/demo/proc/coldemo1.pc). Note that you must follow the instructions included in the comments of coldemo1.pc (manually execute the Oracle Type Translator, precompile, compile and link).
    The sample, however, merely retrieves and displays existing data. I would like my program to be able to insert new rows into county_tbl, including the nested table.
    I have the following code (for simplicitys sake, everything is in the main procedure):
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sqlca.h>                                /* SQL Communications Area */
    #include <coldemo1.h>        /* OTT-generated header with C typedefs for the */
                                          /* database types city_t and citytbl_t */
    #define CITY_NAME_LEN    30
    #define COUNTY_NAME_LEN  30
    #define MAXCITIES 5
    void PrintSQLError()
      EXEC SQL WHENEVER SQLERROR CONTINUE;
      printf("SQL error occurred...\n");
      printf("%.*s\n", (int)sqlca.sqlerrm.sqlerrml,
             (CONST char *)sqlca.sqlerrm.sqlerrmc);
      EXEC SQL ROLLBACK RELEASE;
      exit(-1);
    int main(int argc, char *argv[])
      char * uid = "scott/tiger";
      citytbl_t *cityTable;
      OCIInd cityTableInd;
      char county[COUNTY_NAME_LEN + 1];
      city_t *city[MAXCITIES];
      city_t_ind *cityInd[MAXCITIES];
      char cname[CITY_NAME_LEN + 1];
      int cpop;
      int numCities = MAXCITIES;
      int i, tableSize;
      EXEC SQL WHENEVER SQLERROR DO PrintSQLError();
      EXEC SQL CONNECT :uid;
      /* to null-terminate strings */
      EXEC ORACLE OPTION (char_map=string);
      /* Allocate the required descriptors */
      EXEC SQL ALLOCATE :cityTable;
      EXEC SQL ALLOCATE :city:cityInd;
      strcpy(county,"MYCOUNTY");
      /* Create an array of city objects */
      EXEC SQL FOR :numCities OBJECT CREATE :city:cityInd;
      for(i=0;i<numCities;i++)
        sprintf(cname,"city%d", i);
        cpop = (i * 100);
        EXEC SQL OBJECT SET NAME, POPULATION OF :city[i] TO :cname, :cpop;
        cityInd[i]->_atomic = cityInd[i]->NAME = cityInd[i]->POPULATION = OCI_IND_NOTNULL;
      cityTableInd = OCI_IND_NOTNULL;
      EXEC SQL COLLECTION APPEND :city:cityInd TO :cityTable:cityTableInd;
      EXEC SQL INSERT INTO county_tbl (NAME, CITIES) VALUES (:county, :cityTable:cityTableInd);
      EXEC SQL FREE :city;
      EXEC SQL FREE :cityTable;
      EXEC SQL COMMIT RELEASE;
      return(0);
    }This works as expected, inserting one row into COUNTY_TBL, with name=MYCOUNTY, cities being a nested table containing five city elements.
    My problem occurs when I create a trigger on COUNTY_TBL which attempts to modify elements of the nested table column. Heres the trigger (in this case, we are converting each NAME element of the cities table to upper case):
    create or replace trigger biur_county
    before insert or update on county_tbl
    for each row
    when (new.cities is not null)
    BEGIN
    IF(:NEW.cities.COUNT > 0) THEN
    FOR i IN :NEW.cities.FIRST..:NEW.cities.LAST LOOP
    :NEW.cities(i).NAME := UPPER( :NEW.cities(i).NAME );
    END LOOP;
    END IF;
    END biur_county;
    From SQL*Plus, this works as expected:
    SQL> insert into county_tbl values ('ANOTHERCOUNTY',CITYTBL_T(CITY_T('city1',1),CITY_T('city2',2)));
    1 row created.
    SQL> select * from county_tbl where name='ANOTHERCOUNTY';
    NAME
    CITIES(NAME, POPULATION)
    ANOTHERCOUNTY
    CITYTBL_T(CITY_T('CITY1 ', 1), CITY_T('CITY2 ', 2))
    1 row selected.
    Note that the city names have been converted to upper case.
    If, however, I attempt to run the Pro*C program again, with the trigger enabled, I get a severe error:
    ORA-03113: end-of-file on communication channel
    This also creates entries in the alert log:
    Errors in file /space/oracle/product/9.2.0.1.0/admin/ATDEV/udump/atdev_ora_16790.trc:
    ORA-07445: exception encountered: core dump [0000000100C8EF7C] [SIGBUS] [Invalid address alignment] [0x400000006] [] []
    The trace file includes:
    Exception signal: 10 (SIGBUS), code: 1 (Invalid address alignment), addr: 0x400000006, PC: [0x100c8e
    f7c, 0000000100C8EF7C]
    *** 2002-12-11 15:51:25.469
    ksedmp: internal or fatal error
    ORA-07445: exception encountered: core dump [0000000100C8EF7C] [SIGBUS] [Invalid address alignment]
    [0x400000006] [] []
    Current SQL statement for this session:
    insert into county_tbl (NAME,CITIES) values (:b0,:b1:b2)
    ----- PL/SQL Call Stack -----
    object line object
    handle number name
    38421f020 3 SCOTT.BIUR_COUNTY
    If I subsequently disable the trigger (or alter the trigger so that the contents of the nested table are not modified), all is well again.
    Has anyone else encountered a similar problem? I am assuming that the problem has something to do with the objects in Pro*C being transient and held in the object cache on the client. Perhaps I am doing something wrong in my program. Does anyone have any thoughts?
    Certainly there are ways around this problem (remove the trigger, for example, or perform inserts through a view / instead of trigger, etc), but I would like to have an explanation as to why my method is not working.
    Any insights would be greatly appreciated.

    HELLO!!!
    This problem reveals ONLY in DEBUG configuration (in RELEASE - all ok, but DEBUG is very important feature ;)) and operator
    new in my case have not an influence on this situation.
    I found a problem in other place when calling boxes=box.ptr();
    The boxes oracle class have a nested table. In C++ :
    class CBoxes : public oracle::occi::PObject {
    private:
    OCCI_STD_NAMESPACE::string BOXNAME;
    oracle::occi::Number BOXNUM;
    OCCI_STD_NAMESPACE::vector<CWidget*> WIDGETS;
    ptr() function calling readSQL method of CBoxes class:
    BOXNAME = streamOCCI_.getString();
    BOXNUM = streamOCCI_.getNumber();
    oracle::occi::getVector(streamOCCI_, WIDGETS);
    and getVector is:
    //cutted from occiObjects.h------------------------------
    template <class T>
    void getVector(const AnyData &any, OCCI_STD_NAMESPACE::vector<T> &vect)
    {OCCI_STD_NAMESPACE::vector< PObject *> vec_pobj;      
    getVectorOfPObjects( any,vec_pobj);//!!!!!!! :[  ]
    vect.clear();
    int size= vec_pobj.size();
    for( int i=0; i< size; i++)
    vect.push_back( (T)vec_pobj[i] );
    }//<- the destructor of vec_pobj is being called and if vec_pobj not an empty vector, the program crashes.
    I suppose that getVectorOfPObjects( any,vec_pobj) can't correctly allocate memory for vec_pobj elements in DEBUG mode.

  • Element order is not preserved in NESTED TABLES.

    I may be silly, but I cant understand it.
    Steven Feurenstein : Unlike nested tables, when you store and retrieve a VARRAY, its element order is preserved.
    Element order is not preserved in NESTED TABLES.
    What does it mean?
    Thanks..

    Could you please give an example?He just did? A nested table is really a table like any other, so the same rule applies: if you want the data selected in a specific order, you must use ORDER BY.

  • Bind ordered pair of nested tables into cursor

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

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

  • Display Item texts in Purchase Order items layout as nested table

    Hi to all,
    my issue is the following: I have to display on a form (using transaction SFP) Purcahse Order items and their texts. I built a context in which I put item texts table as a nested table of items table. I followed example "FP_TEST_NESTED_TABLE" in SE38 but I can't diplay item texts under item row. I try to explain: I want my output similar to the following
    Order  Item   |   Quantity  |    Price Uom |  Unit Price
    00010                2500              ST                0.30
                                                                 | This is first row of item texts for item 00010
                                                                 | This is second row of item texts for item 00010
                                                                 | This is third row of item texts for item 00010
                                                                 | This is ..........
                                                                 | ........
    00020                234              ST                0.80
                                                                 | This is first row of item texts for item 00020
                                                                 | This is second row of item texts for item 00020
                                                                 | This is third row of item texts for item 00020
                                                                 | This is ..........
                                                                 | ........
    Any suggestion? please?
    thank you very miuch
    Enrico

    Hi Enrico,
    I have worked on a similar requirement. I have created the whole fields including the item text in a single internal table
    Following was my approach
    I have distinguished the Table body content into two subforms which will be wrapped into one main subform ( representing table body say sub_body). Whose property is set to flowed ( With West Text  property) and repeat each item
    1. Enclose the table columns into subform say sub1, set its propert to flowed with west text property. Alighnment of the columns embaed in Sub1 should be made by adjusting its width and spacing .
    2. Enclose the Corresponding item text ( Which will be one of the colums of the internal tabel mapped ) into Sub2.
    As far as standard text display is concerned which can be displayed in two ways as explained in one of my earlier posts.
    Re: Adobe forms ..Table passing to Form and Display
    Hope this helps,
    Regards,
    Murthy

  • Multi-level nested tables for repeatable XML Elements

    Hi there,
    Suppose we have a XML Schema „ASchema“ like this (XMLDB schema annotations are left out for simplicity):
    <xs:schema xmlns:xs=" .... " />
    <xs:element name=“A“>
         <xs:complexType>
              <xs:sequence>
                   <xs:element name=“B“ maxOccurs=“unbounded“/>
                        <xs:complexType>
                             <xs:sequence>
                                  <xs:element name = “C“ maxOccurs=“unbounded“/>
                             </xs:sequence>
                        </xs:complexType>
                   </xs:element>
              </xs:sequence>
         </xs:complexType>
    </xs:element>
    </xs:schema>
    After registering this schema in Oracle, I can define a table like this:
    CREATE TABLE ATable
    id NUMBER,
    doc XMLTYPE
    XMLTYPE COLUMN doc
    XMLSCHEMA “ASchema“ ELEMENT “A“
    VARARRAY doc.“XMLDATA“.“B“ STORE AS TABLE “BTable“
    ((PRIMARY KEY (NESTED_TABLE_ID, SYS_NC_ARRAY_INDEX$)) ORGANIZATION INDEX)
    This creates a nested table "BTable" within the table "ATable". So far so good, I can use this nested table to gain faster access on every possible subelement of Element B when I set an appropriate index.
    I now want to create another nested table for element “C“ like this:
    DROP TABLE ATable;
    CREATE TABLE ATable
    id NUMBER,
    doc XMLTYPE
    XMLTYPE COLUMN doc
    XMLSCHEMA “ASchema“ ELEMENT “A“
    VARARRAY doc.“XMLDATA“.“B“ STORE AS TABLE “BTable“
    ((PRIMARY KEY (NESTED_TABLE_ID, SYS_NC_ARRAY_INDEX$)) ORGANIZATION INDEX)
    VARARRAY doc.“XMLDATA“.“B“.“C“ STORE AS TABLE “CTable“
    ((PRIMARY KEY (NESTED_TABLE_ID, SYS_NC_ARRAY_INDEX$)) ORGANIZATION INDEX)
    But this statement fails with the error message something like „ ... no such attribute ... „
    And here's my question: is it possible to create nested tables for repeatable XML Elements that are subelements of other repeatable XML Elements ? And if so, how can I do it ?
    Thank you very much in advance
    Jan

    Found a (partial) solution myself:
    If you add the attribute xdb:storeVarrayAsTable="true" to the root element of the XML schema, Oracle XMLDB generates nested tables for all repeatable XML Elements while registering the XML schema.
    Unfortunately, the names of these nested tables are system-generated, hence it's a bit uncomfortable to set indices on them. You can find out the names of these nested tables as follows:
    select table_name, parent_table_name, parent_table_column from user_nested_tables;
    Further information on that subject is supplied in the following thread:
    Re: default tables for elements with maxoccurs > 1
    It would be nice if there was a way to name the generated nested tables via appropriate XMLDB schema annotations.
    regards
    Jan

  • Trigger how to get new and old value for nested table column?

    Hi,
    I have created a nested table based on the following details:
    CREATE TYPE typ_item AS OBJECT --create object
    (prodid NUMBER(5),
    price NUMBER(7,2) )
    CREATE TYPE typ_item_nst -- define nested table type
    AS TABLE OF typ_item
    CREATE TABLE pOrder ( -- create database table
    ordid NUMBER(5),
    supplier NUMBER(5),
    requester NUMBER(4),
    ordered DATE,
    items typ_item_nst)
    NESTED TABLE items STORE AS item_stor_tab
    INSERT INTO pOrder
    VALUES (800, 80, 8000, sysdate,
    typ_item_nst (typ_item (88, 888)));
    Now I would like to create a trigger on table pOrder for after insert or update or delete
    and I would like to track the new and old value for the columns inside nested table.
    Can anybody direct me how to do it?
    I would like to know the sytax for it like:
    declare
    x number;
    begin
    x := :new.nestedtablecolumn;--how to get the new and old value from nested table columns
    end;
    Hope my question is clear.
    Thanks,
    Lavan

    Hi,
    Try like this:
    CREATE OR REPLACE TRIGGER PORDER_I
    BEFORE INSERT
    ON PORDER
    REFERENCING OLD AS old NEW AS new
    FOR EACH ROW
    DECLARE
      items_new typ_item_nst;
      ordid_NEW NUMBER;
    BEGIN
    FOR i IN :new.items.FIRST .. :new.items.LAST LOOP -- For first to last element
      DBMS_OUTPUT.PUT_LINE(':new.items(' || I || ').prodid: ' || :new.items(I).prodid );
      DBMS_OUTPUT.PUT_LINE(':new.items(' || I || ').price:  ' || :new.items(I).price );
    END LOOP;
    END;Regards,
    Peter

  • Using FOR .. LOOP counter in handling of PL/SQL procedures with nest. table

    Hi all!
    I'm learning PL/SQL on Steve Bobrovsky's book (specified below sample is from it) and I've a question.
    In the procedure of specified below program used an integer variable currentElement to get reference to the row of nested table of %ROWTYPE datatype.
    Meanwhile, the program itself uses a common FOR .. LOOP counter i.
    DECLARE
    TYPE partsTable IS TABLE OF parts%ROWTYPE;
    tempParts partsTable := partsTable();
    CURSOR selectedParts IS
      SELECT * FROM parts ORDER BY id;
    currentPart selectedParts%ROWTYPE;
    currentElement INTEGER;
    PROCEDURE printParts(p_title IN VARCHAR2, p_collection IN partsTable) IS
      BEGIN
       DBMS_OUTPUT.PUT_LINE(' ');
       DBMS_OUTPUT.PUT_LINE(p_title || ' elements: ' || p_collection.COUNT);
       currentElement := p_collection.FIRST;
       FOR i IN 1 .. p_collection.COUNT
       LOOP
        DBMS_OUTPUT.PUT('Element #' || currentElement || ' is ');
         IF tempParts(currentElement).id IS NULL THEN DBMS_OUTPUT.PUT_LINE('an empty element.');
         ELSE DBMS_OUTPUT.PUT_LINE('ID: ' || tempParts(currentElement).id || ' DESCRIPTION: ' || tempParts(currentElement).description);
         END IF;
        currentElement := p_collection.NEXT(currentElement);
       END LOOP;
    END printParts;
    BEGIN
    FOR currentPart IN selectedParts
    LOOP
      tempParts.EXTEND(2);
      tempParts(tempParts.LAST) := currentPart;
    END LOOP;
    printParts('Densely populated', tempParts);
    FOR i IN 1 .. tempParts.COUNT
    LOOP
      IF tempParts(i).id is NULL THEN tempParts.DELETE(i);
      END IF;
    END LOOP;
    FOR i IN 1 .. 50
    LOOP
      DBMS_OUTPUT.PUT('-');
    END LOOP;
    printParts('Sparsely populated', tempParts);
    END;
    /When I've substituted an INTEGER global variable with such FOR .. LOOP counter, an APEX have returned an error "ORA-01403: no data found".
    DECLARE
    TYPE partsTable IS TABLE OF parts%ROWTYPE;
    tempParts partsTable := partsTable();
    CURSOR selectedParts IS
      SELECT * FROM parts ORDER BY id;
    currentPart selectedParts%ROWTYPE;
    PROCEDURE printParts(p_title IN VARCHAR2, p_collection IN partsTable) IS
      BEGIN
       DBMS_OUTPUT.PUT_LINE(' ');
       DBMS_OUTPUT.PUT_LINE(p_title || ' elements: ' || p_collection.COUNT);
       FOR i IN 1 .. p_collection.COUNT
       LOOP
        DBMS_OUTPUT.PUT('Element is ');
         IF tempParts(i).id IS NULL THEN DBMS_OUTPUT.PUT_LINE('an empty element.');
         ELSE DBMS_OUTPUT.PUT_LINE('ID: ' || tempParts(i).id || ' DESCRIPTION: ' || tempParts(i).description);
         END IF;
       END LOOP;
    END printParts;
    BEGIN
    FOR currentPart IN selectedParts
    LOOP
      tempParts.EXTEND(2);
      tempParts(tempParts.LAST) := currentPart;
    END LOOP;
    printParts('Densely populated', tempParts);
    FOR i IN 1 .. tempParts.COUNT
    LOOP
      IF tempParts(i).id is NULL THEN tempParts.DELETE(i);
      END IF;
    END LOOP;
    FOR i IN 1 .. 50
    LOOP
      DBMS_OUTPUT.PUT('-');
    END LOOP;
    printParts('Sparsely populated', tempParts);
    END;
    /When I've tried to handle this code in SQL*Plus, the following picture have appeared:
    Densely populated elements: 10
    Element is an empty element.
    Element is ID: 1 DESCRIPTION: Fax Machine
    Element is an empty element.
    Element is ID: 2 DESCRIPTION: Copy Machine
    Element is an empty element.
    Element is ID: 3 DESCRIPTION: Laptop PC
    Element is an empty element.
    Element is ID: 4 DESCRIPTION: Desktop PC
    Element is an empty element.
    Element is ID: 5 DESCRIPTION: Scanner
    Sparsely populated elements: 5
    DECLARE
    ERROR at line 1:                                 
    ORA-01403: no data found                         
    ORA-06512: at line 14                            
    ORA-06512: at line 35What's wrong in code(or what I have not understood)? Help please!

    942736 wrote:
    What's wrong in code(or what I have not understood)? Help please!First code. You have collection of 10 elements:
    1 - null
    2 - populated
    3 - null
    4 - populated
    5 - null
    6 - populated
    7 - null
    8 - populated
    9 - null
    10 - populated
    Then you delete null elements and have 5 element collection
    2 - populated
    4 - populated
    6 - populated
    8 - populated
    10 - populated
    Now you execute:
    printParts('Sparsely populated', tempParts);Inside procedure you execute:
    currentElement := p_collection.FIRST;
    This assingns currentElement value 2. Then procedure loops 5 times (collection element count is 5). Element 2 exists. Inside loop procedure executes:
    currentElement := p_collection.NEXT(currentElement);
    which assigns currentElement values 4,6,8,10 - all existing elements.
    Now second code. Everything is OK until you delete null elements. Again we have:
    2 - populated
    4 - populated
    6 - populated
    8 - populated
    10 - populated
    Again you execute:
    printParts('Sparsely populated', tempParts);Now procedure loops 5 times (i values are 1,2,3,4,5):
    FOR i IN 1 .. p_collection.COUNT
    Very first iteration assingns i value 1. And since collection has no element with substript 1 procedure raises no data found.
    SY.

  • Error in bulk collect into nested table

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

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

  • XML Query Performance on Nested Tables

    I am running an Xpath query on an XMLTYPE column extracting rows from a nested table which is two levels down from the root element:
    e.g.
    select extractValue(x.xmldata,'/rootElement/VersionNumber') VerNumber
    , etc...
    , etc.
    , extractValue(value(m),'/Member/Name/Ttl') Member_title
    , to_char(extractValue(value(e),'/Event/EventDate'),'yyyy-mm-dd') Event_Date
    , extractValue(value(e),'/Event/Type') Event_type
    from xml_table x,
    table(XMLSequence(extract(x.xmldata,'/rootElement/Member'))) m
    ,table(XMLSequence(extract(value(m),'/Member/Event'))) e
    The query is taking around 7 minutes to process 2000 XML docs and the result returns 61,000 rows.
    Statspack reports indicate that the main resource used is the LOBSEGMENT which supports the SYS_XDBPD$ column (system generated) in the Member nested table - result was over 100 million Logical Reads and Consistent Gets.
    Is there any way to influence the Schema Registration/XML Table creation to result in the XDBPD$ column being stored as a Table or VARRAY - the underlying data type for XDBPD$ is:
    XDB.XDB$RAW_LIST_T VARRAY(1000) OF RAW(2000)
    OR
    Should I spend time tuning access to the LOBSEGMENT?
    Anyone tuned this area of XDB before??
    Thanks
    Dave

    Do you need DOM Fidelity at all. DOM Fidelity is typically only needed in a document orientated application or where items like processing instructions and comments are present and need to be maintaned.
    Here are some notes from some training ppt slides that may help you decide
    Dom Fidelity requires that XML DB track document level meta data
    It creates overhead when inserting and retrieving XML due to processing as well as adding additional storage requirements. Dom Fidelity can be turned on and off at the 'Type' Level Each SQL Type corresponding to a complexType where DOM is enabled includes a System Binary attribute called SYS_XDBPD$. The SYS_XDBPD$ attribute is referred to as the Positional Descriptor (PD)
    The PD is used to manage the instance level meta data. The format of the PD is not documented The PD is stored as a (in-line) LOB.
    The PD is used to track
    Comments and Processing Instructions
    Location and Prefixes in Namespace declarations
    Empty Vs Missing Nodes
    Presence of Default Values
    Use of Substitutable elements
    Ordering of elements in all and choice models
    XMLSchemaInstance attributes
    xsi:nil, xsi:Type
    Mixed content –
    Text() nodes that are interspaced with elements
    Disabling DOM Fidelity improves performance
    Reduces storage requirements
    Reduces elapsed time for insert and retrieval operations
    DOM Fidelity is disabled on a Type by Type basis
    Use annotation xdb:maintainDOM="false“ on complexType definition
    Specifying xdb:maintainDOM="false“
    Removes the PD attribute from the SQLType.
    Causes the information managed in the PD to be discarded when shredding the XML document
    In general you can disable DOM Fidelity when
    All information is represented as simple content
    Elements with text() node children and or attribute values
    XML does not make use Mixed Text
    No Comments or Processing Instructions
    Applications do not need to differentiate between empty and missing elements
    Applications do not differentiate between default Vs missing values
    Order of elements in repeating Sequence, All and Choice models is not meaningful
    Typically Data-Centric XML does not require DOM Fidelity while Document Centric XML does. With DOM Fidelity disabled retrieved documents will still be valid per the XML Schema
    Order is preserved when repetition is specified at element or complexType level
    Use annotation xdb:maintainOrder=“false” for slight performance improvement in this case that order is not required in these cases.
    Order is not preserved when repetition is specified at the ‘model’ level, eg on a Choice, Sequence or All containing multiple child elements.
    Take the following document
    <?xml version="1.0" encoding="UTF-8"?>
    <!--Sample XML file generated by XMLSPY v2004 rel. 4 U (http://www.xmlspy.com)-->
    <dft:root xmlns:dft="domFidelityTest"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="domFidelityTest domFidelityExample">
    <?SomePI SomeValue?>
         <xxx:choice xmlns:xxx="domFidelityTest">
         <!--SomeComment-->
              <xxx:A>String</xxx:A>
              <xxx:B>String</xxx:B>
              <?Another PI SomeOtherValue?>
              <xxx:C>String</xxx:C>
              <xxx:A>String</xxx:A>
              <!--Another Comment-->
              <xxx:B>String</xxx:B>
              <xxx:C xsi:nil="true"/>
    </xxx:choice>
    </dft:root>
    With DOM Fidelity disabled it would come back as
    <?xml version="1.0" encoding="WINDOWS-1252"?>
    <!--Sample XML file generated by XMLSPY v2004 rel. 4 U (http://www.xmlspy.com)-->
    <dft:root xmlns:dft="domFidelityTest“ testAttr="NotInOriginal">
    <dft:choice>
    <dft:A>String</dft:A>
    <dft:A>String</dft:A>
    <dft:B>String</dft:B>
    <dft:B>String</dft:B>
    <dft:C>String</dft:C>
    <dft:C/>
    </dft:choice>
    </dft:root>
    In general you can disable DOM Fidelity and see reduced storage requirements and increased throughout...
    Hope this helps...

  • How to return a OCI Table * (nested table) from OCI application to sqlplus

    Hi,
    How to return a OCI Table * (nested table) from OCI application to sqlplus prompt : OCITAble * shows up as empty on the SQLPLUS prompt.
    The ODCIAggregateTerminate member function's OUT parameter is OCITable * returnValue. After completion of this member function it displays data on the sqlplus prompt.
    My problem is that eventhough my OCITable(returnvalue) has elements appended or added to it. But when I return the OCITAble after completion
    of this member function the OCITable shows up as empty collection on the SQLPLUS prompt. But in the OCI code if I iterate through the collection
    I can print out the elements and see their values or data.
    Can any one let me know how I can make the elements or data in the collection available at SQLPLUS prompt after the completion of this member function.
    If my return value or OUT parameter of this member function is OCINumber * returnValue : then I can see the corresponding value assigned in the OCI Code
    and the same value is returned and visible on the SQLPLUS prompt. But when I use the OUT parameter as OCITAble * : then it shows up as empty collection.
    I don't really know why is it happening so.
    member function ODCIAggregateTerminate(
    self IN OUT MinDistanceImpl, returnValue OUT table_out1,
    flags IN number)
    return number
    as language C
    library custagg name "ODCIAggregateTerminate"
    with context
    parameters (
    context,
    self,
    self INDICATOR STRUCT,
    returnValue ,
    returnValue INDICATOR,
    flags,
    flags INDICATOR ,
    RETURN ),
    typedef OCITable table_out1;
    struct ntab_type
    OCINumber empno;
    OCINumber salary;
    OCIString * tst;
    OCIString * te;
    typedef struct ntab_type ntab_type;
    struct ntab_type_ind
    OCIInd _atomic;
    OCIInd empno;
    OCIInd salary;
    OCIInd tst;
    OCIInd te;
    typedef struct ntab_type_ind ntab_type_ind;
    extern "C" OCINumber * ODCIAggregateTerminate(
    OCIExtProcContext *context,
    MinDistanceImpl * self,
    MinDistanceImpl_ind * self_ind,
    table_out1 * returnValue,
    short * returnValue_ind,
    OCINumber * flags,
    short flags_ind)
    ocitypename for collection..
    ocitypename for element
    ociobjectnew for collection
    ociobjectNew's for elements
    ocicollappend of elements to collection
    then iterate thru collection
    and at them collection as those elements and we return that collection
    But is empty : on SQLPLUS prompt :
    Select Mindis(TT) from table1;
    TT(empno, salary, tstart, te)
    Table_Out1()

    > Can anyone pls let me know if there is some way to return an entire table from a function which
    is called from a stored procedure?
    For what purpose?
    Do you realise that this means pulling Megabytes (or even many Gugabytes) of data from disk, into the buffer cache, and then copying that data into PL/SQL memory (using a function) in order to give a stored proc that data?
    This is just plain crazy.. resource wise, performance wise, scalability wise.. this is exactly how NOT to use Oracle.
    Why don't you instead tell us what problem you want to solve. Forget for the moment what you think the solution should be. (and asking us how to get a potentially flawed solution, to work)
    Let's get an accurate problem definition so that we can provide you with suggestions and recommendation on what Oracle features can be used to address that problem.

  • Collection -- Nested tables

    Hi,
    I am trying to use collections as nested tables from below mentioned procedure, but facing a problem of getting only last rows.
    Any help would be appreciated.
    +CREATE OR REPLACE PROCEDURE pr_collection
    AS
    TYPE type_num IS TABLE OF NUMBER;
    t_num type_num;
    TYPE type_char IS TABLE OF VARCHAR2 (20);
    t_char type_char;
    BEGIN
    FOR i IN (SELECT eid, nm
    FROM emp)
    LOOP
    t_num := type_num (i.eid);
    t_char := type_char (i.nm);
    DBMS_OUTPUT.put_line (i.eid || i.nm);
    END LOOP;
    DBMS_OUTPUT.put_line (t_num.COUNT);
    DBMS_OUTPUT.put_line (t_num.FIRST);
    DBMS_OUTPUT.put_line (t_num.LAST);
    FORALL J IN T_NUM.FIRST.. T_NUM.LAST
    INSERT INTO TEST
    VALUES (t_num (J), t_char (J));
    COMMIT;
    END;
    /+
    Output :
    1
    1
    1
    Thanks in Advance,
    Prashant

    Hi,
    It's normal, you get only the last element because of the following
    LOOP
        t_num := type_num (i.eid);
        t_char := type_char (i.nm);
    END LOOP;Each time you call the nested table constructor with the new element, so the previous elements are lost. The correct way of doing this is to call once the constructor before the LOOP and then call the EXTEND method inside the loop in order to make room available for each new element.
    Therefore, something like this:
    CREATE OR REPLACE PROCEDURE pr_collection AS
        TYPE type_num IS TABLE OF NUMBER;
        t_num type_num;
        t_num_idx PLS_INTEGER := 1;
        TYPE type_char IS TABLE OF VARCHAR2 (20);
        t_char type_char;
        t_char_idx PLS_INTEGER := 1;
    BEGIN
        t_char := type_char();
        t_num := type_num();
        FOR i IN (SELECT eid, nm FROM emp) LOOP
            t_num.EXTEND;
            t_num(t_num_idx) := i.eid;
            t_num_idx := t_num_idx + 1;
            t_char.EXTEND;
            t_char(t_char_idx) := i.nm;
            t_char_idx := t_char_idx + 1;
            DBMS_OUTPUT.put_line (i.eid || i.nm);
        END LOOP;
        DBMS_OUTPUT.put_line (t_num.COUNT);
        DBMS_OUTPUT.put_line (t_num.FIRST);
        DBMS_OUTPUT.put_line (t_num.LAST);
        FORALL J IN T_NUM.FIRST.. T_NUM.LAST
            INSERT INTO TEST VALUES (t_num (J), t_char (J));
        COMMIT;
    END;That being said, why do you add elements one by one, it is slow, why not using BULK COLLECT?
    Regards,
    Dariyoosh

  • How to use nested tables in adobe form

    Hi All,
    I have to use nested tables in adobe form for table display. I have used Subforms for displaying table data. I have changed accessibility of the subforms. Currently i am able to print print the table correctly if there is single material record in table 1 and single corresponding record in table 2. But the requirement is that i will have multiple lines in table 1 for single material and only one record in table 2.
    EX: form is for Sales order. in line items if the order is for 100 units then we if we have delivered material as 80, 10, 10, then table 1 will have 3 lines for this. Table 2 will always have only 1 corresponding record.
    item--materialdescription-ordered qty--delivered qty--delivery date-price  
    xxx--xxxxxxx-xxxxxxxxx-10080xxxxxxxxxx-xxxx
    10----
    xxxxxxxxxx
    10----
    xxxxxxxxxx
    yyyyyyyyyyyyyyyyyyy------yyyyyyyyyyyyyyyyyyyyy 
    xxxxxx is table 1 and will have multiple lines
    yyyyyy is table 2 and will have only 1 entry for item xxx
    and this group will be repeate as per no of items. table 1 can have any no of lines per item.
    I am currently able to display 1 line for table 1 and 1 line for table 2.
    But how to show multiple lines for table 1 and 1 line for table 2.

    HI,
          Set the body page as flowed and set the tables also flowed.
    go to bodypage>object->subform-->select flowed option.
    I thihnk this will work..if u are getting all the records properly into the tables 1 and 2.
    Thanks,
    Mahdukar

  • Update Nested Table Problem

    Hi All,
    I have a update problem in nested table.
    Below is my query:
    CREATE OR REPLACE TYPE TRACER.SEARCH_DATA AS TABLE OF VARCHAR2(20);
    UPDATE TRACER_SEARCH_SCHEDULE_LOT_NUM
    SET NOT_FOUND_SOR_LOT_NUM = SEARCH_DATA(
    SELECT
    COLUMN_VALUE
    FROM
    TABLE (SELECT SORTING_LOT_NUMBER FROM TRACER_SEARCH_SCHEDULE_LOT_NUM WHERE JOB_ID = 8)
    WHERE
    TRIM(COLUMN_VALUE) NOT IN (SELECT DISTINCT (SORTING_LOT_NUMBER) FROM SEARCH_SCHEDULE_RESULT_LOT_NUM WHERE JOB_ID = 8)
    ) WHERE JOB_ID = 8;
    ORA-00936: missing expression
    or I try as following
    DECLARE
    sor_lot_num_not_found SEARCH_DATA :=
    SEARCH_DATA
    SELECT
    FROM
    TABLE (SELECT SORTING_LOT_NUMBER FROM TRACER_SEARCH_SCHEDULE_LOT_NUM WHERE JOB_ID = 8)
    WHERE
    TRIM(COLUMN_VALUE) NOT IN (SELECT DISTINCT (SORTING_LOT_NUMBER) FROM SEARCH_SCHEDULE_RESULT_LOT_NUM WHERE JOB_ID = 8)
    BEGIN
    UPDATE TRACER_SEARCH_SCHEDULE_LOT_NUM SET NOT_FOUND_SOR_LOT_NUM = sor_lot_num_not_found WHERE JOB_ID = 8;
    END;
    ORA-06550: line 5, column 9:
    PLS-00103: Encountered the symbol "SELECT" when expecting one of the following:
    ( ) - + case mod new not null others <an identifier>
    table avg count current exists max min prior sql stddev sum
    variance execute multiset the both leading trailing forall
    merge year month DAY_ hour minute second timezone_hour
    timezone_minute timezone_region timezone_abbr time timestamp
    interval date
    <a string literal with character set specificat
    ORA-06550: line 11, column 5:
    PLS-00103: Encountered the symbol ")" when expecting one of the following:
    ; for and or group having intersect minus order start union
    where connect
    ORA-06550: line 14, column 4:
    PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
    begin case declare end exception exit for goto if loop mod
    null pragma raise return select update while with
    <an identifier> <a double-quoted d
    I have try on the Select Statement, it work. So is it the way that I assign data from nested table and update method is wrong?
    Edited by: skymonster84 on Mar 8, 2011 5:12 PM

    Hi,
    I think MULTISET operators might interest you.
    http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/operators006.htm
    Not tested :
    UPDATE tracer_search_schedule_lot_num
    SET not_found_sor_lot_num =
          sorting_lot_number
          MULTISET EXCEPT ALL
          CAST(
            MULTISET(
              SELECT distinct sorting_lot_number
              FROM search_schedule_result_lot_num
              WHERE job_id = 8
            AS search_data
    WHERE job_id = 8
    ;

  • Null value in Nested table of nested table for xml guru Steve Muench

    The procedure I am using takes xml document with nested levels and insert into single table using DBMS_XMLSave.insertXML.
    I am able to insert into table without any error message but when I am selecting row from table, it is showing null values in all the column of nested table's inner nested table.
    When I am removing nested table's nested table by replacing with object type, it is showing data of object type for the first occurance and ignoring the rest nested occurance.
    Help is greatly appreciated.
    Below is the sql I used to create objects and table:-
    Create or Replace Type addressType as Object
    Line_one     varchar2(40),
    Line_two     varchar2(40),
    City          Varchar2(30),
    State          Varchar2(2),
    zip          Varchar2(10)
    Create or Replace Type ce_reqType as Object
    Status               varchar2(25),
    Status_date          Date,
    type_code          Varchar2(25),
    review_begin_date     Date,
    assigned_review_date     date
    Create or Replace type ce_reqListType
    as table of ce_reqType;
    Create or Replace Type LicenseType as Object
    type_code          Varchar2(10),
    license_number          Varchar2(16),
    ce_requirements      ce_reqListType
    Create or Replace type LicenseListType
    as table of LicenseType;
    Create table IndividualType
    individual_id          Number(9),
    social_security_number Varchar2(9),
    Last_name          varchar2(40),
    First_name          Varchar2(40),
    Middle_name          Varchar2(40),
    Birth_date          Date,
    address          addressType,
    Licenses          LicenseListType
    nested table licenses store as licensestab
    (nested table ce_requirements store as lic_ce_reqtab);

    Maddy wrote:
    dbms_output.put_line('The count is '||bookset.count); --> I can see COUNT =1 (why)Because instead of adding an element to bookset collectionto are assigning (ergo replacing) it a collection containing last fetched book. Use:
    declare
        bookset book_table;
        ln_cnt pls_integer;
    begin
        bookset := book_table(book_obj('madhu','kongara','sudhan'));
        dbms_output.put_line('The count is '||bookset.count); --> I can see COUNT =1
        bookset := book_table(); --> Assigning back to NULL.
        dbms_output.put_line('The count is '||bookset.count); --> I can see count as 0
        for rec in (select * from book) loop --> Now Looping two times.
          dbms_output.put_line(' name > '||rec.name);
          bookset.extend;
          bookset(bookset.count) := book_obj(rec.name, rec.author, rec.abstract);
        end loop;
        dbms_output.put_line('The count is '||bookset.count); --> I can see COUNT =1 (why)
    end;
    The count is 1
    The count is 0
    name > Harry Potter
    name > Ramayana
    The count is 2
    PL/SQL procedure successfully completed.
    SQL> Or better use bulk collect:
    declare
        bookset book_table;
        ln_cnt pls_integer;
    begin
        bookset := book_table(book_obj('madhu','kongara','sudhan'));
        dbms_output.put_line('The count is '||bookset.count); --> I can see COUNT =1
        bookset := book_table(); --> Assigning back to NULL.
        dbms_output.put_line('The count is '||bookset.count); --> I can see count as 0
        select  book_obj(name,author,abstract)
          bulk collect
          into  bookset
          from  book;
        for i in 1..bookset.count loop --> Now Looping two times.
          dbms_output.put_line(' name > '||bookset(i).name);
        end loop;
        dbms_output.put_line('The count is '||bookset.count); --> I can see COUNT =1 (why)
    end;
    The count is 1
    The count is 0
    name > Harry Potter
    name > Ramayana
    The count is 2
    PL/SQL procedure successfully completed.
    SQL> SY.

Maybe you are looking for