What is the purpose of "RETURN AS VALUE" in NESTED TABLES (Oracle 9i) - oracle

Is there a specific case, when i should use RETURN AS VALUE?
Normally i use only NESTED TABLE xxx STORE AS xxx
For example:
CREATE OR REPLACE TYPE address_t AS OBJECT (
ADDID NUMBER(10,0),
STREET VARCHAR2(40),
ZIP VARCHAR2(5),
CITY VARCHAR2(40)
)
/
CREATE OR REPLACE TYPE addresses_nt AS TABLE OF address_t
/
CREATE OR REPLACE TYPE invoicepos_t AS OBJECT (
ARTID NUMBER(10,0),
AMOUNT NUMBER(10,0)
)
/
CREATE OR REPLACE TYPE invoicepos_nt AS TABLE OF invoicepos_t
/
CREATE OR REPLACE TYPE customer_t AS OBJECT (
CUSID NUMBER(10,0),
FIRSTNAME VARCHAR2(30),
LASTNAME VARCHAR2(30),
ADDRESSES addresses_nt
)
/
CREATE OR REPLACE TYPE invoice_t AS OBJECT (
INVOICEID NUMBER(10,0),
CUSTOMER REF customer_t,
ADDID NUMBER(10,0),
POSITIONS invoicepos_nt
)
/
CREATE TABLE customer OF customer_t
NESTED TABLE ADDRESSES STORE AS all_adresses RETURN AS VALUE
/
CREATE TABLE invoices OF invoice_t
NESTED TABLE POSITIONS STORE AS all_invoicepos RETURN AS VALUE
/

As far as I can tell, the only difference is that LOCATORs are a bit faster than VALUEs. But that doesn't make sense and I'm hoping somebody will prove me wrong; there's almost never a "fast=true" switch.
According to the SQL Language Reference:
RETURN [AS] Specify what Oracle Database returns as the result of a query.
VALUE returns a copy of the nested table itself.
LOCATOR returns a collection locator to the copy of the nested table.
The locator is scoped to the session and cannot be used across sessions. Unlike a LOB locator, the collection locator cannot be used to modify the collection instance.
This implies that LOCATORs are read-only. But on 11gR2 a LOCATOR can still be modified.
The Object Relational Developer's Guide also discusses LOCATORs, but does not mention any downsides to using them.
Sample Schema
CREATE OR REPLACE TYPE invoicepos_t AS OBJECT (
ARTID NUMBER(10,0),
AMOUNT NUMBER(10,0)
)
/
CREATE OR REPLACE TYPE invoicepos_nt AS TABLE OF invoicepos_t
/
create table invoices_val
(
INVOICEID NUMBER,
POSITIONS invoicepos_nt
)
NESTED TABLE POSITIONS STORE AS all_invoicepos_val RETURN AS VALUE
/
create table invoices_loc
(
INVOICEID NUMBER,
POSITIONS invoicepos_nt
)
NESTED TABLE POSITIONS STORE AS all_invoicepos_loc RETURN AS locator
/
insert into invoices_val values(1, invoicepos_nt(invoicepos_t(1,1)));
insert into invoices_loc values(1, invoicepos_nt(invoicepos_t(1,1)));
insert into invoices_def values(1, invoicepos_nt(invoicepos_t(1,1)));
commit;
Compare performance and funcionality
--Value: 1.0 seconds
declare
v_positions invoicepos_nt;
begin
for i in 1 .. 10000 loop
select positions
into v_positions
from invoices_val;
end loop;
v_positions.extend;
v_positions(2) := invoicepos_t(3,3);
update invoices_val set positions = v_positions;
end;
/
--Locator: 0.8 seconds
declare
v_positions invoicepos_nt;
begin
for i in 1 .. 10000 loop
select positions
into v_positions
from invoices_loc;
end loop;
v_positions.extend;
v_positions(2) := invoicepos_t(3,3);
update invoices_loc set positions = v_positions;
end;
/

Related

Insertion in Nested Tables on Oracle DB

