You are on page 1of 14

User Defined TEMPORARY datatypes:

a)PLSQL Record
b)Index-by-table / Associate Array / PLSQL Table
User defined permanent DataTypes:

PLSQL Collections

a)Objects
b)VARRAY

Schema level

c)NESTED TABLE
PLSQL Collections:
a)Index-by-Table / Associate Array / PLSQL Table
b)Varray
c)Nested Table

PLSQL RECORD
We can declare a record in three ways:
1)Table-based Record
one_book

books%ROWTYPE;

2)Cursor-based Record
CURSOR my_books_cur IS
SELECT * FROM books
WHERE author LIKE '%FEUERSTEIN%';
one_SF_book my_books_cur%ROWTYPE;
3)Programmer-defined Record
TYPE book_info_rt IS RECORD (
books.author%TYPE,
category VARCHAR2(100),
total_page_count POSITIVE);
steven_as_author book_info_rt;
steven_as_author book_info_rt;
This is an user defined temporary data type which is used to represent different datatypes as a single unit.It
is same as structures in C language. This is an user defined type so we are creating two steps process.

Syntax:
Step 1: Type <typename> is Record (attribute1 datatype(size),attr2 datatype(size),.);
Step 2:variable_name <typename>;
Example:
Step 1: type t1 is record (a1 number(10),a2 number(10),a3 number(10));
Step 2: tvar t1;

Programs:
DECLARE
TYPE erec IS RECORD (veno NUMBER(4) not null:=7369,
vname emp.ename%TYPE,
vsal emp.sal%TYPE );
e erec;
BEGIN
select empno,ename,sal into
e
from emp
where empno=e.veno;
display(e.veno||' '||e.vname||' '||e.vsal);
END;
DECLARE
TYPE erec IS RECORD (veno NUMBER(4),
vname emp.ename%TYPE,
basic emp.sal%TYPE,
i dept%ROWTYPE,
vgross number(16,2));
e erec;
BEGIN
e.veno:=&employe;
select ename,sal,dept.deptno,dname into
e.vname,e.basic,e.i.deptno,e.i.dname
from emp,dept
where emp.deptno=dept.deptno and empno=e.veno;
e.vgross:=e.basic+e.basic*.25+e.basic*.35-e.basic*.12;
display(e.veno||' '||e.basic||' '||e.i.deptno||' '||e.i.dname||' '||e.vgross);
END;
DECLARE
TYPE erec IS RECORD (veno NUMBER(4) not null:=7369,

vname emp.ename%TYPE,
basic emp.sal%TYPE,
comm Emp.comm%type default 100,
i dept%ROWTYPE,
vgross number(16,2));
e erec;
BEGIN
select ename,sal,comm,dept.deptno,dname into
e.vname,e.basic,e.comm,e.i.deptno,e.i.dname
from emp,dept
where emp.deptno=dept.deptno and empno=e.veno;
e.vgross:=e.basic+e.basic*.25+e.basic*.35-e.basic*.12;
display(e.veno||' '||e.basic||' '||e.comm||' '||e.i.deptno||' '||e.i.dname||' '||e.vgross);
END;
DECLARE
TYPE erec IS RECORD (veno NUMBER(4) not null:=7369,
vname emp.ename%TYPE,
basic emp.sal%TYPE,
comm Emp.comm%type default 100,
i dept%ROWTYPE,
vgross number(16,2));
TYPE rec is RECORD (e erec);
v rec;
BEGIN
select ename,sal,comm,dept.deptno,dname into
v.e.vname,v.e.basic,v.e.comm,v.e.i.deptno,v.e.i.dname
from emp,dept
where emp.deptno=dept.deptno and empno=v.e.veno;
v.e.vgross:=v.e.basic+v.e.basic*.25+v.e.basic*.35-v.e.basic*.12;
display(v.e.veno||' '||v.e.basic||' '||v.e.comm||' '||v.e.i.deptno||' '||v.e.i.dname||' '||v.e.vgross);
END;
/* Record inside Record */
declare
type t1 is record(v1 number:=10);
v_t1 t1;
type t2 is record(v2 t1:=v_t1);
v_t2 t2;
begin
display(v_t1.v1||' '||v_t2.v2.v1);

