How to select columns from nested table which points to object references - oracle

I have type:
CREATE OR REPLACE TYPE something AS OBJECT(
name VARCHAR2(100),
nestedObjects objects
);
where objects type is table of references:
CREATE TYPE objects IS TABLE OF REF object;
and object is:
CREATE OR REPLACE TYPE object AS OBJECT (
number NUMBER
);
then I create table:
CREATE TABLE tab_something OF something
NESTED TABLE nestedObjects STORE AS tab_nestedObjects;
and I want select numbers from objects contained in something table, I try:
SELECT ts.name, cursor(
select deref(object).number
from TABLE(ts.nestedObjects) object
) FROM tab_something ts;
or:
SELECT DEREF(object).number
FROM tab_something ts, TABLE(ts.nestedObjects) object;
but it doesn't work. Oracle say 'object' identifier does not valid.
When nestedObjects consist of objects then it work well because there is no need to deal with references. but when it points to object references it does not work. Ho can I deal with it?
THANKS FOR HELP!

Ok I resolved:
SELECT DEREF(VALUE(object)).number
FROM tab_something ts, TABLE(ts.nestedObjects) object;

Related

ORACLE: The best way to parse JSON into collection of object types

I have an object type: create type t_ref_rec is object(id number, name varchar2(256));
And a table type: create type t_ref_tbl is table of t_ref_rec;
I parse JSON onto a collection like this:
declare
var_ref_tbl t_ref_tbl;
begin
...
select
t_ref_rec(id, name)
bulk collect into
var_ref_tbl
from
json_table
(
'[{"id":1, "name":"one"}, {"id":2, "name":"two"}]',
'$[*]'
columns
(
id number path '$.id',
name varchar2 path '$.name'
)
);
....
end;
Is there a better way to parse data from JSON into a collection of t_ref_tbl type?
If you're on 19c or higher, the best way is to state your object as the return type for a JSON_value call and the database will map it for you:
create type t_ref_rec is object(id number, name varchar2(256));
/
create type t_ref_tbl is table of t_ref_rec;
/
select json_value (
'[{"id":1, "name":"one"}, {"id":2, "name":"two"}]',
'$' returning t_ref_tbl
) obj
from dual;
OBJ(ID, NAME)
---------------------------------------------------
T_REF_TBL(T_REF_REC(1, 'one'), T_REF_REC(2, 'two'))
The on mismatch clause enable you to define what happens if there's a difference between the JSON document and the object type.

Insert records into collection type Oracle

I want to inserted into my collection some SQL records, but I can not. I'm a beginner. Can you help me ?
This is my tables :
CREATE TYPE article_type AS OBJECT (idA CHAR(10), nomA CHAR(10), prixA CHAR(10) )
CREATE TYPE facture_type AS OBJECT (idF CHAR(10), dateFact DATE)
CREATE TYPE ens_collection_fact AS OBJECT (refFact facture_type, refArticle article_type)
CREATE TYPE collection_fact AS TABLE OF ens_collection_fact
CREATE TYPE client_type AS OBJECT (idC NUMBER, nomC CHAR(10),adresse CHAR(10), Compose collection_fact )
CREATE TABLE Article OF article_type
CREATE TABLE Facture OF facture_type
CREATE TABLE Client OF client_type (PRIMARY KEY(idC)) NESTED TABLE Compose STORE AS temp
This is my query that I want to insert, but I have an error from the Oracle : ORA-02315
INSERT INTO ECOLER.CLIENT VALUES
(100, 'Jules Verne', '1', Collection_fact(Ens_collection_fact(reffact('A','2002-12-10'), ens_collection_fact(refarticle('D','E','F'))) ))
Thank in advance
reffact and refarticle are identifiers for objects within other objects, not types; you need to refer to the actual types. You also need to supply both values for each Ens_collection_fact attribute for the default constructor; you can pass null if you only want one or the other:
INSERT INTO CLIENT VALUES
(100, 'Jules Verne', '1',
Collection_fact(
Ens_collection_fact(facture_type('A',date '2002-12-10'), null),
Ens_collection_fact(null, article_type('D','E','F'))
)
)
Also notice that I've added the date keyword so it's providing an actual date literal rather than a string, which would be converted - if you're lucky - with your session NLS settings.
This will still error because 'Jules Verne' is 11 characters and you've defined the name attribute as 10 characters/bytes, but it will work with a shorter string literal.
db<>fiddle

