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:12user8117512 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
EnricoHi 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
JanFound 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,
LavanHi,
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
DaveDo 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. -
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,
PrashantHi,
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 -
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 PMHi,
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
-
Problems on selecting views with french characters into column names
Hi All, I have views with column names such as "Détermination Planimétriq" or "Année de construction:*"; I can get in my c# function this columns names from ALL_VIEWS dictionary table, but if I try to make a selectionby use of an OracleCommand, Oracl
-
Scsi messages in /var/adm/messages file
Hi, After open the /var/adm/messages i have the SCSI error messages: Jul 8 15:45:13 kapttdw2 Corrupt label; wrong magic number Jul 8 15:45:13 kapttdw2 scsi: [ID 107833 kern.warning] WARNING: /ssm@0,0/pci@1a,600000/SUNW,qlc@1/fp@0,0/ssd@w5006048452a65
-
I updated yesterday to iOS 6, but it has brought me some problems. I rather stay with the 5.1.1 version as it was. Just I cannot find the software download to do this. Thank you.
-
Pixel Bender does not show in filters after installation but shows in extension mgr as plugin
I installed pixel bender (64bit) into my CS5 extended group through the extension manager as administrator as per directions for win 7. All went well and I restarted both PS5 and the computer. I do not have any pixel bender option under filters or an
-
Product registrastion won't stop asking me to regis
I have registered every Creative poduct I have. Recently I purchased a Creative usb camera. I've had it for a few weeks and just yesturday I keep getting a message to register all my products. It is still coming up even though I have nothing left to