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
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))
);
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.
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.
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.
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.