Unable to create a table with a column of object type (and the same object type contains an attribute of nested table type)

I am trying to create a table with a column of object type and tricky nested table hierarchy. Getting ORA-22913 error. In CREATE table statement the column "theCol" is of type object (i.e. MainObj). MainObj contains an attribute of type nested table i.e. ChildTab.
I think am supposed to use NESTED TABLE clause in CREATE TABLE statement. But not sure how to use it here because "theCol" is NOT of nested table type.
DROP TYPE MainObj;
DROP TYPE ChildTab;
DROP TYPE ChildObj;
CREATE TYPE ChildObj AS OBJECT (
naame varchar2(20)
, kaam varchar2(20)
);
/
CREATE TYPE ChildTab AS TABLE OF ChildObj;
/
Create TYPE MainObj as OBJECT (
KEEY VARCHAR2(5),
ChildList ChildTab
);
/
CREATE TABLE TestTableDesi (
theCol MainObj
);
/
Type dropped.
Type dropped.
Type dropped.
Type created.
Type created.
Type created.
ORA-22913: must specify table name for nested table column or attribute
Just found the solution here. How do I create an Oracle table of objects containing nested tables?
The create table statement should be as follows.
CREATE TABLE TestTableDesi (
theCol MainObj
) nested table theCol.ChildList store as ChildList_tab ;
/

SQL3 ORA-22913: must specify table name for nested table column or attribute

I am trying to define a table in SQL3 of a type that contains a nested table in its type declaration. I do not understand why I am always getting the same error despite having tried several solutions. Here is the piece of code:
create type Composite;
/
create type L_PieceComposite as table of ref Composite;
/
create type Piece as object(
name VARCHAR(20),
containedInto L_PieceComposite
)
not final not instantiable;
/
create type PieceQuantity as Object (
quantity NUMBER,
pieceref ref Piece
);
/
create type L_PieceQuantity as table of PieceQuantity;
/
create type Composite UNDER Piece(
cost NUMBER,
contains L_PieceQuantity
);
/
In another file I use:
create table thePieces of Piece;
CREATE TABLE theComposites of Composite NESTED TABLE contains store as tab7;
But get the following error:
ORA-22913: must specify table name for nested table column or attribute
Could anyone help?
Thanks
SOLVED..conclusion: we must beware of inherited tables.
create table lesComposites of Composite nested table containedInto store as tab5 nested table contains store as tab6;

(Oracle) How to extract a specialized UDO from a object table based on a generalized UDO?