end;
declare
type t is record(veno emp.empno%type,
vname emp.ename%type,
vjob emp.job%type,
vmgr emp.mgr%type,
vdate emp.hiredate%type,
vsal emp.sal%type,
vcomm emp.comm%type,
vdeno emp.deptno%type);
v_t t;
begin
select * into v_t from emp where empno=7369;
display(v_t.vname);
end;
declare
type t is record(e emp%rowtype);
v_t t;
begin
select * into v_t.e from emp where empno=7369;
display(v_t.e.ename);
end;

Collections
A collection is a data structure that acts like a list or a single-dimensional array.
Types of Collections:
a)Associate Arrays / Index-by-table / PLSQL table: (Non-Persistence / Temporary)
These are single-dimensional, unbounded, sparse collections of homogeneous elements that are available
only in PL/SQL. No constructor - you must assign values explicitly.
Syntax:
TYPE <typename> IS TABLE OF datatype [NOT NULL] INDEX BY string/integer;
Var_name <typename>;

INDEX BY clause
INDEX BY PLS_INTEGER
INDEX BY SIMPLE_INTEGER
INDEX BY NATURAL
INDEX BY POSITIVE
INDEX BY SIGNTYPE
INDEX BY VARCHAR2(N)

Minimum value
231
231
0
1
-1
Any string within
specified length

Maximum value
231 1
231 1
231 1
231 1
1
Any string within
specified length

b)Nested Tables: (Persistence / Permanent)


These are also single-dimensional, unbounded collections of homogeneous elements.They are initially
dense but can become sparse through deletions. Nested tables can be defined in both PL/SQL and the database (for
example, as a columnin a table). Nested tables are multisets, which means that there is no inherent order to the
elements in a nested table.
By using constructor we can initialize the values in collection at declarative section which is not possible in
associate arrays;
Syntax:
TYPE type_name IS TABLE OF element_datatype [ NOT NULL ];
Var_name type_name:=type_name();
c)Varray: (Persistence / Permanent)
Like the other two collection types, VARRAYs (variable-sized arrays) are also single-dimensional
collections of homogeneous elements. However, they are always bounded and never sparse. When you define a type
of VARRAY, you must also specify the maximum number of elements it can contain. Like nested tables, they can be
used in PL/SQL and in the database. Unlike nested tables, when you store and retrieve a VARRAY, its element order
is preserved.
Syntax:
TYPE type_name IS VARRAY (max_elements) OF element_datatype [ NOT NULL ];
Var_name type_name:=type_name();

Associate Arrays Programs:


DECLARE
TYPE name IS TABLE OF
VARCHAR2(50) INDEX BY BINARY_INTEGER;
n name;
l binary_integer;
BEGIN
n(0):='Siva';
n(1):='Rama';
n(-2):='Krishna';
l:=n.first;
while(l is not null)
loop
display(n(l));
l:=n.next(l);
end loop;
end;
declare
type t is table of emp%rowtype index by pls_integer;
v_t t;
cursor c is select *from emp;
ct pls_integer:=1;
begin
open c;