I am a new learner of PL/SQL databases,A kind of exercise given to apply database on apex.oracle.com with given sequence.Then I have created tables but when it comes to fill tables with the insertion code as follows,Application has given error,Would you mind if I need your assistance
Thanks in Advance,
CREATE TYPE TEMPORAL_VARCHAR AS OBJECT (
VALID_TIME_LOWER_BOUND DATE,
VALID_TIME_UPPER_BOUND DATE,
VALUE_PART VARCHAR2(50)
);
CREATE TYPE TEMPORAL_NUMBER AS OBJECT (
VALID_TIME_LOWER_BOUND DATE,
VALID_TIME_UPPER_BOUND DATE,
VALUE_PART NUMBER );
Time-related attributeshave defined with the code as follows;
CREATE TYPE NAME_TYPE AS TABLE OF TEMPORAL_VARCHAR;
CREATE TYPE ADDRESS_TYPE AS TABLE OF TEMPORAL_VARCHAR;
CREATE TYPE DEPARTMENT_TYPE AS TABLE OF TEMPORAL_VARCHAR;
CREATE TYPE MANAGER_TYPE AS TABLE OF TEMPORAL_VARCHAR;
CREATE TYPE SALARY_TYPE AS TABLE OF TEMPORAL_NUMBER;
CREATE TABLE EMPLOYEE (
SSN NUMBER primary key,
NAME NAME_TYPE,
ADDRESS ADDRESS_TYPE ,
BIRTH_DATE DATE,
MANAGER MANAGER_TYPE ,
DEPARTMENT DEPARTMENT_TYPE,
SALARY SALARY_TYPE
)
NESTED TABLE NAME STORE AS NAME_TABLE,
NESTED TABLE ADDRESS STORE AS ADDRESS_TABLE,
NESTED TABLE MANAGER STORE AS MANAGER_TABLE,
NESTED TABLE DEPARTMENT STORE AS DEPARTMENT_TABLE,
NESTED TABLE SALARY STORE AS SALARY_TABLE
;
And the insertion that I am inteded to do
INSERT INTO EMPLOYEE VALUES
(101,
NAME(TEMPORAL_VARCHAR('23.11.2005','12.31.9999','James Brown')),
ADDRESS(TEMPORAL_VARCHAR('23.11.2005','12.31.9999','BUCA, IZMIR')),
'23.10.1986',
MANAGER(TEMPORAL_VARCHAR('23.11.2005','12.31.9999','Mike White')),
DEPARTMENT(TEMPORAL_VARCHAR('23.11.2005','12.31.9999','DEPT_ID05')),
SALARY(TEMPORAL_NUMBER('23.11.2005',’12.31.9999’, 250000))
);
And the error message I recieved is :
ORA-00904: "SALARY": invalid identifier
There are spaces before _ here
CREATE TYPE MANAGER _TYPE AS TABLE OF TEMPORAL_VARCHAR;
CREATE TYPE SALARY _TYPE AS TABLE OF TEMPORAL_NUMBER;
DEPARTMENT DEPARTMENT _TYPE
A comma is missing after DEPARTMENT _TYPE
try this solution:
'alter session set NLS_DATE_FORMAT='DD.MM.YYYY';'
----------------------------------------------------
INSERT INTO EMPLOYEE VALUES
(101,
NAME_TYPE(TEMPORAL_VARCHAR('23.10.1986','09.09.9999','James Brown')),
ADDRESS_TYPE(TEMPORAL_VARCHAR('15.12.2009','09.09.9999','BUCA')),
'23.10.1986',
MANAGER_TYPE(TEMPORAL_VARCHAR('24.05.2008','09.09.9999','Mike White')),
DEPARTMENT_TYPE(TEMPORAL_VARCHAR('03.01.2012','09.09.9999','DEPT_ID05')),
SALARY_TYPE(TEMPORAL_NUMBER('01.01.2003','09.09.9999', 3200))
);

Update a table which has a nested table

My application has users (and subtype applicant) and jobs, with applicants being able to submit applications for jobs. I have objects types and tables set up as below :
create or replace type user_typ as object(
user_id number(19,0),
username nvarchar2(40 char)
)NOT FINAL;
I inherit an applicant_typ from this :
create or replace type applicant_typ under user_typ (
resume_text nclob
);
My design involves jobs to which applicants can apply. To this end, I create an application_typ as follows :
create or replace TYPE Application_typ AS OBJECT (
application_id NUMBER,
candidate applicant_typ,
time_of_app DATE
);
CREATE TYPE Application_tab IS TABLE OF Application_typ;
And now I create an object type called Job_typ, and a table containing those objects, wherein there is a nested table for applications :
CREATE OR REPLACE TYPE Job_typ AS OBJECT (
job_ID NUMBER,
description NVARCHAR2(1000),
name NVARCHAR2(200),
application Application_tab
);
CREATE TABLE Job_tab OF Job_typ
NESTED TABLE application STORE AS application_nt;
All of this works fine. I inserted some jobs into the job_tab table as follows :
INSERT INTO job_tab VALUES (1, 'The Software Developer will be responsible for authoring high-quality software...',
'Software Developer', NULL);
INSERT INTO job_tab VALUES (2, 'This position requires a team player and a self-starter with experience leading... ',
'Project Manager', NULL);
INSERT INTO job_tab VALUES (3, 'In the first year of this unique 24-month program, you rotate through various...',
'Store Manager', NULL);
Note that at this point the nested table attribute 'application' has NULL value for all jobs. Assume that I already have some applicants in a table called applicant_table, which are of type applicant_typ. How do I create and insert a new application for a job?
I tried some things like :
UPDATE job_tab
SET application = application_typ (
1,
Applicant_typ(SELECT VALUE(a) from applicant_table a where user_id=1),
'12-MAY-2014')
WHERE job_id=1
But this doesn't work.
Consider something like this
merge into job_tab D
using (select t.a app_typ from applicant_table t where t.a.user_id = 1) S
on (job_id = 1)
when matched then
update
set application = Application_tab(Application_typ(1,
s.app_typ,
to_date('12-05-2014', 'DD-MM-YYYY')));
Also I will suggest to use some other naming convention, very complicated to understand at first glance.