I apologize in advance for not knowing the terminology, but here it goes:
How do I extract a specialized UDO (UDO= user defined object & specialized= that 'extends' or is 'under' another UDO) that I inserted in a object table defined for a generalized UDO (generalized - higher in the same UDO hierarchy).
Details:
CREATE OR REPLACE TYPE GENERIC_UDO AS OBJECT (
atribute_1 TYPE,
...
atribute_n TYPE2, //TYPE2 is a nested table
) NOT FINAL NOT INSTANTIABLE;
CREATE OR REPLACE TYPE SPECIALIZED_UDO UNDER GENERIC_UDO (
atribute_1 TYPE,
...
atribute_q TYPE3, //TYPE3 is also a nested table
) FINAL INSTANTIABLE;
CREATE TABLE TBL_GENERIC_UDO OF GENERIC_UDO
( CONSTRAINT PK...)
... //other nested tables
NESTED TABLE atribute_n STORE AS atribute_n_nst;
So this works:
INSERT INTO TBL_GENERIC_UDO values (new TBL_GENERIC_UDO(...)); because TBL_GENERIC_UDO is 'under' GENERIC_UDO.
A 'select * from TBL_GENERIC_UDO' shows me as columns just the GENERIC_UDO atributes (as expected!)
So how do I extract or extract and convert, because I need to read back the inserted SPECIALIZED_UDO.
I payed a bit with:
VALUE(x): SELECT VALUE(tgo) FROM TBL_GENERIC_UDO tgo;
TREAT(x as Y): SELECT TREAT(VALUE(tgo) as SPECIALIZED_UDO) FROM TBL_GENERIC_UDO tgo;
and no good results. Actually in booth cases I get
SCHEMANAME.SPECIALIZED_UDO(values, values,..., null)
oracle.sql.STRUCT#54faa2
In the first case, when I did the insert, the corespondent value for atribute_q was set to null, in the second one it was a proper value, ex: SPECIALIZED_UDO('value1','value1',...)
I am asumming thats because TBL_GENERIC_UDO doesnt have a store clause for atribute_q from SPECIALIZED_UDO.
So anyone thoughts, explanations would be appreciated.
Solved it myself! Wasn't that hardcore as I expected. First I thought that Oracle will 'truncate' when inserting a specialized UDO into the table defined for a generic UDO, and in my case the specialized UDO had additionally another nested table as a atribute, but it doesn't.
Check code example, last line is the most important one:
CREATE OR REPLACE TYPE OBJ_TBL_TEXT IS TABLE OF VARCHAR2(100);
CREATE OR REPLACE TYPE OBJ_CONTAINER1 AS OBJECT (
ATRIBUTE NUMBER(6),
TBL_TEXT OBJ_TBL_TEXT
) NOT FINAL NOT INSTANTIABLE;
CREATE OR REPLACE TYPE OBJ_CONTAINER2 UNDER OBJ_CONTAINER1(
SECOND_TBL_TEXT OBJ_TBL_TEXT
) FINAL INSTANTIABLE;
CREATE TABLE TBL_CONTAINER1 OF OBJ_CONTAINER1
( CONSTRAINT PK_TBL_CONTAINER1 PRIMARY KEY(ATRIBUTE))
NESTED TABLE TBL_TEXT STORE AS TBL_TEXT_NST;
INSERT INTO TBL_CONTAINER1 VALUES (NEW OBJ_CONTAINER2(1,null,null));
INSERT INTO TBL_CONTAINER1 VALUES (NEW OBJ_CONTAINER2(2,null, OBJ_TBL_TEXT('VAL1','VAL2')));
INSERT INTO TBL_CONTAINER1 VALUES (NEW OBJ_CONTAINER2(3,OBJ_TBL_TEXT('VAL3','VAL4'), null));
INSERT INTO TBL_CONTAINER1 VALUES (NEW OBJ_CONTAINER2(4,OBJ_TBL_TEXT('VAL5','VAL6'), OBJ_TBL_TEXT('VAL7','VAL8')));
--------------------------------------------------------------------------------
SELECT * FROM TBL_CONTAINER1;
SELECT VALUE(tc) FROM TBL_CONTAINER1 tc;
SELECT TREAT(VALUE(tc) as OBJ_CONTAINER2).SECOND_TBL_TEXT FROM TBL_CONTAINER1 tc;
First select will display as columns just the atributes from the OBJ_CONTAINER1, like:
ATTRIBUTE| TBL_TEXT
--===============--
- 1 (null)
- 2 (null)
- 3 VARCHAR(VAL3,VAL4)
- 4 VARCHAR(VAL5,VAL6)
Second one looks weirder
VALUE(TC)
--=====--
DATAMODELER.OBJ_CONTAINER2(1,null,null)
oracle.sql.STRUCT#57ac8e
oracle.sql.STRUCT#1df6f
oracle.sql.STRUCT#f40801
VALUE - returns the object instance for a row of an object table as associated with the correlation_variable (table alias)
Third one lets me have access to nested attributes not mention in the nested clause in the creation of TBL_CONTAINER1.
TREAT(VALUE(tc) as OBJ_CONTAINER2).SECOND_TBL_TEXT
--==============================================--
(null)
VARCHAR(VAL1,VAL2)
(null)
VARCHAR(VAL7,VAL8)
It is exactly what I needed. Dont know yet how Oracle stores the additional attributes, and don't care. Though to share the solution...

Resources