loop
fetch c into v_t(ct);
exit when c%notfound;
display(v_t(ct).ename||'
'||v_t(ct).job||'
'||v_t(ct).sal);
ct:=ct+1;
end loop;
end;
DECLARE
TYPE list IS TABLE OF varchar2(20) INDEX BY varchar2(20);
family list;
l_row varchar2(20);
BEGIN
family (2020202020) := 'Eli';
family (-15070) := 'Steven';
family (-90900) := 'Chris';
family ('a') := 'Veva';
l_row := family.FIRST;
WHILE (l_row IS NOT NULL)
LOOP
DBMS_OUTPUT.put_line (family (l_row));
l_row := family.NEXT (l_row);
END LOOP;
END;
/* Associate arrays inside the record type */
declare
type t is table of emp.ename%type index by pls_integer;
type rec is record(v_t t);
vrec rec;
ct pls_integer:=1;
cursor c is select ename from emp;
begin
open c;
loop
fetch c into vrec.v_t(ct);
exit when c%notfound;
display(vrec.v_t(ct));
ct:=ct+1;
end loop;
end;
/*Ref cursor and Associate array with record type */
declare
type t is table of emp%rowtype index by pls_integer;
r sys_refcursor;
type rec is record(v_t t);
vrec rec;
ct pls_integer:=1;
begin
open r for select *from emp where deptno=10;
loop
fetch r into vrec.v_t(ct);
exit when r%notfound;
display(vrec.v_t(ct).ename);
ct:=ct+1;

end loop;
end;
/*Ref cursor and Associate array with record type */
declare
type t is table of emp%rowtype index by pls_integer;
r sys_refcursor;
type rec is record(v_t t);
vrec rec;
ct pls_integer:=1;
begin
open r for select *from emp where deptno=10;
loop
fetch r into vrec.v_t(ct);
exit when r%notfound;
display(vrec.v_t(ct).ename);
ct:=ct+1;
end loop;
display('------------------');
open r for select *from emp where deptno=20;
loop
fetch r into vrec.v_t(ct);
exit when r%notfound;
display(vrec.v_t(ct).ename);
ct:=ct+1;
end loop;
end;

/*all methods in Associate Arrays*/


DECLARE
TYPE list IS TABLE OF varchar2(20) INDEX BY pls_integer;
c list;
l_row varchar2(20);
BEGIN
display(c.count);--0
c(1) := 'a';
c(2) := 'b';
c(3) := 'c';
c(6) := 'd';
l_row := c.FIRST;
WHILE (l_row IS NOT NULL)
LOOP
DBMS_OUTPUT.put_line (c(l_row));
l_row := c.NEXT (l_row);
END LOOP;
display(c.count);
--4
display(c.first);
--1
display(c.next(2));
--3
display(c.last);
--6
if c.exists(2) then
display('e');
else
display('ne');
end if;
display(c.prior(2));
--1

--c.extend(3);
display(c.limit);
--display(c.trim);
c.delete(4,6);
display(c.count);
c.delete;
display(c.count);
END;

--extend method not supports.


--limitless so null
-- trim method not supports.
--delete elements including and in between 4 and 6
--all the elements are deleted

Nested Table Programs:


declare
type nes is table of emp.ename%type;
vnes nes:=nes();
--Here nes() is called constuctor
n number:=1;
begin
for i in (select * from emp)
loop
vnes.extend;
--It is mandatory to enter values into collections
vnes(n):=i.ename;
display(vnes(n));
n:=n+1;
end loop;
end;
declare
type nes is table of emp.ename%type;
vnes nes:=nes();
begin
for i in (select * from emp)
loop
vnes.extend;
vnes(vnes.count):=i.ename;
display(vnes.count||')'||vnes(vnes.count));
end loop;
end;
declare
type nes is table of emp.ename%type;
vnes nes:=nes();
cursor c is select ename from emp;
begin
open c;
loop
vnes.extend;
fetch c into vnes(vnes.count);
exit when c%notfound;
display(vnes(vnes.count));
end loop;
vnes.delete;
for i in (select * from emp)
loop
vnes.extend;
vnes(vnes.count):=i.ename;
display(vnes.count||')'||vnes(vnes.count));
end loop;
end;

/*all the collections methods in nested table*/


declare
type nes is table of varchar2(10);
vnes nes:=nes('a','b','c','d');
begin
display(vnes.count);
display(vnes.first);
display(vnes.next(1));
display(vnes.prior(2));
display(vnes.last);
display(vnes.limit);
vnes.extend;
display(vnes.count);
vnes.extend(2);
display(vnes.count);
for i in vnes.first..vnes.last loop
display('vnes values
end loop;
vnes.extend(2,3);
display('----------------------');
for i in vnes.first..vnes.last loop
display('vnes values
end loop;
vnes(5):='e';
vnes(6):='f';
vnes(7):='g';
display('----------------------');
for i in vnes.first..vnes.last loop
display('vnes values
end loop;
vnes.trim;
display('----------------------');
for i in vnes.first..vnes.last loop
display('vnes values
end loop;
vnes.trim(2);
display('----------------------');
for i in vnes.first..vnes.last loop
display('vnes values
end loop;
vnes.delete(1);
display('----------------------');
for i in vnes.first..vnes.last loop
display('vnes values
end loop;
vnes.delete(4,6);
display('----------------------');
for i in vnes.first..vnes.last loop
display('vnes values
end loop;
vnes.delete;
display(vnes.count);
end;

--4
--1
--2
--1
--4
--limit less so null
--5
--7
'||i||':'||vnes(i));
--extend two values and assign 3rd value
'||i||':'||vnes(i));

'||i||':'||vnes(i));
--will delete last value
'||i||':'||vnes(i));
-- will delete last two values
'||i||':'||vnes(i));
--will delete first key-value pair(specific deletion is possible)
'||i||':'||vnes(i));
-- will delete key-value pair b/w and including 4 and 6
'||i||':'||vnes(i));
--will delete all the elements

/*Nested table type inside plsql record type*/


declare
type nes is table of emp.ename%type;
type rec is record(vnes nes:=nes());
vrec rec;
begin
for i in (select *from emp)
loop
vrec.vnes.extend();
vrec.vnes(vrec.vnes.count):=i.ename;
display(vrec.vnes(vrec.vnes.count));
end loop;
end;

Varray Programs:
declare
type arr is varray(20) of emp.ename%type;
varr arr:=arr();
begin
for i in (select *from emp)
loop
varr.extend;
varr(varr.count):=i.ename;
display(varr(varr.count));
end loop;
end;
/*all collection methods in varrrays*/
declare
type arr is varray(20) of emp.ename%type;
varr arr:=arr('a','b','c','d');
begin
display('----------------------');
for i in varr.first .. varr.last
loop
display('varray values
end loop;
display('----------------------');
display('count
:'||varr.count);
display('first
:'||varr.first);
display('next
:'||varr.next(2));
display('prior
:'||varr.prior(3));
display('limit
:'||varr.limit);
display('last
:'||varr.last);
varr.extend;
display('count
:'||varr.count);
display('----------------------');
for i in varr.first .. varr.last
loop
display('varray values
end loop;
varr.extend(2,4);

'||i||':'||varr(i));
--4
--1
--3
--2
--20 it has limit
--4
--5

'||i||':'||varr(i));

10

display('----------------------');
for i in varr.first .. varr.last
loop
display('varray values
end loop;
display('count
:'||varr.count);
display('----------------------');
if varr.exists(5) then
display('exists');
else
display('not exists');
end if;
varr.extend;
varr.trim;
display('----------------------');
for i in varr.first .. varr.last
loop
display('varray values
end loop;
varr.trim(2);
display('----------------------');
for i in varr.first .. varr.last
loop
display('varray values
end loop;
--varr.delete(n);
varr.delete;
display('count
:'||varr.count);

'||i||':'||varr(i));
--7

--will delete last one element

'||i||':'||varr(i));
--will delete last two elements

'||i||':'||varr(i));
--specific deletion is not possible

end;
/*varray in record type*/
declare
type arr is varray(20) of emp.ename%type;
type rec is record(varr arr:=arr());
vrec rec;
begin
for i in (select *from emp)
loop
vrec.varr.extend;
vrec.varr(vrec.varr.count):=i.ename;
display(vrec.varr(vrec.varr.count));
end loop;
end;

Differences Between Collection types:


First , Last , Count ,
Next(n)
Limit
Prior(n),exists(n)
Delete
Delete(n)

PLSQL TABLE
Yes

NESTED TABLE
Yes

VARRAY
Yes

Limit less
Yes
Yes
Yes

Limit less
Yes
Yes
Yes

Limit
Yes
Yes
Specific deletion is not
possible

11

Delete(n,m)

Yes

Yes

Not possible

Extend , Extend(n,i)

No

Yes

Possible up to limit

Trim , Trim(n)

no

yes

yes

Dimensionality

Single

Single

Single

Usable in SQL?

No

Yes

Yes

Initialization

Automatic, when declared

Sparse?

Yes

Via constructor, fetch,


assignment
No

Bounded?

No

Via constructor, fetch,


assignment
Initially, no; after
deletions,yes
Can be extended

Can be compared for


Equality?
Usable as column datatype
In a table?
Can be manipulated with
Set operators
Persistence

No

Yes, Oracle Database 10g


and later
Yes; data stored out of
line (in separate table)
Yes, Oracle Database 10g
and Later
Yes (Permanent in schema
level)

No

No
No
No (Temporary)

Yes

Yes; data stored in line


(in Same table)
No
Yes (Permanent in schema
level)

MULTISET in Nested Tables:


MULTISET operator gets a nested table whose elements are set to certain elements of two nested tables that
are input to MULTISET. There are three MULTISET operators:
MULTISET UNION Returns a nested table whose elements are set to the elements of the two input nested
tables.
MULTISET INTERSECT Returns a nested table whose elements are set to the elements that are common
to the two input nested tables.
MULTISET EXCEPT Returns a nested table whose elements are in the first input nested table but not in the
second.
You may also use one of the following options with MULTISET:
ALL Indicates that all applicable elements in the input nested tables are set in the returned nested table.
ALL is the default.

12

DISTINCT Indicates that only the distinct non-duplicate elements in the input nested tables are set in the
returned nested table.
declare
TYPE nestedTableType IS TABLE OF VARCHAR2(10);
myTable1 nestedTableType;
myTable2 nestedTableType;
myTable3 nestedTableType;
count_var INTEGER;
BEGIN
myTable1 := nestedTableType('F', 'G', 'S');
myTable2 := nestedTableType('G', 'S', 'R');
myTable3 := myTable1 MULTISET UNION myTable2;
DBMS_OUTPUT.PUT('UNION: ');
FOR count_var IN 1..myTable3.COUNT LOOP
DBMS_OUTPUT.PUT(myTable3(count_var) || ' ');
END LOOP;
DBMS_OUTPUT.PUT_LINE(' ');
myTable3 := myTable1 MULTISET UNION DISTINCT myTable2;
DBMS_OUTPUT.PUT('UNION DISTINCT: ');
FOR count_var IN 1..myTable3.COUNT LOOP
DBMS_OUTPUT.PUT(myTable3(count_var) || ' ');
END LOOP;
DBMS_OUTPUT.PUT_LINE(' ');
myTable3 := myTable1 MULTISET INTERSECT myTable2;

13

DBMS_OUTPUT.PUT('INTERSECT: ');
FOR count_var IN 1..myTable3.COUNT LOOP
DBMS_OUTPUT.PUT(myTable3(count_var) || ' ');
END LOOP;
DBMS_OUTPUT.PUT_LINE(' ');
myTable3 := myTable1 MULTISET EXCEPT myTable2;
DBMS_OUTPUT.PUT_LINE('EXCEPT: ');
FOR count_var IN 1..myTable3.COUNT LOOP
DBMS_OUTPUT.PUT(myTable3(count_var) || ' ');
END LOOP;
end;

14

You might also like