what is the difference between nested table and object type in oracle?

I have following object tables in oracle DB.
create type deposit_ty as object
(
depno number(6),
depcategory ref depcategory_ty,
amount number(6),
period number(2)
);
create type deposit_ntty as table of deposit_ty;
create type address_ty as object
(
homeno number,
street varchar(30),
city varchar(30)
);
create type customer_ty as object
(
cusid char(4),
custname varchar(40),
address address_ty,
dob DATE,
deposits deposit_ntty
);
can any one tell what is the difference between column address and deposits in customer_ty object table?
An object type/abstract data type/record is like a row or tuple: it contains an ordered set of attributes. To populate address you must set one and only one value for each of homeno, street, and city.
A nested table is like a table: it contains an unordered set of rows. Usually a nested table only contains a set of simple values, like a number. In your example, it is a set of object types. To populate deposits you can create any number of deposit_ty.
For example:
declare
customer customer_ty :=
customer_ty(
'ABC',
'Name',
address_ty('123', 'fake street', 'Springfield'),
sysdate,
deposit_ntty(
deposit_ty(1, null, 100, 1),
deposit_ty(2, null, 200, 2)
)
);
begin
null;
end;
Also, you probably want to use a VARCHAR2 instead of VARCHAR or CHAR. And if it's not too late, throw out all this object stuff and use tables like everyone else.

Using objects to insert variable array into nested table

I have a series of tables and objects I have defined. I have an object nested table that I am trying to insert values into. The values are in the form of a variable array but I don't know how to insert them. my tables and code are as follows.
Table wu.classes
crn number(5)
department varchar2(8)
title carchar2(25)
Table wu.students
student_id char(11)
name varchar2(10)
dept varchar2(8)
advisor varchar(10)
classes wu.classes_va
wu.classes_va varray(5) of number (5)
create type classes_ty as object(crn varchar2(5),department varchar2(8), coursetitle varchar2(25)
create table classes_ot of classes_ty;
insert into classes_ot select crn,department,title from wu.classes;
create or replace type classes_ref_ty as table of ref classes_ty;
create table student_plus(student# varchar2(11),student_name varchar2(10),major varchar2(8), advisor (10), enrolled classes_ref_ty) nested table enrolled store as classes_ref_ty_tab;
Problem here (I need to loop through to fill the table but I just need to know how to do it for one values and i can figure the rest out):
begin
insert into student_plus values('700-123-948','Hooker','CS','VanScoy',classes_ref_ty();
insert into table(select enrolled from student_plus where student#='700-123-948')
select ref(c) from classes_ot c where ???
end;
/
I don't know how to access the variable array and use it with the classes_ref_ty.

Where does oracle store my object instances?

I've created the following two object types :
create or replace type person_typ as object (
person# varchar(10)
) not final;
create or replace type salesperson_typ under person_typ (
salesperson# varchar(10),
sSurname varchar(10),
sForename varchar(10),
dateOfBirth date
);
create table person_tab of person_typ (
person# primary key
);
And I've inserted a row using :
insert into person_tab
values (salesperson_typ('p1','s1', 'Jones', 'John', sysdate));
Which I can retrieve using the following :
select
treat(value(s) as salesperson_typ).person# as person_number,
treat(value(s) as salesperson_typ).sSurname as sSurname
from
person_tab s
;
However, if I look at person_tab I only see the following :
SQL> select * from person_tab;
PERSON#
----------
p1
I'm curious, where does the salesperson specific data get stored? I was almost expecting to find a salesperson table, but I can't find anything obvious.
Your object is stored invisibly in the same table.
You can check columns by querying USER_TAB_COLS:
SELECT *
FROM user_tab_cols
WHERE table_name = 'PERSON_TAB';
Then you can then use the column names* you just discovered in a query (except SYS_NC_ROWINFO$, that throws an error for me).
SELECT SYS_NC_OID$
,SYS_NC_TYPEID$
--,SYS_NC_ROWINFO$
,PERSON#
,SYS_NC00005$
,SYS_NC00006$
,SYS_NC00007$
,SYS_NC00008$
FROM PERSON_TAB;
Note*
You should not use these column names in any application because they are internal and subject to change in future patches/releases.

Resources