0% found this document useful (0 votes)
396 views142 pages

PLSQL

PL/SQL is a procedural language that allows developers to perform operations like control flow statements, define functions and procedures, and handle exceptions. It supports data types like records, objects, and collections. Key elements include blocks, control statements, cursors, exceptions, stored procedures, functions, packages, and triggers. PL/SQL code can be executed using SQL*Plus by setting serveroutput on and running a script containing PL/SQL code.

Uploaded by

Cutenag India
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
396 views142 pages

PLSQL

PL/SQL is a procedural language that allows developers to perform operations like control flow statements, define functions and procedures, and handle exceptions. It supports data types like records, objects, and collections. Key elements include blocks, control statements, cursors, exceptions, stored procedures, functions, packages, and triggers. PL/SQL code can be executed using SQL*Plus by setting serveroutput on and running a script containing PL/SQL code.

Uploaded by

Cutenag India
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 142

PL/Sql

This is procedure Language or Programming Language.


This is consists of units of blocks.
Makes application design easy.
Provides security and portability
It is used to handle the multiple statements
To define our own logic we use plsql
It supports the control statements like If conditions,
loops ...and soon
Explicitly define our own cursors in plsql and it allows the
Boolean data types also.

TOPICS::
1) Introduction
2) Composite Data types
a) %Type
b) %Row Type
c) Record Type/ Plsql Record
d) Index By table or Plsql table or associative array
e) Objects
f) Varrays
g) Nested tables/ table
(e,f,g are oops concepts)
3) Blocks
a) Named Blocks
b) Unnamed Blocks
c) Nested Blocks

4) Control Statements::
a) Sequential (Default)
b) Conditional Stmts (If, Case)
5) Cursors ::
a) Implicit Cursor
b) Explicit Cursor
6) Exceptions (Run Time Errors)
1) Predefined
2) User Defined

7) Stored procedures
a) Functions
b) Procedure
c) Triggers
d) Packages

3) Blocks::
a) Unnamed Blocks::
Syntax::
DECLARE

Optional
BEGIN
Code(Mandatory)
EXCEPTION;
Optional(Exceptionsection)
END;

Declarative Section::
We use declarative section to define the variables,
Constants, Cursors, Exceptions.. and soon.
We have to define the things in declarative section which
are not understood by plsql engine.
Which is optional
Executable section::
Here we have to define or provide the code
Execution takes place in executable section, which is
mandatory
It starts from begin to end
Exception section::
We use exception section to handle the runtime errors and
which is optional.

NESTED BLOCKS::
Block within the another block is called as Nested Block
Ex::
DECLARE

BEGIN
declare

begin

exception;

end;
EXCEPTION;

END;

BEGIN
BEGIN
END;
END;

EX:: Write a program to display the message on the screen?


begin

dbms_output.put_line('hello...........');
end;

O/p::hello...........

If you want to run the same in sql plus we will use the below
steps

NOTE:: Please write the below syntax to get the output on


sqlplus.
Set serveroutput on;
We have two steps here to execute the code
Step1:: Copy the code and paste at sql prompt

STEP2:: save the text pad as sql and copy the path of text pad(By
using f3) and paste on the sqlplus.

Click on f3 on textpad you will get below screen

Copy the path and paste the path after @ symbol in sqlplus.

Using Null as Statements::


BEGIN

outputwillnotcomewithoutusinganystatemtsanditwillnotexecute
END;

BEGIN

null;

Wecanusenullalsointhecodesection
END;

2) Using Constant::
block

We don't change the modifications in entire

Ex::
Declare
aconstantnumber(5,3):=3.14;
bnumber(5):=100;
Begin
b:=50;
dbms_output.put_line(a+b);

End;

O/P::53.14

Note:: If we use in place of b:=50 to a:=50 we will get an error


message that
PLS00363:expression'A'cannotbeusedasanassignmenttarget

Changing the output automatically::


Declare
anumber(5):=&a;

bnumber(5):=&b;
Begin

dbms_output.put_line(a+b);
End;

Comments:: By using the comments we can explain the


functionality of the source code in program but these statements
will be ignore by the oracle complier.
Single line comment:: -Multiline comment:: /* Multi Line Comment*/

Composite Data types::


a) %Type:: It is used to provide column data type to a variable so
no need to remember the data type of column. This is nature is
called as dynamic.
Syntax:: Variable_name table_name.column_name%type;
Ex:: V_ename emp.ename%type;
Ex:: Write a program to display the employee name by providing
the employee number?
DECLARE
v_enameVARCHAR2(100);
v_empnoNUMBER(10):=&empno;
BEGIN
SELECTename
INTOv_ename
FROMemp
WHEREempno=v_empno;
DBMS_OUTPUT.put_line(v_ename);
END;
I/P::7654
O/P::MARTIN

NOTE:: If we want display the output with proper message we


will us the below line
DBMS_OUTPUT.put_line('EmployeeNameis::'||v_ename);

O/P::

Employee Name is ::MARTIN

NOTE2:: If we declare the variable below like we will get an error


message
v_enamenumber(10);

ORA06502:PL/SQL:numericorvalueerror:charactertonumberconversion
error

This is the reason we will use the composite data types like
(%type, %rowtypes)
Ex:: By using composite data type
DECLARE
v_enameEMP.ENAME%type;
v_empnoemp.empno%type:=&empno;
BEGIN
SELECTename
INTOv_ename
FROMemp
WHEREempno=v_empno;
DBMS_OUTPUT.put_line('EmployeeNameis::'||v_ename);
END;
I/p::7654
EmployeeNameis::MARTIN

NOTE3:: Disadvantage of this is not possible to store the entire


record.
a) %RowType:: It assign the entire columns data types of a
table, and it is useful to store the total record.
Syntax:: variable_name table_name%rowtype;
Ex:: v_ename emp%rowtype
Ex::
DECLARE
v_empnoemp.empno%TYPE:=&v_empno;
v_rowemp%ROWTYPE;
BEGIN
SELECTename,job,sal
INTOv_row.ename,v_row.job,v_row.sal
FROMemp
WHEREempno=v_empno;
DBMS_OUTPUT.put_line(v_row.ename||','||v_row.job||','||
v_row.sal);
END;

I/P::7654
O/P::MARTIN , SALESMAN , 1250

NOTE:: By using %rowtype, It is not possible to store table record


along with user data (or) user information.
If we declare below like we will get an error message.
v_empnoemp%rowTYPE:=&v_empno;
PLS00320:thedeclarationofthetypeofthisexpressionisincomplete
ormalformed

CNTORL STATEMENTS::
a) Conditional Controls
b) Iterations
a) Conditional Control Flow:: If statements, Case statements.
1) IF::
Syntax::
IF condition THEN
exce stmts...
elsif condtion then
exce stmts..
else
exce stmts...
end if ;

Ex::
DECLARE
v_salNUMBER(10):=&v_num;
BEGIN
IFv_sal>1000
THEN
DBMS_OUTPUT.put_line('Givensalaryis::'
||v_sal
||'anditismorethan1000'
);
ENDIF;
END;

I/P::2000
O/P::Given salary is::2000 and it is more than 1000

2) NESTED IF ::
Syntax::

IF CONDTION THEN
IF condtion then
Seq of stmts;
END IF;
END IF;
Ex::

DECLARE
v_salNUMBER(10):=#
BEGIN
IFv_sal>1000
THEN
DBMS_OUTPUT.put_line('Salaryisgraterthan1000');
IFv_sal>1500
THEN
DBMS_OUTPUT.put_line('Salaryisgraterthan1500');
ENDIF;
ENDIF;
END;
I/P::3000
O/P::
Salaryisgraterthan1000
Salaryisgraterthan1500

3) CASE:: Case two types

1) Simple Case 2) Search Case


Syntax::

Search Case

CASE[Columns/Expressions]
WHENconditionTHEN

execseqofstmts;
whencondtionthen

execseqofstmts;
whencondtionthen

execseqofstmts;
else

execseqofstmts;
ENDCASE;

2) Search Case (Sql Example)::

SELECTsal,CASE
WHENsal=5000
THEN'A'
WHENsal>3000
THEN'B'
ELSE'C'
ENDCASE
FROMemp
ORDERBYsalDESC

SAL
5000
3000
3000
2975
2850
2450
1600
1500
1300
1250
1250
1100
950
800

CAS
E
A
B
B
C
C
C
C
C
C
C
C
C
C
C

3) Plsql example

declare

v_empnoemp.empno%type:=&v_num;
v_salEMP.SAL%TYPE;
begin
selectsalintov_sal
fromemp
whereempno=v_empno;

case

whenv_sal=5000then
dbms_output.put_line('Givenemployeenumbersalis::'||
v_sal);
whenv_sal>=3000then
dbms_output.put_line('Givenemployeenumbersalis::'||
v_sal);
ELSE
dbms_output.put_line('Givenemployeenumbersalis::'||
v_sal);
endcase;
end;
I/P::7654
O/P::Givenemployeenumbersalis::1250

NOTE:: In the absence of else part if all the conditions are false
then it will thrown on an error.(ORA06592:CASEnotfoundwhile
executingCASEstatement)
Ex::
declare
v_empnoemp.empno%type:=&v_num;
v_salEMP.SAL%TYPE;
begin
selectsalintov_sal
fromemp
whereempno=v_empno;

case

whenv_sal=5000then
dbms_output.put_line('Givenemployeenumbersalis::'||
v_sal);
whenv_sal>=3000then
dbms_output.put_line('Givenemployeenumbersalis::'||
v_sal);
ELSE
dbms_output.put_line('Givenemployeenumbersal
is::'||v_sal);

endcase;
end;
O/P::
ORA06592:CASEnotfoundwhileexecutingCASEstatement

1) Simple Case:: It is not allow the special operators


Ex::
DECLARE
v_salemp.sal%TYPE;
v_empnoemp.empno%TYPE:=&v_emno;
BEGIN
SELECTsal
INTOv_sal
FROMemp
WHEREempno=v_empno;
CASEv_sal
WHEN5000
THEN
DBMS_OUTPUT.put_line('sal=5000');
WHEN3000
THEN
DBMS_OUTPUT.put_line('sal=3000');
ELSE
DBMS_OUTPUT.put_line('sal='||v_sal);
ENDCASE;
END;

I/P::7839
O/P::sal=5000
I/P::7654
O/P::sal=1250

b) Iterations:: To execute the same statement or coding for


repeated times us use loops
1) Simple loop
2) While loop
3) For loop
a) Numeric for loop
b) Cursor for loop
1) Simple loop:: it is an infinity loop, explicitly we have to
stop the loop by using EXIT key word/EXIT WHEN. And it is
uses in blocks.
Syntax::
LOOP
Seq of statements..
END LOOP;

Ex::
declare
v_nonumber(10):=0;
begin
Loop
dbms_output.put_line(v_no);
v_no:=v_no+1;
ifv_no>=10then

exit;

endif;

endloop;

end;
O/P::
0
1
2
3
4
5
6
7
8
9
Ex2::
DECLARE
xnumber:=10;
BEGIN
LOOP
dbms_output.put_line(x);
x:=x+10;
exitWHENx>50;
ENDLOOP;
afterexit,controlresumeshere
dbms_output.put_line('AfterExitxis:'||x);
END;
/

AfterExitxis:60

2) While loop:: It is a pre tested loop. A while loop statement in


PL/SQL repeatedly execute a target statement as long as
given condition is true.
Syntax::
WHILEconditionLOOP
sequence_of_statements
ENDLOOP;

FOR loop_counter IN [REVERSE]


lowest_number..highest_number
LOOP
{...statements...}
END LOOP;

GOTO:: The GOTO statement transfers control to a labeled block or


statement.

Restrictions on GOTO Statement

A GOTO statement cannot transfer control into


an IF statement, CASE statement, LOOP statement, or sub-block.

A GOTO statement cannot transfer control from one IF statement


clause to another, or from one CASE statement WHENclause to another.

A GOTO statement cannot transfer control out of a subprogram.

A GOTO statement cannot transfer control into an exception handler.

A GOTO statement cannot transfer control from an exception handler


back into the current block (but it can transfer control from an
exception handler into an enclosing block)
SYNTAX::
GOTO label ;

Ex::
CREATE OR REPLACE Function FindCourse
( name_in IN varchar2 )

RETURN number
IS
cnumber number;

CURSOR c1
IS
SELECT MAX(course_number)
FROM courses_tbl
WHERE course_name = name_in;

BEGIN

open c1;
fetch c1 into cnumber;

IF c1%notfound then
GOTO default_number;

ELSE
GOTO increment_number;
END IF;

<<default_number>>

cnumber := 0;

<<increment_number>>
cnumber := cnumber + 1;

close c1;

RETURN cnumber;

END;

CURSORS
In Order to process the sql statements, oracle will allocate
an area of memory is called as CONTEAXT AREA/ CURSOR/
VIRTUAL TABLE in Pl/Sql.
Plsql uses this context area to store and execute the sql
statements.
The information/rows retrieved from data base table, which
is available in the context area, is know as ACTIVE SET
A cursor is a pointer which works on the Active set, i.e which
points one row at a time in the context area.
A cursor is used to process the multiple rows using Pl/Sql.
A cursor is a private memory(PGA) or buffer.
It is use to hold the data from the tables (or) views in
memory location for manipulate purpose.
Cursors are validate in PlSql Blocks only.
Cursor variables, that you can define in the DECLARE section of
the PLSql block.

TYPES OF CURSORS:: There are two types of cursors.


1) Implicit Cursor 2) Explicit Cursor
1) Implicit Cursor:: It is a cursor that is automatically declared
by oracle every time when SQL stmt is executed. These are
created and erased automatically. These are identified by
SQL%<attribute Name>
Cursor attributes:: there are 4 types of cursor attributes.
1) SQL% found
2) SQL%notfound
3) SQL%ISOPEN
4) SQL%ROWCOUNT
NOTE:: First 3 will return BOOLEAN VALUES last one will return as
NUMBER

Ex:: Implicit Cursor::

NOTE:: if we execute the above query, we will get the message


like 0rows Update. Internally oracle will define the cursor so
this is the reason we will get these types of messages.
When we execute a part of block issue a sql statements, Plsql
create an implicit cursor , which is manage by plsql
automatically.
A implicit cursor is automatically with Every DML statements.
During the process of implicit cursor, Oracle automatically
performs the operations like

DECLARE, OPEN, FETECH,CLOSE of the context area.


CUROSR ATTRIBUTES:: Cursor attributes are appended to a cursor
name in plsql block. Similar to %type or %rowtype.
The attributes are %FOUND, %NOTFOUND , %ISOPEN,
%ROWCOUNT
%FOUND:: It is a Boolean attribute and it will returns true if the
most recent sql statement effects one or more rows.
%NOTFOUND:: It is a Boolean attribute and it will returns true if
the most recent sql statement does not effects one or more rows.
%ISOPEN:: It is a Boolean attribute and it will return true is the
cursor is open otherwise it will return false.
%ROWCOUNT:: It will return no of rows effected by the most
recent SQL statement(An Integer value it will return).

BIND VARIABLE:: A variable which is defined at sql prompt is


called as Bind variable. Bind variable should be defined on SQL
prompt and also we can use those variables in PLSQL.
Syntax::
var v_name datatype ;
Ex:: Write a program to know how many records are deleting through Plsql block,
by using input as empno.

Ex2::
Write a program to display the how many records are
updated for given job in emp table. And if not updated any
records please show the output as Data is not found.
DECLARE
v_jobemp.job%TYPE:='&JOB';
BEGIN
UPDATEemp
SETsal=sal+100
WHEREjob=v_job;
DBMS_OUTPUT.put_line(SQL%ROWCOUNT||'Rowsareupdated');
IFSQL%NOTFOUND
THEN
DBMS_OUTPUT.put_line('Dataisnotfoundsonoupdations..');
ENDIF;
END;
I/P::SALESMAN
O/P::4Rowsareupdated

Implicit cursor with for loop::

Ex:: Write a PlSql program to delete the employees if sal<2000


and delete the 30th dept records and deleted records should be
store in del_tab table.
Step1:: Table Creation.
CREATETABLEdel_tabASSELECTempno,ename,jobFROMempWHERE1=2

Step2::
BEGIN
FORiIN(SELECT*
FROMemp
WHEREdeptno=30)
LOOP
IFi.sal<=1500
THEN
DELETEFROMemp
WHEREempno=i.empno;
INSERTINTOdel_tab
(empno,ename,job
)
VALUES(i.empno,i.ename,i.job
);
ENDIF;
ENDLOOP;
END;

Explicit Cursor::
Explicit cursors are explicitly declare by the
programmer. This cursor is declared within the PLSQL block and it
is allows the sequential process of each row of the returned from
the database.
How this cursor will work::

The life cycle of the explicit cursor goes through 4 stages.


Declare
Open
Fetch
--(Exit)
Close
1) Declare:: The cursor statement is used to declare explicitly
in declarative section.
Syntax::
Cursor<Curosr_Name>is
Selectlistofcolumns
Fromtable_name
[wherecondition];

NOTE:: In <select statement> include most of the usual clauses ,


except INTO clause (If we use there is no use)(It will not give any
error)
Ex:: Cursor with INTO operator
DECLARE
v_salNUMBER(10):=2000;
CURSORc1
IS
SELECTsal
INTOv_sal
FROMemp
WHEREempno=7902;
BEGIN
DBMS_OUTPUT.put_line('Thevalofv_salis::'||v_sal);
END;
O/P::Thevalofv_salis::2000

OPEN:: Here query execution is done so now we can fetch the


data.
Syntax:: open <cursor name>
Ex:: open C1;
NOTE: Now the cursor will point to the first row in the active set.
FETCH:: The retrieval of data into plsql variable or host variable is
done through FETCH statement.

Syntax:: FETCH <Cursor Name> INTO <Variable>;


NOTE:: Fetch statement should write within the loop and to
terminate the loop we can use the cursor attribute.
Syntax::
Exit when <Cursor Name>%<Cursor Attribute>;
CLOSE:: It explicitly close the cursor, allowing it be reopened if it
require. Means the active set can be established several times.
Syntax:: close <Cursor Name>;
Ex:: Close C1;
Cursor Example:: Write a plsql cursor to display the empno,
ename, sal, deptno of the 20th dept.
DECLARE
CURSORcd20
IS
SELECTempno,ename,sal,deptno
FROMemp
WHEREdeptno=20;
v_empnoemp.empno%TYPE;
v_enameemp.ename%TYPE;
v_salemp.sal%TYPE;
v_deptnoemp.deptno%TYPE;
BEGIN
OPENcd20;
LOOP
FETCHcd20
INTOv_empno,v_ename,v_sal,v_deptno;
EXITWHENcd20%NOTFOUND;
DBMS_OUTPUT.put_line(v_empno
||','
||v_ename
||','
||v_sal
||','
||v_deptno
);
ENDLOOP;
CLOSEcd20;
END;
O/P::
7566,JONES,2975,20

7788,SCOTT,3000,20
7902,FORD,3000,20
7369,SMITH,800,20
7876,ADAMS,1100,20

Cursor exampl2:: To hike the commission with the following


criteria.
1)

If employee commission is null give the commission as 250

2) If employee commission as "0" give the commission as 300


3) Other than these two conditions hike the commission as 15%
and display empno, ename, comm values.
DECLARE
CURSORcur_vsing
IS
SELECTempno,ename,comm
FROMemp_1;
v_empnoemp_l.empno%TYPE;
v_enameemp_l.ename%TYPE;
v_commemp_l.comm%TYPE;
BEGIN
OPENcur_vsing;
LOOP
FETCHcur_vsing
INTOv_empno,v_ename,v_comm;
EXITWHENcur_vsing%NOTFOUND;
IFv_commISNULL
THEN
v_comm:=250;
ELSIFv_comm=0
THEN
v_comm:=300;
ELSE
v_comm:=(v_comm+(v_comm*0.15));
ENDIF;
UPDATEemp_l
SETcomm=v_comm
WHEREempno=v_empno;
DBMS_OUTPUT.put_line(v_empno||','||v_ename||','||v_comm);
ENDLOOP;
CLOSEcur_vsing;
END;

NOTE:: If we write the program blow


EXITWHENcur_vsing%NOTFOUND;
FETCHcur_vsing
INTOv_empno,v_ename,v_comm;

EXIT after FETCH we get the output


statement will execute two times"

like "Last executable

User authentication:: by using translate function


Ex::
CREATETABLEuser_tab(user_idVARCHAR2(30),pwdVARCHAR2(30))

INSERTINTOuser_tab
VALUES(UPPER('&USER_ID'),
TRANSLATE(UPPER('&PASSWORD'),
'ABSCDEFGHIJKLMNOPQRSTUVWXYZ',
'1234567890!@#$%^&*()_+=\/"'
));
select*fromuser_tab

DECLARE
CURSORuser_insert
IS
SELECT'X'
FROMuser_tab
WHEREuser_id=UPPER('&userid')
ANDpwd=
TRANSLATE(UPPER('&PASSWORD'),
'ABSCDEFGHIJKLMNOPQRSTUVWXYZ',
'1234567890!@#$%^&*()_+=\/"'
);
dummy_varCHAR;
BEGIN
OPENuser_insert;
FETCHuser_insert
INTOdummy_var;
IFuser_insert%FOUND
THEN
DBMS_OUTPUT.put_line('Theusernameanpwdiscorrect');
ELSE
DBMS_OUTPUT.put_line('Theusernameanpwdiswrong');
ENDIF;
closeuser_insert;
END;
I/P::tirupati/tirupati

O/P::Theusernameanpwdiscorrect
I/P::xxxx/xxxx
O/P::Theusernameanpwdiswrong

FOR LOOP WITH EXPLICIT CURSOR::


Syntax::
for<var>in<cursor_name>
loop
<ExecutableStmts>;
endloop;

NOTES::
--/*1) No need to define a variable for cursor*/
2) No need to open cursor explicitly
3) No need to fetch the data explicitly
4) No need to terminate the loop by using cursor attributes
5) No need to close the cursor explicitly.
Ex:: 1) Write an explicit cursor to print the empno, ename, sal,
hra, da, pf for which salary is greater than 2000.
2) Find the No of employees eligible for PF.
DECLARE
CURSORexp_cur
IS
SELECTempno,ename,salbasic,sal*0.45hra,sal*0.35da,
sal*0.15pf
FROMemp
WHEREsal>2000;
v_grossNUMBER(10);
BEGIN
FORiINexp_cur
LOOP
v_gross:=i.basic+i.hra+i.dai.pf;
DBMS_OUTPUT.put_line(i.empno
||','
||i.ename

||','
||i.basic
||','
||i.hra
||','
||i.da
||','
||i.pf
||','
||v_gross
);
ENDLOOP;
END;

O/P::
7839,KING,5000,2250,1750,750,8250
7698,BLAKE,2850,1282.5,997.5,427.5,4703
7782,CLARK,2450,1102.5,857.5,367.5,4043
7566,JONES,2975,1338.75,1041.25,446.25,4909
7788,SCOTT,3000,1350,1050,450,4950
7902,FORD,3000,1350,1050,450,4950

Ex2:: Find the No of employees eligible for PF.


DECLARE
CURSORexp_cur
IS
SELECTempno,ename,salbasic,sal*0.45hra,sal*0.35da,
sal*0.15pf
FROMemp
WHEREsal>2000;
v_grossNUMBER(10);

cntnumber:=0;

BEGIN
FORiINexp_cur
LOOP
v_gross:=i.basic+i.hra+i.dai.pf;
DBMS_OUTPUT.put_line(i.empno
||','
||i.ename
||','
||i.basic
||','
||i.hra
||','
||i.da
||','
||i.pf
||','
||v_gross

);

cnt:=cnt+1;

ENDLOOP;

dbms_output.put_line('NoofemployeeseligibleforPF::'||cnt);

END;
O/P::
7839,KING,5000,2250,1750,750,8250
7698,BLAKE,2850,1282.5,997.5,427.5,4703
7782,CLARK,2450,1102.5,857.5,367.5,4043
7566,JONES,2975,1338.75,1041.25,446.25,4909
7788,SCOTT,3000,1350,1050,450,4950
7902,FORD,3000,1350,1050,450,4950
NoofemployeeseligablefroPF::6

GROUP FUNCTIONS IN A CURSOR ::


EX:: Write a program to display the details high sal, low sal, total
sal , No of employees department wise.
DECLAREo
CURSORgrp_cur
IS
SELECTdeptno,MAX(sal)high_sal,MIN(sal)low_sal,
SUM(sal)tot_sal,COUNT(*)noe
FROMemp
GROUPBYdeptno;
BEGIN
FORiINgrp_cur
LOOP
DBMS_OUTPUT.put_line(i.deptno
||','
||i.high_sal
||','
||i.low_sal
||','
||i.tot_sal
||','
||i.noe
);
ENDLOOP;
END;
O/P::

30,2850,950,9400,6
20,3000,800,10875,5
10,5000,1300,8750,3

NOTE::
1) Alias Names can't represent in a double codes in the
cursor select statement.
2) We can't fetch the values from higher boundary to
lower boundary of records. (here reverse for loop is not possible)

ADVANCED EXPLICIT CURSOR CONCEPTS::


Cursor defined with parameter is called as parametric cursor
Cursor parameter can be assigned with default values
The mode of cursor parameters can be only "IN" mode
We have three types of parameters 1) IN 2) OUT 3) INOUT(2,3 not
possible in cursor)
Parameter is also a variable which is used to pass the value to
caller program and receive the values from calling program.
NOTE: No size for parameter variables.
Ex:: Write a PlSQl cursor to display the empno, ename , deptno
and JOB for entered deptno & Job through the parameters.
Syntax::
cursorcur_name(parameter_name[in]datatype,.,....)
is
selectlistofcolumnsfromtab_name
[wherecondition];
Ex::
DECLARE
CURSORparm_cur(p_deptnoemp.deptno%TYPE,p_jobemp.job%TYPE)
IS
SELECTempno,ename,job,deptno
FROMemp
WHEREdeptno=p_deptnoANDjob=p_job;
iparm_cur%ROWTYPE;
BEGIN
OPENparm_cur(&deptno,'&job');
LOOP
FETCHparm_cur
INTOi;

EXITWHENparm_cur%NOTFOUND;
DBMS_OUTPUT.put_line(i.empno
||','
||i.ename
||','
||i.job
||','
||i.deptno
);
ENDLOOP;
CLOSEparm_cur;
END;

I/P::ANALYST,20
7788,SCOTT,ANALYST,20
7902,FORD,ANALYST,20

Ex:: Write a PL/Sql cursor


to display the employee details
according to the deptno of the deptable.
DECLARE
CURSORdept_cur
IS
SELECTdeptno
FROMdept;
CURSORemp_cur(p_deptnoINdept.deptno%TYPE)
IS
SELECTempno,ename,sal,job,deptno
FROMemp
WHEREdeptno=p_deptno;
v_deptnodept.deptno%TYPE;
iemp_cur%ROWTYPE;
BEGIN
OPENdept_cur;
LOOP
FETCHdept_cur
INTOv_deptno;
EXITWHENdept_cur%NOTFOUND;
OPENemp_cur(v_deptno);
LOOP
FETCHemp_cur
INTOi;
EXITWHENemp_cur%NOTFOUND;
DBMS_OUTPUT.put_line(i.empno
||','

||i.ename
||','
||i.sal
||','
||i.job
||','
||i.deptno
);
ENDLOOP;
IFemp_cur%ROWCOUNT>0
THEN
DBMS_OUTPUT.put_line

(''
);
ENDIF;
CLOSEemp_cur;
ENDLOOP;
CLOSEdept_cur;
END;
O/P::
7839,KING,5000,PRESIDENT,10
7782,CLARK,2450,MANAGER,10
7934,MILLER,1300,CLERK,10

7566,JONES,2975,MANAGER,20
7788,SCOTT,3000,ANALYST,20
7902,FORD,3000,ANALYST,20
7369,SMITH,800,CLERK,20
7876,ADAMS,1100,CLERK,20

7698,BLAKE,2850,MANAGER,30
7499,ALLEN,1600,SALESMAN,30
7521,WARD,1250,SALESMAN,30
7654,MARTIN,1250,SALESMAN,30
7844,TURNER,1500,SALESMAN,30
7900,JAMES,950,CLERK,30

CURSOR WITH SUB QUERY:: Write a plsql cursor to display deptno,


deptname, location and no of employees , that deartment which
is having more than 3 employees.
DECLARE
CURSORdept_cur
IS
SELECTd.deptno,d.dname,d.loc,v.noe
FROMdeptd,
(SELECTdeptno,COUNT(*)noe
FROMemp
GROUPBYdeptnohavingcount(*)>3)v
WHEREd.deptno=v.deptno;

BEGIN
FORiINdept_cur
LOOP
DBMS_OUTPUT.put_line(i.deptno||','||i.
dname||','||i.loc||','||i.noe
);
ENDLOOP;
END;

O/P::
30,SALES,CHICAGO,6
20,RESEARCH,DALLAS,5

Example ::

DECLARE
CURSORcur(c_locationINmast_location.LOCATION%TYPE)
IS
SELECTebiz_sku_no,packcode,size_id,SUM(act_qty)qty
FROMtrn_opentask
WHEREend_location=c_location
ANDtask_typeIN('PUTW','MOVE','REPL')
ANDcomp_id=p_comp_id
ANDsite_id=p_site_id
ANDebiz_appown_no=p_ebiz_appown_no
ANDact_end_dateISNULL
GROUPBYebiz_sku_no,packcode,size_id;
BEGIN
FORiIN(SELECTLOCATION
FROMmast_location)
LOOP
FORcur_recIN(cur(i.LOCATION))
LOOP
BEGIN
SELECTNVL(wght,0),NVL(CUBE,0)
INTOl_wght,l_cube
FROMTABLE(tp_mast_skudims.skudims(p_comp_id,
p_site_id,
p_ebiz_appown_no,
cur_rec.ebiz_sku_no
)
)
WHEREpackcode=cur_rec.packcode
ANDactive_flag='Y'
ANDdelete_flag='N'

ANDNVL(base_uom_flag,'N')='Y';
EXCEPTION
WHENNO_DATA_FOUND
THEN
NULL;
END;
ENDLOOP;
ENDLOOP;
END;

REFCURSOR/Dynamic Cursor::
Explicit cursors is a static cursor and it refers always one work
area associated with cursor.
REFCURSOR:: Ref cursor is a dynamic cursor
It refers different work area in memory
It works like pointer un C
Declaring a cursor variable with a pointer as datatype
known as REFCURSOR.
It

is

used

to

declare

the

cursor

without

select

statement
Cursor can be reused, if it is declared in package.
Supports to return more than one row from sub
program
Different select statement can be associated with
cursor variable at RUNTIME.
Types of ref cursor:: They are two types of dynamic cursor
1) weak ref cursor:: The cursor variable without return type is
called as weak ref cursor
Syntax:: type<typename> is ref cursor;
2) strong ref cursor:: The cursor variable with return type called
as strong ref cursor.
Syntax::
type<typename>isrefcursor
return<tablename>%rowtype;
NOTE::AlwaysreturnisRECORDTYPE

Ex:: Write a PlSql procedure to display the empno, ename ,


deptno, of the 10th dept, emono, ename,job of the 20thdept,
other than these two(10&20) display the ename, job, sal of that
argument.
createorreplaceprocedureproc_ref(p_deptnoemp.depto%type)
is
v_empnoemp.empno%type;
v_enameemp.ename%type;
v_deptnoemp.deptno%type;
v_jobemp.job%type;
v_salemp.sal%type;
typeemp_ref_curisrefcursor;
ref_valemp_ref_cur;itisadatatypeofemp_ref_cur
begin
ifdeptno=10then
openref_valforselectempno,ename,deptnofromempwhere
deptno=p_deptno;
elsifdeptno=20then
openref_valforselectempno,ename,jobfromempwhere
deptno=p_deptno;
else
openref_valforselectempno,job,salfromempwheredeptno=p_deptno;

endif;
ifdeptno=10then
loop
fetchref_valintov_empno,v_ename,v_deptno;
exitwhenref_val%notfound;
dbms_output.put_line(v_empno||','||v_ename||','||v_deptno);
endloop;
closeref_val;
elsifdeptno=20then
loop
fetchref_valintov_empno,v_ename,v_job;
exitwhenref_val%notfound;
dbms_output.put_line(v_empno||','||v_ename||','||v_job);
endloop;
closeref_val;
elsedeptno=30then

loop
fetchref_valintov_empno,v_sal,v_job;
exitwhenref_val%notfound;
dbms_output.put_line(v_empno||','||v_sal||','||v_deptno);
endloop;
closeref_val;

endif;
end;

Since Oracle 7.3 the REF CURSOR type has been available to allow recordsets to be
returned from stored procedures and functions. Oracle 9i introduced the
predefined SYS_REFCURSOR type, meaning we no longer have to define our own REF
CURSOR types.

USING WHERE CURRENT OF CLAUSE::

LOCKS
Locks are introduced in oracle 7.x version. But more features were added
in 8.x version. In oracle 8i automatic row level lock system is perform.
Locks are the mechanism used to prevent the distractive
transactions/interactions between users. Accessing the same recourses
simultaneously.
Here A resource can, either table or specific row in a table.
Thus locks provide a high degree of data concurrency.
Concurrency: Multiple users use same resource at same time.
Locking system of oracle to prevent the concurrent users to do
destructive transactions.

LOCKS can be accrued in at two different levels:


1) ROW LEVEL
2) TABLE LEVEL

ROW LEVEL LOCKS: In the ROW level lock, a row is locked exclusively so
that other users cannot modify the row until the commit or rollback by
holding user.
Examples:
1) Select * from emp where empno=7788 for update of hiredate(Not
mandatory).
2) Update emp set hiredate=12-12-2012
Where empno=7788
Locks contain three statuses:
1) Define a lock
2) Invoked a lock
3) Release a lock
Grant select , insert, update, delete on emp to user A.
STEP1: Define a lock
Select * from emp Where empno=7788 for update (Here the lock
is defined)
STEP2: Invoked lock
Update emp set sal=sal+1000 where empno=7788 (Here the lock is
invoked)
At this moment, suppose if any user want to delete in another
schema they cant delete.
For example please connect another user USERA and write the below
query.
Delete from emp where Empno=7788
Here the system will not respond, it is in waiting
mode until scott user do commit or rollback.

STEP3: Release the lock


Do the commit or rollback

TABLE LEVEL LOCKS:

A table level lock will protect the table data, when the data is
being accessed concurrently by the multiple users.
A table level lock can be several modes:
1) Share Lock
2) Share Update Lock
3) Exclusive Lock
SYNTAX: lock table <table name> in <share/share update/exclusive
mode>;
Share Lock:A share lock, locks the table allowing the other users to only
query but not Insert, Update, Delete rows in a table.
EX: Lock table emp in share mode
Share Update: By using this only we can lock specific records (Like 10th
dept or 20th dept). And it permits the other users to concurrently query,
insert , update, delete on other remaining unlocked rows.
It prevents the other users from updating the rows that has been locked.
EX: Lock table emp in share update mode.
Update emp set sal=sal+1000 where deptno=10;
Exclusive Locks: It allows the other user to only query but not insert ,
update, delete rows in a table.
It almost similar to a share lock, but only one user can place an
exclusive lock on a table at a time. Where many users can place a share
lock on the same table at the same time.
EX: Lock table emp in exclusive mode;
NOTE: Locks are temporary mechanisms as soon as commit or roll back or
exit session all locks are released.
Dead Locks:Dead lock occurs when two users have a lock on a same
resource. For example user A locked/updated the emp table at the same
time userB also locked/updated the emp table. Here userB have to wait
until userA release the emp table but userA will not release and now
userB lock will not release until the userA released.
At this point both users cant do their
business/operations. In such a case, oracle detects the dead locks
automatically and solving the problem by aborting one of the two
transactions.

ROLES IN ORACLE: A role is a named group of related privileges that can


be granted to the user.
Advantages of role: Rather than assigning privileges one at a
time directly to USER, we can create a role, assign privileges to that role,
and then grant that role.

WHERE CURRENT OF CLAUSE::


WHERE CURRENT OF clause is refer the current record, fetched
from the explicit cursor.
We need to suffix the name of the explicit cursor with the
CURRENT OF clause to refer the current record.
In order to use the WHERE CURRENT OF clause, you need to
lock the records fetched from the cursor.
FOR UPDATE CLAUSE::
For update clause explicitly locks the records stored in the
work area.
You need not provide the explicit commit command to release
the lock acquired by using the FOR UPDATE CLAUSE.
EX:: write a Pl/Sql cursor to display all employees if any employee
is belongs to 50th dept, remove that employees and after remove
the employees, display the remaining employees by using same
program.
DECLARE
CURSORfor_upd_cur
IS
SELECTempno,ename,deptno,job
FROMemp_l
FORUPDATE;
ifor_upd_cur%ROWTYPE;
BEGIN
OPENfor_upd_cur;
LOOP
FETCHfor_upd_cur
INTOi;
EXITWHENfor_upd_cur%NOTFOUND;
DBMS_OUTPUT.put_line(i.empno||','||i.ename||','||
i.deptno);

IFi.deptno=20
THEN
DELETEFROMemp_l
WHERECURRENTOFfor_upd_cur;
ENDIF;
ENDLOOP;
CLOSEfor_upd_cur;
DBMS_OUTPUT.put_line('Afterdeletingthe50thdepartmentemployee
records');
OPENfor_upd_cur;
LOOP
FETCHfor_upd_cur
INTOi;
.
EXITWHENfor_upd_cur%NOTFOUND;
DBMS_OUTPUT.put_line(i.empno||','||i.ename||','||
i.deptno);
ENDLOOP;
END;

O/P::
7839,KING,10
7698,BLAKE,30
7782,CLARK,10
7566,JONES,20
7788,SCOTT,20
7902,FORD,20
7369,SMITH,20
7499,ALLEN,30
7521,WARD,30
7654,MARTIN,30
7844,TURNER,30
7876,ADAMS,20
7900,JAMES,30
7934,MILLER,10
Afterdeletingthe20thdepartmentemployeerecords
7839,KING,10
7698,BLAKE,30
7782,CLARK,10
7499,ALLEN,30
7521,WARD,30
7654,MARTIN,30
7844,TURNER,30
7900,JAMES,30
7934,MILLER,10

EXCEPTION HANDLING
EXCEPTIONS:: Basically/Generally errors are two types
1) Syntactical
2) Runtime
We will get the syntactical errors at compilation time and at the
time of compilation time itself we can rectify the compilation
errors.
To handle the run time errors, we use the exceptions.
Exception Handling::
An exception in PlSQL block raised during the execution of block
It terminates the main body of action, means a block always
terminates when Pl/Sql raises an exception.
We can specify an exception handler to perform final action.
Trapping Exceptions::
An exception handler section contains the code that is executed,
when the error associated with the exception occurs, and the
exception is raised.
Syntax::
exception
when<exception1>[orexception2...]then
<execstatemnts>;
when<exception2>[orexception4...]then
<execstatemnts>;
whenothersthen
<execstatemnts>;

end;

Others Exception Handler::


The others exception is optional exception handling clause that
traps unspecified exceptions.
The other should always be the last handler in the block

This is a good programming practice to have the OTHERS handler


at the top level of your program to ensure that no errors go
undetected.
NOTE:: If exception is raised in executable section of the block
and there is no corresponding handler, the plsql block terminates
with failure.
If the exception is handled then the plsql block
terminates successfully.
Types Of Exceptions:: There are two types of exceptions
1) User defined
2) Pre defined
User
defined
exceptions::
User
has
to
declared
the
exceptions/Created by the user, raise/Activated the exception by
the user and the handle/Solution provided by the user.
Pre defined exception:: Provided by the oracle and activated by
the oracle automatically.
Pre defined exception:: Oracle has several predefined exceptions
and these are most common oracle errors.
Each predefined exception begins with ORA followed by a number.
As soon As the exception occurs oracle implicitly raise the
exception and jumps into the exception handler block, If proper
exception handler is found managed the specified steps.
In predefined oracle server exceptions only one exception is
raised and handled any time.
Predefine exceptions list::
Error No
ORA-0001
ORA-1001
ORA-1403

Exception Name
DUP_VAL_ON_INDE
X
INVALID_CUROSR
NO_DATA_FOUND

ORA-1422

TOO_MANY_ROWS

ORA-1722

INVALID_NUMBER

ORA-6502
ORA-6511

VALUE_ERROR
CURSOR_ALREADY_

Description
Unique Constraint violated
illegal cursor Operator
No Data Found
A select INTO statement matches more
than one row
Conversion to a Number
failed(100+'4,200)
Truncation, Arithmetic or Conversion
Error
When reopen a cursor without close

OPEN
ORA-1017
ORA-1476
ORA-6592

LOGIN_DENINED
ZERO_DEVIDE
CASE_NOT_FOUND

When you enter a wrong user name and


password
Devisor is equal to zero
When the enter case is not matched

Ex:: NO_DATA_FOUND(Write a program to display the ename and


job for given employee number, if no data found for given
employee number please print a message like 'Given employee
number is not exist, so please enter valid employee number)
DECLARE
v_empnoemp.empno%TYPE:=&empno;
v_enameemp.ename%TYPE;
v_jobemp.job%TYPE;
BEGIN
SELECTename,job
INTOv_ename,v_job
FROMemp
WHEREempno=v_empno;
DBMS_OUTPUT.put_line(v_ename
||','
||v_job
||''
||'aretheemployeedetails'
);
EXCEPTION
WHENNO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line
('Givenemployeenumberisnotexist,sopleaseentervalid
employeenumber'
);
END;

I/P::7839
O/P::KING,PRESIDENTaretheemployeedetails
I/P::1111
O/P:: Givenemployee number is not exist, sopleaseentervalidemployee
number

Ex2::
No_data_found,
examples

TO_MANY_ROWS,

OTHERS

exception

DECLARE
iemp%ROWTYPE;
BEGIN
SELECTename,deptno
INTOi.ename,i.deptno
FROMemp
WHEREempno=7788ANDename='SCOTT';
DBMS_OUTPUT.put_line('The'||i.ename||'isworkingfor'||
i.deptno);
SELECTename
INTOi.ename
FROMemp
WHEREdeptno=10;
DBMS_OUTPUT.put_line('Theempnamewhoisworkingin10thdept'||
i.ename);
EXCEPTION
WHENNO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line('Theemployeenumberenamedeptnonotexists');
WHENTOO_MANY_ROWS
THEN
DBMS_OUTPUT.put_line('The1othdeptemployeesmorethan1');
WHENOTHERS
THEN
DBMS_OUTPUT.put_line
('Thereisunhandledexceptionwhileprocessinga
program');
END;
O/P::
TheSCOTTisworkingfor20
The1othdeptemployeesmorethan1

From the above program if we comment the below exception code


WHENTOO_MANY_ROWS
THEN
DBMS_OUTPUT.put_line('The1othdeptemployeesmorethan1');

O/P::
TheSCOTT is working for 20
There is unhandled exception while processing a program

RAISE_APPLICATION_ERROR:: It is a built in function and it is used


to suspend the task and display our own messages.
SYNTAX:: raise_application_error(<errorno>,<errormesg>);
Range::20,000to20,999

Ex:: Write a PLSQL program to hike the emp salary as 15% if


employee salary is more than 2000. If emp salary is less than
2000 suspended the program with appropriate message.
DECLARE
iemp%ROWTYPE;
BEGIN
i.empno:=&empno;
SELECTename,sal
INTOi.ename,i.sal
FROMemp
WHEREempno=i.empno;
IFi.sal<2000
THEN
raise_application_error(20345,
'Thesalislessthan2000,Noupdations
done'
);
ELSE
i.sal:=i.sal+i.sal*0.15;
UPDATEemp
SETsal=i.sal
WHEREempno=i.empno;
DBMS_OUTPUT.put_line('Theempdetailsare'||i.ename||''||
i.sal);
ENDIF;
EXCEPTION
WHENNO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line('Thegivenempnoisnotexist');
/*WHENOTHERS
THEN
DBMS_OUTPUT.put_line
('Anunhandledexceptionoccurwhileprocessingthe
program');*/
END;

I/P::1111
O/P::Thegivenempnoisnotexist
I/P::

ORA20345:Thesalislessthan2000,Noupdationsdone
NOTE::Ifweusewhenothersintheexceptionhandlersectionwewillget
thebelowmessage.
I/P::7369
O/P::Anunhandledexceptionoccurwhileprocessingtheprogram

NOTE:: Whenever the RAISE_APPLICATION_ERROR used we can't


use the WHEN OTHERS. here RAISE_APPLICATION_ERROR directly
jumps into WHEN OTHERS statement.
In the above program raise_application_error may not display the
message when others exception will be activated.
DIFF B/W PUT_LINE & RAISE_APPLICATION ERROR::
PUT_LINE
It is the construct of the DBMS_OUTPUT
package

RAISE_APPLICATION_ERROR

It contains only one parameter

It is standard alone function


It contains two parameters RANGE,ERROR
Message

It only display the messages and


variable values

It will display the messages and variable


values and also suspended task also

ERROR FUNCTIONS/
COLUMNS::

QUALIFIERS

in

EXCEPTIONS

PSEDEO

We have tow qualifiers


1) SQL CODE:: To capture the error code(Holds the current raised
error numbers)
2) SQL ERRM:: To Capture the error message(Holds the current
raised error messages
NOTE:: We can't use the error functions in a sql statements.
USER DEFINED EXCEPTIONS::
STEPS::
1) Declare the exception
2) Raise the exception in executable section. Explicitly by using
RAISE statement.
3) Handled the raised exception in exception section.

EX:: Write a PLSQL program to hike the employee salary as 15% if


employee contains a salary. If not having a salary gives the
default sal as 3000.
DECLARE
sal_missingEXCEPTION;
iemp%ROWTYPE;
BEGIN
i.empno:=&empno;
SELECTename,sal
INTOi.ename,i.sal
FROMemp
WHEREempno=i.empno;
IFi.salISNULL
THEN
RAISEsal_missing;
ELSE
i.sal:=i.sal+i.sal*0.15;
UPDATEemp
SETsal=i.sal
WHEREempno=i.empno;
DBMS_OUTPUT.put_line('Theemployeedetailsare::'
||i.ename
||''
||i.sal
);
ENDIF;
EXCEPTION
WHENNO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line('GivenEmployeenumberisnotexist');
WHENsal_missing
THEN
DBMS_OUTPUT.put_line
('Theemployeeisnothavingsal,sogiveasadefaultsalis
3000');
UPDATEemp
SETsal=3000
WHEREempno=i.empno;
DBMS_OUTPUT.put_line(SQLCODE||''||SQLERRM);
WHENOTHERS
THEN
DBMS_OUTPUT.put_line('Theunhandledexceptionisoccur');
END;

I/P::7369
O/P::Theemployeedetailsare::SMITH920

PRAGMA EXCEPTION_INIT:: It is user defined exception. We use


PRAGAM EXCEPTION_INIT mainly whenever we are violating the
constraints.
EXCEPTION_INIT:: will provide our own messages by overriding
the built in messages for end user purpose.
PRAGMA:: It is a complier hint or engine directive
We have to provide the PRAGMA at declarative section
NOTE:: EXCEPTION_INIT takes two arguments
1) error code 2) user defined error message
STEPS::
1) Declare Exception
2) Declare the prgma exception with argument name
previously defined exception and with some error number.

as

3) Handled the raised exception


Syntax:: pragma exception_init(exception name, error no);
Ex:: Write a PL/SQl Program to display the user defined message
when you enter a duplicate empno number through insert
statements.
DECLARE
pk_violatedEXCEPTION;
PRAGMAEXCEPTION_INIT(pk_violated,001);
BEGIN
INSERTINTOemp
VALUES(7839,'KING','PRESIDENT',NULL,NULL,5000,null,10);
EXCEPTION
WHENpk_violated
THEN
DBMS_OUTPUT.put_line('Duplicateaccountnumberisnotallowed
here');
END;

O/P::
Duplicateaccountnumberisnotallowedhere

SUBPROGRAMS
Subprograms are used to provide the modularity, reusability,
maintainability.
Once the subprogram built and validated, they can used in a
number of applications
Subprograms are also provide the abstraction
Subprograms are named plsql blocks that can accept parameters
A sub program can also have declarative part, an executable part
and exception handling part.
MODULARITY:: Sub Program allows us to break a program into a
modules to maintain easily.
REUSABILITY:: Subprograms once executed, we can use in any
number of applications
MNATAINBILITY:: If a subprogram is effected, only its definition
changes this means maintenance of subprograms easy.

Subprograms are:: 1) Procedures 2) Functions 3) packages


PROCEDURE/STORED PROCEDURE:: Stored procedure is logically
grouped the set of SQL and PLSQL statements that perform a
specific task.
Types of procedures::
1) Standard alone schema object 2) A Part of the Package
1) Standard alone schema object:: The procedure which is
created outside of the package is called as standard alone
schema object.
2) A Part of the Package:: The procedure which is created inside
of the package is called as A Part of the Package.
This procedure not stored anywhere in the database.(Which is
available under with packagename.procname)
Syntax::
cretaeorreplcaeprocedure<procedurename>
([parametername[mode]]<datatype>,.,..)
is/as
[localvariabledeclaration];
begin
<execstmts>;
[exception
whencondtionthen
<execstmts>;]
end[procedurename];

EX1::
Write a plsql procedure to calculate the simple and
compound interest.
createorreplaceprocedurecal_si_ci(pinnumber,
ninnumber,
rinnumber
)
is
sinumber;
cinumber;
begin
si:=(p*n*r)/100;
ci:=p*power((1+r/100),n);
ci:=cip;
dbms_output.put_line('TheSIandCIis::'||si||''||ci);

end;
/

Calling procedure::
1) At Sql Prompt::
Syntax:: exec procedurename(arg1,ard2,arg3...);
Ex::

2) In Plsql Program::
BEGIN
cal_si_ci(1000,12,2);
END;
O/P::TheSIandCIis::240268.241794562545318301696

NOTE:: Procedures are stored in


1) user_source
2) user_procedures
3) user_objects
4) db_objects

Ex:: Write a PLSQL procudure to hike the emp sal with the
following conditions
a) If employee commission is null give the comm as
250 and calculate the bonus as 15% on his net sal.
b) Calculate the bonus as 25% if the employee comm is
zero
c) Other than these two, calculate the 35% bonus on
their net sal.
4) Update employee sal with this bonus.

OUTPUT should displayed as ename, bonus and updated salary.


CREATEORREPLACEPROCEDUREcal_bonus
IS
CURSORcal_bonus_cur
IS
SELECTempno,ename,sal,comm
FROMemp;
ical_bonus_cur%ROWTYPE;
v_bonusnumber;
BEGIN
OPENcal_bonus_cur;
LOOP
FETCHcal_bonus_cur
INTOi;
EXITWHENcal_bonus_cur%NOTFOUND;
IFi.commISNULL
THEN
v_bonus:=(i.sal+250)*0.15;
ELSIFi.comm=0
THEN
v_bonus:=(i.sal*0.25);
ELSE
v_bonus:=(i.sal+i.comm)*0.35;
ENDIF;
i.sal:=i.sal+v_bonus;
UPDATEemp
SETsal=i.sal
WHEREempno=i.empno;
DBMS_OUTPUT.put_line(i.ename
||''
||v_bonus
||''
||i.sal
);
ENDLOOP;
CLOSEcal_bonus_cur;
ENDcal_bonus;

execcal_bonus;
KING787.55787.5
BLAKE4653315
CLARK4052855
JONES483.753458.75
SCOTT487.53487.5
FORD487.53487.5
SMITH157.5957.5

ALLEN6652265
WARD612.51862.5
MARTIN927.52177.5
TURNER3751875
ADAMS202.51302.5
JAMES1801130
MILLER232.51532.5

Procedure can call in diff locations::


At Sql Prompt, In Plsql block, Procedure, Function, Trigger,
Package...
BANKING TABLES::
CREATETABLErcb_acc_tab(
rcb_accnoVARCHAR2(30)CONSTRAINTrpk_accnoPRIMARYKEY,
rcb_acc_holder_nameVARCHAR2(40)CONSTRAINTrnn_nameNOTNULL,
rcb_acc_holder_acctypeCHARCONSTRAINTrchk_acctype
CHECK(rcb_acc_holder_acctypeIN('S','C','R')),
rcb_acc_holder_jdateTIMESTAMPDEFAULTSYSDATE,
rcb_acc_holder_balanceNUMBERCONSTRAINTrnn_balanceNOTNULL,
CONSTRAINTrcb_check_balCHECK((rcb_acc_holder_acctype='S'AND
rcb_acc_holder_balance>=5000)OR
(rcb_acc_holder_acctype='C'ANDrcb_acc_holder_balance>=10000)OR
(rcb_acc_holder_acctype='R'ANDrcb_acc_holder_balance>=5000)
)
)

CREATETABLErcb_tran_table(
rcb_tran_idNUMBERCONSTRAINTrpk_tran_idPRIMARYKEY,
rcb_accnoVARCHAR2(30)CONSTRAINTrfk_accnoREFERENCES
rcb_acc_tab(rcb_accno),
rcb_tran_typeCHARCONSTRAINTrtchk_rcb_tran_typeCHECK(rcb_tran_type
IN('D','W')),
rcb_date_of_transactionTIMESTAMPDEFAULTSYSDATE,
rcb_tan_amountNUMBERCONSTRAINTnn_tran_amountNOTNULL
)

EX::
Write
a
program
deposite/withdraw

to

update

the

balance

after

CREATEORREPLACEPROCEDUREupd_bal(
p_accnorcb_acc_tab.rcb_accno%TYPE,
p_ttypercb_tran_table.rcb_tran_type%TYPE,
p_rcb_tan_amountrcb_tran_table.rcb_tan_amount%TYPE
)
IS
v_rcb_acc_holder_acctypercb_acc_tab.rcb_acc_holder_acctype%TYPE;
v_rcb_acc_holder_balancercb_acc_tab.rcb_acc_holder_balance%TYPE;
BEGIN
SELECTrcb_acc_holder_acctype,rcb_acc_holder_balance
INTOv_rcb_acc_holder_acctype,v_rcb_acc_holder_balance

FROMrcb_acc_tab
WHERErcb_accno=p_accno;
IFUPPER(p_ttype)='D'
THEN
v_rcb_acc_holder_balance:=v_rcb_acc_holder_balance+
p_rcb_tan_amount;
ELSIFUPPER(p_ttype)='W'
THEN
v_rcb_acc_holder_balance:=v_rcb_acc_holder_balance+
p_rcb_tan_amount;
IFv_rcb_acc_holder_balance<=5000ANDv_rcb_acc_holder_acctype=
'S'
THEN
raise_application_error(20345,
'Thebalistoolowsonotransaction'
);
ELSIFv_rcb_acc_holder_balance<=10000
ANDv_rcb_acc_holder_acctype='S'
THEN
raise_application_error(20345,
'Thebalistoolowsonotransaction'
);
ENDIF;
ENDIF;
UPDATErcb_acc_tab
SETrcb_acc_holder_balance=v_rcb_acc_holder_balance
WHERErcb_accno=p_accno;
INSERTINTOrcb_tran_table
VALUES(NVL((SELECTMAX(rcb_tran_id)
FROMrcb_tran_table),100)+1,p_accno,p_ttype,
SYSDATE,p_rcb_tan_amount);
EXCEPTION
WHENNO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line(p_accno||'Isnotexists');
ENDupd_bal;
/

Calling the above procedure::


execupd_bal(1,'D',200);
O/P::
Select*fromrcb_acc_tab
select*fromrcb_tran_table

PARAMETERS MODE:: We have three parameter modes


1) IN 2) OUT 3) INOUT

IN:: this is the default, always accept a value into a subprogram.


It can't assigned with a value in subprogram.
OUT:: Used to return a value from subprogram. Initialized sub
program, it can't carries a value into a subprogram.
INOUT:: Carries a value into a subprogram. return a values from
sub program.
NOTE::
subprograms.

Maximum

32

arguments

supported

by

(<parametername>[parametermode]<datatype>)

Ex:: Write a plsql procedure to return square, Cube value for


entered number.
CREATEORREPLACEPROCEDUREproc_sqcb(nINNUMBER,sOUTNUMBER,cOUT
NUMBER)
IS
BEGIN
s:=n*n;
c:=n*n*n;
ENDproc_sqcb;

Execution at Sqlplus::

Execution in another PL/SQL program::


DECLARE
v_nNUMBER:=&no;

v_sNUMBER;
v_cNUMBER;
BEGIN
proc_sqcb(v_n,v_s,v_c);
DBMS_OUTPUT.put_line(v_s||','||v_c);
END;
I/P:2
O/P::4,8

NOTE:: Bind variables can use in a PL/Sql program.


DECLARE
v_nNUMBER:=&no;

BEGIN
proc_sqcb(v_n,:rs,:rc);
DBMS_OUTPUT.put_line(:rs||','||:rc);
END;

I/P:3
O/P::9,27

Ex2:: Write a Pl/Sql Procedure to return no of employees for given


deptno.
CREATEORREPLACEPROCEDUREproc_cnt(p_deptnoINOUTNUMBER)
IS
noeNUMBER(10);
BEGIN
SELECTCOUNT(*)
INTOnoe
FROMemp
WHEREdeptno=p_deptno;

dbms_output.put_line(noe||'eployeesareavailableinthedepartment');

ENDproc_cnt;
Callingtheaboveprogram::

Ex::Write a program to insert the values to table.


createtableadd_dept_tabasselect*fromdept

createsequenceadd_Dept

CREATEORREPLACEPROCEDUREproc_add_dept(
p_dnameINdept.dname%TYPEdefault'UNKNOWN',
p_locINdept.loc%TYPEdefault'UNKNOWN'
)
IS
BEGIN
INSERTINTOadd_dept_tab
VALUES(add_dept.NEXTVAL,p_dname,p_loc);
ENDproc_add_dept;

execproc_add_dept('EXPORT','BLORE');
select*fromadd_dept_tab

execproc_add_dept('SOFTWARE');
select*fromadd_dept_tab
execproc_add_dept()
select*fromadd_dept_tab
execproc_add_dept
select*fromadd_dept_tab
execproc_add_dept(,'HYD')itisgivinganerror
execproc_add_dept('','HYD');thisnotcorrect
select*fromadd_dept_tab

NOTE::
Through this is procedure
LOCATION

we need to pass only

Types of sending arguments::


1) Position Notation: By position of the parameter the arguments
will be passed
Ex:: execproc_add_dept('EXPORT','BLORE');
2) Named Notation:: (==>) The arguments can be passed by
name of the paramaters.

Ex::
execproc_add_dept(p_loc=>'HYD');
select*fromadd_dept_tab

HOW TO GRANT A PERMISION ON A PROCEDURE::


We can grant the permissions on a procedure.
grantexecuteoncal_intrtokrishna(user)
execscott.cal_intr(1000,12,2);

PROCEDURE FOR SYNONYM::


Syntax:: createsynonym<sname>for<procname>;
Ex::
createpublicsynonymsc2forproc_add_dept;
grantexecutesc2topublic;
loginwithkrishnauser
execsc2('hardware','NPM');

NOTE:: We can't create a synonym for procedure, which is in the


part of the package.
Synonyms are only crate for data base objects.
PROCEDURE OVER LOADING:: A procedure can define with same
name with different signature in a package is called as procedure
over loading.

1) Diff signature and Diff no of parameters


proc1(p1innumber)
proc1(p1innumber,p2innumber)

2) Diff sequence of data types


proc1(p1innumber,p2varchar2)
proc1(p1invarchar2,p2number)

3)Diff types of data types


proc1(p1invarchar2,p2invarchar2)

NOTE:: It is happens only in, inside the package.


TO REMOVE THE PROCEDURE::
dropprocedure<proc_name>;

NESTED PROCEDURES::
if we call one procedure in another
procedure is called as NTESTED PROCEDURE.
PRAGMA
AUTONOMOUS_TRANSACTION::
To
make
the
TCL(Commit/rollback) commands independently use the PRAGMA
AUTONOMUS_TRANSACTION.
It is allows to writes the TCL triggers.
CREATEORREPLACEPROCEDUREproc_add_emp
AS
PRAGMAAUTONOMOUS_TRANSACTION;
BEGIN
INSERTINTOemp
(empno,ename,sal,deptno
)
VALUES(1002,'1johny',2000,50
);
COMMIT;
ENDproc_add_emp;

createorreplaceprocedureproc_add_dept1
as
begin
insertintodeptvalues(60,'EEEXPORT','NNNPM');
proc_add_emp;
end;

NOTE:: In this case proc_add_emp procedure is called as called


procedure. add_dept procedure is called as calling procedure.
execproc_add_dept1;

emp -> 15
dept-> 5
rollback;
The dept transaction rollback but emp records are not rollback

emp-> 15
dept -> 4
NOTE:: Emp commit will not effects the calling program.

FUNCTIONS
They are similar to that of procedures but by default return single
value, we use the functions mainly for calculation purpose or to
make the use of dml operations.
Function is named plsql block and it may or may not take the
parameters, but it must return the value.
Function must have a return clause in the executable section of a
function.
Functions are mainly used to perform the calculations
The datatype of the return value must be declared in the header
of the function
Procedure and functions can be stored in the database
declared with in the package.

or

Procedures and functions are different forms of PL/SQL blocks,


with declare executable and exception sections.
A procedure call is a PL/SQl stmt by itself, while a function is
called as part of an expression.
A function has a output that needs to be assigned to a variable
(or) it can be used in select statement.

Ex::
1)
begin

varname:=fun1(arg1,arg2);
end;

2) selectfun1(arg1,arg2)fromdual;
Function can't call when it has return data type as Boolean at sql
prompt.
Function can't call at sql prompt when return a value through OUT
mode, INOUT mode parameters.
A function can contain more than one return statements, each
exception should have return statement.

Syntax::
create[orreplace]function<function_name>(parameterlist)
returndatatype
is
[localvariables];
begin
<body>;
return(value);
exception
execstmts;
endfunction_name;

Function can invoked at ::


In select statement , In Pl/Sql block, In procedure, In Function, In
Trigger , package , other application in S/W.
Standard Form of a function calling is ::
begin
variablename:=funname(arg1,arg2);
end;

At SQL prompt::

execvariablename:=fun1(arg1,arg2);

Ex:: Write a Pl/SQL function to calculate the compound interest.


CREATEORREPLACEFUNCTIONfun_cal_co(pINNUMBER,nINNUMBER,rNUMBER)
RETURNNUMBER
IS
ciNUMBER;
BEGIN
ci:=p*POWER((1+r/100),n);
ci:=cip;
RETURN(ci);
ENDfun_cal_co;

In SELECT statement calling::


selectfun_cal_co(1000,12,2)fromdual

In another plsql block calling::


DECLARE
cintrNUMBER;
BEGIN
cintr:=fun_cal_co(1000,12,2);
DBMS_OUTPUT.put_line('Displaythecompoundinterestis::'||cintr);
END;
Displaythecompoundinterestis::268.241794562545318301696
begin
dbms_output.put_line('Thecompoundinterestis::'||fun_cal_co(1000,12,2));
end;
O/P::
Thecompoundinterestis::268.241794562545318301696

At SQL PROMPT::

Ex2:: Write a plsql function to return as EVEN/ODD number for


entered number.
CREATEORREPLACEFUNCTIONfun_even_odd(nINNUMBER)
RETURNVARCHAR2
AS
BEGIN
IFMOD(n,2)=0
THEN
RETURN('Itisaevennumer');
ELSE
RETURN('Itisaoddnumber');
ENDIF;
ENDfun_even_odd;

Ex3:: Write a plsql function to find the entered year is a


LEAPYEAR/NOT, return the character value as O/P.
CREATEORREPLACEFUNCTIONfun_leap_year(yINNUMBER)
RETURNVARCHAR2
IS
BEGIN
IFMOD(y,400)=0OR(MOD(y,4)=0ANDMOD(y,100)!=0)
THEN
RETURN('Itisaleapyear');
ELSE
RETURN('Itisnotaleapyear');
ENDIF;
ENDfun_leap_year;

Ex:: Write a Pl/SQL function to return a Boolean value to check


the eligibility of withdrawl.
CREATEORREPLACEFUNCTIONfun_chk_bal(
p_rcb_accnoINrcb_acc_tab.rcb_accno%TYPE,

p_rcb_tan_amountINrcb_tran_table.rcb_tan_amount%TYPE
)
RETURNBOOLEAN
AS
v_rcb_acc_holder_acctypercb_acc_tab.rcb_acc_holder_acctype%type;
v_rcb_acc_holder_balancercb_acc_tab.rcb_acc_holder_balance%type;
BEGIN
SELECTrcb_acc_holder_acctype,rcb_acc_holder_balance
INTOv_rcb_acc_holder_acctype,v_rcb_acc_holder_balance
FROMrcb_acc_tab
WHERErcb_accno=p_rcb_accno;
v_rcb_acc_holder_balance:=v_rcb_acc_holder_balancep_rcb_tan_amount;
IFv_rcb_acc_holder_balance<=5000ANDv_rcb_acc_holder_acctype='S'
THEN
RETURN(FALSE);
ELSIFv_rcb_acc_holder_balance<=10000ANDv_rcb_acc_holder_acctype=
'C'
THEN
RETURN(FALSE);
ELSE
RETURN(TRUE);
ENDIF;
ENDfun_chk_bal;

Calling the above fuction::


BEGIN
IFfun_chk_bal(&accno,&amt)
THEN
DBMS_OUTPUT.put_line('itisvalid');
ELSE
DBMS_OUTPUT.put_line('itisvalid');
ENDIF;
END;

O/P::

it is not valid

Function
Function is mainly used in the case where it
must return a value
Function can be called from SQL statements
Functions are normally used for
computations
Function returns 1 value only
We can use DDL in Procedure using
Execute Immediate statement

Procedure
Where as a procedure may or may not return a
value or may return more than one value using
the OUT parameter.
where as procedure can not be called from the
sql statements
where as procedures are normally used for
executing business logic.
Procedure can return multiple values (max
1024).
while tht is not possible in functions

o
JOBS CREATION IN ORACLE::
SYS.dbms_job.PROCEDUREisubmit(jobINBINARY_INTEGER,
whatINVARCHAR2,
next_dateINDATE,
intervalINVARCHAR2DEFAULT'null',
no_parseINBOOLEANDEFAULTFALSE);

TO CREATE A NEW JOB ::


DECLARE
X NUMBER;
BEGIN
INTFMGR.DBMS_JOB.ISUBMIT
( job

=> 17

,what
=> 'declare x number ; l_process_seq_no number ; begin
x:=logging.logprocesstab(null,null,null,'MSIL',sysdate ,
to_char(sysdate,'sssss'),2,null,null,'intfmgr.ebiz_intf_msil_so.so_main
Called ','JOB-17' ,l_process_seq_no ,
null ,'intfmgr.ebiz_intf_msil_so.so_main','02'); x :=
intfmgr.ebiz_intf_msil_so.so_main('MSIL','02',2,4,'SO',null);
x:=logging.logprocesstab(null,null,null,'MSIL',sysdate ,
to_char(sysdate,'sssss'),2,null,null,'intfmgr.ebiz_intf_msil_so.so_main
Called ','JOB-17' ,l_process_seq_no ,
x ,'intfmgr.ebiz_intf_msil_so.so_main','02'); end;'
,next_date => sysdate;
,interval => 'SYSDATE + (04/(24*60))'
,no_parse => FALSE
);
DBMS_OUTPUT.PUT_LINE('Job Number is: ' || to_char(x));
COMMIT;
END;

/
TO DROP THE JOB::
BEGIN
SYS.DBMS_JOB.REMOVE(17);
COMMIT;
END;
/
COLLECTIONS
http://www.tutorialspoint.com/plsql/plsql_collections.htm

Collections are composite data types. By using collections we can


retrieve the data fast at runtime. Why because every collection creates
with an index this is the reason data retrieving fast.
We have three types of collections
1) Nested table
2) Varray
3) Index by table(Associative array)
Nested table Example::
DECLARE
TYPEname_tabISTABLEOFvarchar2(20);
NAMEname_tab;
BEGIN

NAME:=name_tab('ravi','tiru','rao');intilization
FORiIN1..NAME.COUNT
LOOP
dbms_output.put_line(NAME(i));
ENDLOOP;

END;
/
Indexwillbelike::

1 Ravi
2 Tiru
3 Rao
Varray Example::
DECLARE
TYPEname_tabISVARRAY(20)OFvarchar2(20);
NAMEname_tab;
BEGIN

NAME:=name_tab('ravi','tiru','rao');intilization
FORiIN1..NAME.COUNT
LOOP
dbms_output.put_line(NAME(i));
ENDLOOP;

END;
/

Index By table Example::


DECLARE
TYPEslaryISTABLEOFnumberINDEXBYBINARY_INTEGER;
sal_listslary;
NAMEvarchar2(100);
BEGIN

sal_list('tirupati'):=500;
sal_list('ram'):=200;
NAME:=sal_list.FIRST;
WHILENAMEISNOTNULL
LOOP
dbms_output.put_line(sal_list(NAME));
NAME:=sal_list.NEXT(NAME);

ENDLOOP;
END;

Collections are composite data types. By using collections we can


retrieve the data fast at runtime. Why because every collection creates
with an index this is the reason data retrieving fast.
We have three types of collections
1) Nested table
2) Varray
3) Index by table(Associative array)

Difference::
Nested Table
Type type_name is table of
datatype
Un bounded (At run time
we can increase the size)
Index should be in
sequence(We can use
possitive numbers for
index)
We can delete the middle
values
Need intilization (No need
if we use bulk collect)
Valid in Sql and Plsql
collection.limit = null
Can Be Object Type
Attribute

Varray
Type type_name is varray(size) of
datatype

Index by table/Associative Array


Type type_name is table of
data_type index by binary_integer

Bounded (We can't increase)

Unbounded

Index should be in sequence(We


can use possitive numbers for
index)

Index can be possitvie and


negetive and special characters
and strings also we can give

We can't delete the middle values


Need intilization (No need if we
use bulk collect)
Valid in Sql and Plsql
collection.limit = Not null

we can delete

Can Be Object Type Attribute

No

No Need initialization
Valid only in plsql
collection.limit = null

Collection Methods::
S.N
.

Method Name & Purpose

EXISTS(n)
Returns TRUE if the nth element in a collection exists; otherwise returns FALSE.

COUNT
Returns the number of elements that a collection currently contains. COL.Count

LIMIT

Checks the Maximum Size of a Collection. COL.LIMIT


4

FIRST -- COL.LIMIT
Returns the first (smallest) index numbers in a collection that uses integer subscripts.

LAST COL.LAST
Returns the last (largest) index numbers in a collection that uses integer subscripts.

PRIOR(n)
Returns the index number that precedes index n in a collection.

NEXT(n)
Returns the index number that succeeds index n.

EXTEND
Appends one null element to a collection.

EXTEND(n)
Appends n null elements to a collection.

10

EXTEND(n,i)
Appends n copies of the ith element to a collection.

11

TRIM
Removes one element from the end of a collection.

12

TRIM(n)
Removes n elements from the end of a collection.

13

DELETE
Removes all elements from a collection, setting COUNT to 0.

14

DELETE(n)
Removes the nth element from an associative array with a numeric key or a nested table. If the
associative array has a string key, the element corresponding to the key value is deleted. If n is
null, DELETE(n) does nothing.

15

DELETE(m,n)
Removes all elements in the range m..n from an associative array or nested table. If m is larger
than n or if m or n is null, DELETE(m,n) does nothing.

Collection Exceptions
The following table provides the collection exceptions and when they are raised:
Collection Exception

Raised in Situations

COLLECTION_IS_NULL

You try to operate on an atomically null collection.

NO_DATA_FOUND

A subscript designates an element that was deleted, or a nonexistent


element of an associative array.

SUBSCRIPT_BEYOND_COUNT A subscript exceeds the number of elements in a collection.


SUBSCRIPT_OUTSIDE_LIMIT

A subscript is outside the allowed range.

VALUE_ERROR

A subscript is null or not convertible to the key type. This exception


might occur if the key is defined as a PLS_INTEGER range, and the
subscript is outside this range.

Using nested table in sql::


CREATEORREPLACETYPENESISTABLEOFVARCHAR2(100);
CREATETABLEnsetab(snoNUMBER(5),coltabnes)NESTEDTABLEcoltabSTOREAS
ntab

SELECT*FROMnsetab

INSERTINTOnsetabVALUES(1,NES('XYZ'))
INSERTINTOnsetabVALUES(2,NES('123'))
INSERTINTOnsetabVALUES(3,NES('XYZ','123','456'))
SELECT*FROMnsetab

Output::

If we double click on data set we will get the below detals

Collections are composite data types which are used to store the
complex data. These are three types.
1) Nested table
2) varrays
Both are user defined datatypes which are using in sql as well
as Pl/sql also.
3)Index by table(It is temperory data type, it works only on pl/sql)
4) Pl/sql Record

NESTED TABLE Ex1::


Syntax:: type type_name is table of datatype;
We have many functions like ::
type.count, type.first, type.last, type.prior(2), type.next(3),
type.extend, type.exted(2), type.exten(3,4), type.exists(3), type.trim,
type.trim(2), type.delete, , type.limit
DECLARE
TYPEnesISTABLEOFVARCHAR2(20);
vnesnes:=nes('A','B','C','D');
BEGIN
DBMS_OUTPUT.put_line('VNESCOUNTIS::'||vnes.COUNT);
IFvnes.COUNTISNOTNULL
THEN
DBMS_OUTPUT.put_line('VNESLIMITIS::'||vnes.LIMIT);
ENDIF;
DBMS_OUTPUT.put_line('VNESFIRSTIS::'||vnes.FIRST);
DBMS_OUTPUT.put_line('VNESLASTIS::'||vnes.LAST);
DBMS_OUTPUT.put_line('VNESPRIORIS::'||vnes.PRIOR(2));

DBMS_OUTPUT.put_line('VNESNEXTIS::'||vnes.NEXT(3));
DBMS_OUTPUT.put_line('VNESVALUES');
FORiINvnes.FIRST..vnes.LAST
LOOP
DBMS_OUTPUT.put_line('VNESVALUES('||i||')'||vnes(i));
ENDLOOP;
vnes.EXTEND;
vnes.EXTEND(2);
DBMS_OUTPUT.put_line('VNESVALUESAFTEREXTENSION');
FORiINvnes.FIRST..vnes.LAST
LOOP
DBMS_OUTPUT.put_line('VNESAFTEREXTENSIONVALUES('
||i
||')'
||vnes(i)
);
ENDLOOP;
vnes(5):='E';
vnes(6):='f';
vnes(7):='g';
vnes.EXTEND(10,2);
DBMS_OUTPUT.put_line('VNESVALUESAFTERPROVIDING');
FORiINvnes.FIRST..vnes.LAST
LOOP
DBMS_OUTPUT.put_line('VNESVALUESAFTERPROVIDING('
||i
||')'
||vnes(i)
);
ENDLOOP;
IFvnes.EXISTS(3)
THEN
DBMS_OUTPUT.put_line('VNES3RDINDEXVALUES>'||vnes(3));
ELSE
NULL;
ENDIF;
vnes.DELETE(1);
DBMS_OUTPUT.put_line('VNESAFTERDELETIONOFINDEX');
FORiINvnes.FIRST..vnes.LAST
LOOP
DBMS_OUTPUT.put_line('VNESVALUESAFTERDELETINGTHEINDEX('
||i
||')'
||vnes(i)
);
ENDLOOP;
vnes.DELETE(2,4);
DBMS_OUTPUT.put_line('AFTERRANGEDELETION');

FORiINvnes.FIRST..vnes.LAST
LOOP
DBMS_OUTPUT.put_line('AFTERRANGEDELETIONVALUESOFVNES('
||i
||')'
||vnes(i)
);
ENDLOOP;
vnes.TRIM;
vnes.TRIM(2);
DBMS_OUTPUT.put_line('AFTERRANGETRIM');
FORiINvnes.FIRST..vnes.LAST
LOOP
DBMS_OUTPUT.put_line('AFTERTRIMVALUESOFVNES('||i||')'
||vnes(i)
);
ENDLOOP;
vnes.DELETE;
DBMS_OUTPUT.put_line('AFTERCOMPLATIONOFDELETEVNES');
('||I||')'||
VNES(I));
FORiINvnes.FIRST..vnes.LAST
LOOP
DBMS_OUTPUT.put_line('AFTERTRIMVALUESOFVNES('||i||')'
||vnes(i)
);
ENDLOOP;
END;

O/P::
VNES COUNT IS::4
VNES LIMIT IS::
VNES FIRST IS::1 (If we give the argumnt as 1(vnes.first(1), it will give the NULL value as output))
VNES LAST IS::4 (If we give the argumnt as 4 i mean lastval(vnes.first(4), it will give the NULL value as output))
VNES PRIOR IS::1
VNES NEXT IS::4
VNES VALUES
VNES VALUES(1)A
VNES VALUES(2)B
VNES VALUES(3)C
VNES VALUES(4)D
VNES VALUES AFTER EXTENSION
VNES AFTER EXTENSION VALUES(1)A
VNES AFTER EXTENSION VALUES(2)B
VNES AFTER EXTENSION VALUES(3)C
VNES AFTER EXTENSION VALUES(4)D
VNES AFTER EXTENSION VALUES(5)
VNES AFTER EXTENSION VALUES(6)
VNES AFTER EXTENSION VALUES(7)
VNES VALUES AFTER PROVIDING
VNES VALUES AFTER PROVIDING(1)A
VNES VALUES AFTER PROVIDING(2)B
VNES VALUES AFTER PROVIDING(3)C
VNES VALUES AFTER PROVIDING(4)D
VNES VALUES AFTER PROVIDING(5)E
VNES VALUES AFTER PROVIDING(6)f
VNES VALUES AFTER PROVIDING(7)g
VNES VALUES AFTER PROVIDING(8)B

VNES VALUES AFTER PROVIDING(9)B


VNES VALUES AFTER PROVIDING(10)B
VNES VALUES AFTER PROVIDING(11)B
VNES VALUES AFTER PROVIDING(12)B
VNES VALUES AFTER PROVIDING(13)B
VNES VALUES AFTER PROVIDING(14)B
VNES VALUES AFTER PROVIDING(15)B
VNES VALUES AFTER PROVIDING(16)B
VNES VALUES AFTER PROVIDING(17)B
VNES 3RD INDEX VALUES-->C
VNES AFTER DELETION OF INDEX
VNES VALUES AFTER DELETING THE INDEX(2)B (We can delete fist insedx directly, but we cn't delete the other
indexes directly)
VNES VALUES AFTER DELETING THE INDEX(3)C
VNES VALUES AFTER DELETING THE INDEX(4)D
VNES VALUES AFTER DELETING THE INDEX(5)E
VNES VALUES AFTER DELETING THE INDEX(6)f
VNES VALUES AFTER DELETING THE INDEX(7)g
VNES VALUES AFTER DELETING THE INDEX(8)B
VNES VALUES AFTER DELETING THE INDEX(9)B
VNES VALUES AFTER DELETING THE INDEX(10)B
VNES VALUES AFTER DELETING THE INDEX(11)B
VNES VALUES AFTER DELETING THE INDEX(12)B
VNES VALUES AFTER DELETING THE INDEX(13)B
VNES VALUES AFTER DELETING THE INDEX(14)B
VNES VALUES AFTER DELETING THE INDEX(15)B
VNES VALUES AFTER DELETING THE INDEX(16)B
VNES VALUES AFTER DELETING THE INDEX(17)B
AFTER RANGE DELETION
AFTER RANGE DELETION VALUES OF VNES(5)E
AFTER RANGE DELETION VALUES OF VNES(6)f
AFTER RANGE DELETION VALUES OF VNES(7)g
AFTER RANGE DELETION VALUES OF VNES(8)B
AFTER RANGE DELETION VALUES OF VNES(9)B
AFTER RANGE DELETION VALUES OF VNES(10)B
AFTER RANGE DELETION VALUES OF VNES(11)B
AFTER RANGE DELETION VALUES OF VNES(12)B
AFTER RANGE DELETION VALUES OF VNES(13)B
AFTER RANGE DELETION VALUES OF VNES(14)B
AFTER RANGE DELETION VALUES OF VNES(15)B
AFTER RANGE DELETION VALUES OF VNES(16)B
AFTER RANGE DELETION VALUES OF VNES(17)B
AFTER RANGE TRIM
AFTER TRIM VALUES OF VNES(5)E
AFTER TRIM VALUES OF VNES(6)f
AFTER TRIM VALUES OF VNES(7)g
AFTER TRIM VALUES OF VNES(8)B
AFTER TRIM VALUES OF VNES(9)B
AFTER TRIM VALUES OF VNES(10)B
AFTER TRIM VALUES OF VNES(11)B
AFTER TRIM VALUES OF VNES(12)B
AFTER TRIM VALUES OF VNES(13)B
AFTER TRIM VALUES OF VNES(14)B
AFTER COMPLATION OF DELETE VNES (If we write a for loop to print the values after delete the
type we will get an error message that NUMARIC VALUE ERROR)

USING NESTED TABLE IN SQL::


Creating type::
CREATEORREPLACETYPENESISTABLEOFVARCHAR2(100);

Creating table by using type::


CREATETABLEnsetab(snoNUMBER(5),coltabnes)NESTEDTABLEcoltabSTOREAS
ntab

INSERTING the values into the table

INSERTINTOnsetabVALUES(1,NES('XYZ'))
INSERTINTOnsetabVALUES(2,NES('123))'
INSERTINTOnsetabVALUES(3,NES('XYZ','123','456'))
SELECT*FROMnsetab
NOTE:Ifyouwritetheselectquerylike
select*fromntab
wewillgetanerrormessagethat
ORA22812:cannotreferencenestedtablecolumn'sstoragetable

O/P::

If We double click on the data set value, you can see the actual value.
pleasse find the below.

VARRAYS::
NOTE: DELETE will not supports the arguments here.
DECLARE
TYPEnesISVARRAY(10)OFVARCHAR2(20);
vnesnes:=nes('A','B','C','D');
BEGIN
DBMS_OUTPUT.put_line('VNESCOUNTIS::'||vnes.COUNT);
IFvnes.COUNTISNOTNULL
THEN
DBMS_OUTPUT.put_line('VNESLIMITIS::'||vnes.LIMIT);
ENDIF;
DBMS_OUTPUT.put_line('VNESFIRSTIS::'||vnes.FIRST);
DBMS_OUTPUT.put_line('VNESLASTIS::'||vnes.LAST);
DBMS_OUTPUT.put_line('VNESPRIORIS::'||vnes.PRIOR(2));
DBMS_OUTPUT.put_line('VNESNEXTIS::'||vnes.NEXT(3));
DBMS_OUTPUT.put_line('VNESVALUES');
FORiINvnes.FIRST..vnes.LAST
LOOP
DBMS_OUTPUT.put_line('VNESVALUES('||i||')'||vnes(i));
ENDLOOP;
vnes.EXTEND;
vnes.EXTEND(2);
DBMS_OUTPUT.put_line('VNESVALUESAFTEREXTENSION');
FORiINvnes.FIRST..vnes.LAST
LOOP
DBMS_OUTPUT.put_line('VNESAFTEREXTENSIONVALUES('
||i
||')'
||vnes(i)
);
ENDLOOP;

vnes(5):='E';
vnes(6):='f';
vnes(7):='g';
vnes.EXTEND(3,4);
DBMS_OUTPUT.put_line('VNESVALUESAFTERPROVIDING');
FORiINvnes.FIRST..vnes.LAST
LOOP
DBMS_OUTPUT.put_line('VNESVALUESAFTERPROVIDING('
||i
||')'
||vnes(i)
);
ENDLOOP;
IFvnes.EXISTS(3)
THEN
DBMS_OUTPUT.put_line('VNES3RDINDEXVALUES>'||vnes(3));
ELSE
NULL;
ENDIF;
vnes.TRIM;
vnes.TRIM(2);
DBMS_OUTPUT.put_line('AFTERRANGETRIM');
FORiINvnes.FIRST..vnes.LAST
LOOP
DBMS_OUTPUT.put_line('AFTERTRIMVALUESOFVNES('||i||')'
||vnes(i)
);
ENDLOOP;
vnes.DELETE;
DBMS_OUTPUT.put_line('AFTERDELETIONOFCOMPLETION');

END;

O/P::
VNES COUNT IS::4
VNES LIMIT IS::10
VNES FIRST IS::1
VNES LAST IS::4
VNES PRIOR IS::1
VNES NEXT IS::4
VNES VALUES
VNES VALUES(1)A
VNES VALUES(2)B
VNES VALUES(3)C
VNES VALUES(4)D
VNES VALUES AFTER EXTENSION
VNES AFTER EXTENSION VALUES(1)A
VNES AFTER EXTENSION VALUES(2)B
VNES AFTER EXTENSION VALUES(3)C
VNES AFTER EXTENSION VALUES(4)D
VNES AFTER EXTENSION VALUES(5)
VNES AFTER EXTENSION VALUES(6)
VNES AFTER EXTENSION VALUES(7)

VNES VALUES AFTER PROVIDING


VNES VALUES AFTER PROVIDING(1)A
VNES VALUES AFTER PROVIDING(2)B
VNES VALUES AFTER PROVIDING(3)C
VNES VALUES AFTER PROVIDING(4)D
VNES VALUES AFTER PROVIDING(5)E
VNES VALUES AFTER PROVIDING(6)f
VNES VALUES AFTER PROVIDING(7)g
VNES VALUES AFTER PROVIDING(8)D
VNES VALUES AFTER PROVIDING(9)D
VNES VALUES AFTER PROVIDING(10)D
VNES 3RD INDEX VALUES-->C
AFTER RANGE TRIM
AFTER TRIM VALUES OF VNES(1)A
AFTER TRIM VALUES OF VNES(2)B
AFTER TRIM VALUES OF VNES(3)C
AFTER TRIM VALUES OF VNES(4)D
AFTER TRIM VALUES OF VNES(5)E
AFTER TRIM VALUES OF VNES(6)f
AFTER TRIM VALUES OF VNES(7)g
AFTER DELETION OF COMPLETION

USING VARRAY IN SQL::


CREATEORREPLACETYPERAYISVARRAY(2)OFVARCHAR2(100);
CREATETABLERAYTAB(SNONUMBER(5),RCOLRAY);
INSERTINTORAYTABVALUES(1,RAY('X','y'))
INSERTINTORAYTABVALUES(1,RAY('X'))
INSERTINTORAYTABVALUES(1,RAY('X','U'))

SELECT*FROMRAYTAB
NOTE::ifweinsertmorethan2valuesitwillgiveanerrorlikebelow
INSERTINTORAYTABVALUES(1,RAY('X','U','Z'))
ORA22909:exceededmaximumVARRAYlimit
SELECT*FROMRAYTAB

O/P:

Index by table ::

DECLARE
TYPEnesISTABLEOFVARCHAR2(20)
INDEXBYBINARY_INTEGER;
vnesnes;
BEGIN
vnes(1):='A';
vnes(2):='B';
vnes(3):='C';
vnes(4):='D';
vnes(5):='E';
vnes(6):='G';

DBMS_OUTPUT.put_line('VNESCOUNT:'||vnes.COUNT);
IFvnes.LIMITISNOTNULL
THEN
DBMS_OUTPUT.put_line('VNESLIMITLESS');
ENDIF;
DBMS_OUTPUT.put_line('VNESFIRSTIS::'||vnes.FIRST);
DBMS_OUTPUT.put_line('VNESLASTIS::'||vnes.LAST);
DBMS_OUTPUT.put_line('VNESPRIORIS::'||vnes.PRIOR(2));
DBMS_OUTPUT.put_line('VNESNEXTIS::'||vnes.NEXT(3));
DBMS_OUTPUT.put_line('VNESVALUES');
FORiINvnes.FIRST..vnes.LAST
LOOP
DBMS_OUTPUT.put_line('VNESVALUES('||i||')'||vnes(i));
ENDLOOP;
IFvnes.EXISTS(3)
THEN
DBMS_OUTPUT.put_line('VNES3RDINDEXVALUES>'||vnes(3));
ELSE
NULL;
ENDIF;
vnes.DELETE(1);
DBMS_OUTPUT.put_line('VNESAFTERDELETIONOFINDEX');
FORiINvnes.FIRST..vnes.LAST
LOOP
DBMS_OUTPUT.put_line('VNESVALUESAFTERDELETINGTHEINDEX('
||i
||')'
||vnes(i)
);
ENDLOOP;
vnes.DELETE(2,4);
DBMS_OUTPUT.put_line('AFTERRANGEDELETION');
FORiINvnes.FIRST..vnes.LAST
LOOP
DBMS_OUTPUT.put_line('AFTERRANGEDELETIONVALUESOFVNES('
||i
||')'
||vnes(i)
);
ENDLOOP;
vnes.DELETE;
DBMS_OUTPUT.put_line('AFTERCOMPLATIONOFDELETEVNES');
END;

O/P::
VNES COUNT:6
VNES FIRST IS::1
VNES LAST IS::6
VNES PRIOR IS::1
VNES NEXT IS::4
VNES VALUES
VNES VALUES(1)A
VNES VALUES(2)B
VNES VALUES(3)C
VNES VALUES(4)D
VNES VALUES(5)E
VNES VALUES(6)G
VNES 3RD INDEX VALUES-->C
VNES AFTER DELETION OF INDEX
VNES VALUES AFTER DELETING THE INDEX(2)B
VNES VALUES AFTER DELETING THE INDEX(3)C
VNES VALUES AFTER DELETING THE INDEX(4)D
VNES VALUES AFTER DELETING THE INDEX(5)E
VNES VALUES AFTER DELETING THE INDEX(6)G
AFTER RANGE DELETION
AFTER RANGE DELETION VALUES OF VNES(5)E
AFTER RANGE DELETION VALUES OF VNES(6)G
AFTER COMPLATION OF DELETE VNES

NOTE::
1) Nested tables and varrays are not allowed character values only
index by will allow the CHARACTER values.
2) Nested tables and varrays are wont allow negetive values but index
by table will allow NEGETIVE values.
3) LIMIT will support only in VARRAYS, wn't allow in nested tables and
index by table.

TABLES regarding with collecctions::


USER_TYPES
USER_COLL_TYPES

FIRST
LAST
NEXT
PRIOR
COUN
T
EXIST
S
DELET
E
EXTEN
D
TRIM
LIMIT
KEY
COLU
MN
VALUE
S

NESTED TABLE
Y
Y
Y
Y

VARRAYS
Y
Y
Y
Y

INDEX BY
TABLE
Y
Y
Y
Y

Y
SPECIFC DELETION IS NOT
POSSIBLE
POSSIBLE WITH IN THE
LIMIT
Y
Y
SAME AS NESTED TABLE

Y
Y
Y
N
POSSITIVE
INTEGER
VALUES, ALWAYS
STRAT WITH 1,
WONT ALLOW
NEGEITIVE AND
CHARACTERS

Y
N
N
N
ALLOWS BOTH +
AND -, MUST
NOT BE AN
ORDER AND
EVEN ALLOWS
CHARACTERS
AND NULLS

Collections are composite data types which are used to store the
complex data. These are two types.
PLSQL RECORD::
Defined by user
Valid with in PL/SQL block only
It holds the list of elements of different data types
Similar to C stricture
Syntax::
TYPE <RECORD NAME > IS RECORD
( ELEMENT1 <DATATYPE>,
ELEMENT2 <DATATYPE>,
ELEMENTN <DATATYPE>
)

EX1:: WRITE A PLSQL PROGRAM TO DISPLAY THE EMPLOYEE


NAME,JOB,SAL,DEPTNO,DNAME AND GRROSS SALARY FOR ENTERED
EMPLOYEE NO.
DECLARE
WRITEAPLSQLPROGRAMTODISPLAYTHEEMPLOYEE
NAME,JOB,SAL,DEPTNO,DNAMEANDGRROSSSALARYFORENTEREDEMPLOYEENO.
TYPEemp_recISRECORD(
empnoNUMBER,
enameemp.ename%TYPE,
jobemp.job%TYPE,
salemp.sal%TYPE,
idept%ROWTYPE,
grossNUMBER
);
veemp_rec;
BEGIN
ve.empno:=&empno;
SELECTe.ename,e.job,e.sal,d.deptno,d.dname
INTOve.ename,ve.job,ve.sal,ve.i.deptno,ve.i.dname
FROMempe,deptd
WHEREe.empno=ve.empnoANDe.deptno=d.deptno;
ve.gross:=ve.sal+(ve.sal*.45)+(ve.sal*.35)(ve.sal*.15);
DBMS_OUTPUT.put_line(ve.ename
||','
||ve.job
||','
||ve.sal
||','
||ve.i.dname
||','
||ve.gross
);
END;

O/P::

BLAKE , MANAGER , 2850,SALES,4702.5 ( entered emp no is 7698)

PLSQL TABLE:: It holds the list of elements of same datatype


syntax::
type <type Name> is table of <data type> index by binary_integer
it is syntatically C array.
Ex:: display the data into the given below format.
Eid

Name

Basic

pf
pfno

Pamt

7566 James

2975

1 Xxxx

DECLARE
TYPEpf_empISRECORD(
pfnoNUMBER,
pf_amtNUMBER
);
TYPEemp_recISRECORD(
eidNUMBER,
NAMEemp.ename%TYPE,
basicemp.sal%TYPE,
pfpf_emp
);
TYPEetabISTABLEOFemp_rec
INDEXBYBINARY_INTEGER;
l_etabetab;
cntNUMBER:=1;
BEGIN
FORemp_pf_detIN(SELECTempno,ename,sal,sal*0.15pf_amt
FROMemp
WHEREsal>2000)
LOOP
l_etab(cnt).eid:=emp_pf_det.empno;
l_etab(cnt).NAME:=emp_pf_det.ename;
l_etab(cnt).basic:=emp_pf_det.sal;
l_etab(cnt).pf.pfno:=emp_pf_det.empno+100;
l_etab(cnt).pf.pf_amt:=emp_pf_det.pf_amt;
DBMS_OUTPUT.put_line(l_etab(cnt).eid
||''
||l_etab(cnt).NAME
||''
||l_etab(cnt).basic
||''
||l_etab(cnt).pf.pfno
||''
||l_etab(cnt).pf.pf_amt
);
cnt:=cnt+1;
ENDLOOP;
DBMS_OUTPUT.put_line(cnt);
END;
DECLARE
TYPEpf_recISRECORD(
pfnoNUMBER(5),
pamtNUMBER(14,2)
);
TYPEemp_recISRECORD(
eidNUMBER(5),

NAMEVARCHAR2(50),
basicNUMBER(12,2),
pfpf_rec
);
TYPEetabISTABLEOFemp_rec
INDEXBYBINARY_INTEGER;
cntNUMBER(3):=1;
eetab;
BEGIN
FORiIN(SELECTempno,ename,sal,sal*.15pamt
FROMemp
WHEREsal>2000)
LOOP
e(cnt).eid:=i.empno;
e(cnt).NAME:=i.ename;
e(cnt).basic:=i.sal;
e(cnt).pf.pfno:=i.empno+5;
e(cnt).pf.pamt:=i.pamt;
cnt:=cnt+1;
ENDLOOP;
DBMS_OUTPUT.put_line('DISPLAYVALUES');
FORkIN1..e.COUNT
LOOP
DBMS_OUTPUT.put_line(e(k).eid
||','
||e(k).NAME
||','
||e(k).basic
||','
||e(k).pf.pfno
||','
||e(k).pf.pamt
);
ENDLOOP;
END;

O/P:
DISPLAY VALUES
7839,KING,5000,7844,750
7698,BLAKE,2850,7703,427.5
7782,CLARK,2450,7787,367.5
7566,JONES,2975,7571,446.25
7788,SCOTT,3000,7793,450
7902,FORD,3000,7907,450

Returning into clause(8.0)::

This feature is introduced in oracle 8.0 and we can use it in SQL aswell
as PL/SQl also.
It is used to return the updated and deleted data into a variable.
NOTE: We can't assign more than one value to a bind variable.
EX1::
VARVSAL1NUMBER;
VARVNAMEVARCHAR2(30);
UPDATEEMP1SETSAL=SAL+3000
WHEREEMPNP=7788
RETURNINGSAL,ENAMEINTO:VSAL1,:VNAME
PRINT:VNAME:VSAL1

BULK COLLECT AND BULK BIND::


It is a process which is used to increase the performance. it decreases
the the context switchs or minimise the interaction b/w sql/plsql engeen
or reduce the trafic.
Insted of N number of transactions it happens only with one interaction.
Bulk collect is a clause. We have to provide the bulk collect only in the
following stmts.
SYNTAX::
select column bulk collect into variable from tname;
fetch cursor bulk collect into variable;
return column name bulk collect into variable;(out binding)
NOTE:: Always we have to store the bulk collect data in a collections(I
mean collection variables)
BULK BINDING::
We perform bulk binding for DML operations
SYNTAX::
forall i in 1..100
insert/update/delete /merge statements/values of collections/indices of
collection;(IN BINDING)

BULK COLLECT Ex1 for find the time gap difference::

CREATETABLESAM(SNONUMBER(20))
BEGIN
FORIIN1..1000
LOOP
INSERTINTOSAMVALUES(I);
COMMIT;
ENDLOOP;
END;
SELECTCOUNT(*)FROMSAMO/P:1000

DECLARE
TYPEnesISTABLEOFNUMBER(20);
vnesnes:=nes();
xNUMBER(10):=0;
yNUMBER(10):=0;
zNUMBER(10):=0;
BEGIN
x:=DBMS_UTILITY.get_time;
FORiIN(SELECTsno
FROMsam)
LOOP
vnes.EXTEND;
vnes(vnes.LAST):=i.sno;
DBMS_OUTPUT.PUT_LINE('VNES.LAST'||VNES.LAST);
ENDLOOP;
y:=DBMS_UTILITY.get_time;
z:=yx;
DBMS_OUTPUT.put_line('WITHOUTBULKCOLLECT'||z);
x:=DBMS_UTILITY.get_time;
SELECTsno
BULKCOLLECTINTOvnes
FROMsam;
y:=DBMS_UTILITY.get_time;
z:=yx;
DBMS_OUTPUT.put_line('WITHBULKCOLLECT'||z);
END;

O/P::
WITH OUT BULK COLLECT3
WITH BULK COLLECT0

Bulk collect with SELECT statement

/*Formattedon2013/07/2704:04(FormatterPlusv4.8.8)*/
DECLARE
TYPENAMEISTABLEOFemp.ename%TYPE
INDEXBYBINARY_INTEGER;
TYPEpayISTABLEOFemp.sal%TYPE
INDEXBYBINARY_INTEGER;
nNAME;
ppay;
BEGIN
SELECTename,sal
BULKCOLLECTINTOn,p
FROMemp;
FORiIN1..n.COUNT
LOOP
DBMS_OUTPUT.put_line(RPAD(n(i),10)||','||p(i));
ENDLOOP;
END;

O/P::
KING
BLAKE
CLARK
JONES
SCOTT
FORD
SMITH
ALLEN
WARD
MARTIN
TURNER
ADAMS
JAMES
MILLER

,5000
,2850
,2450
,2975
,3000
,3000
,800
,1600
,1250
,1250
,1500
,1100
,950
,1300

Ex3:: Write a plsql program to remove 30th dept employees, if any


employee having his salary more than 1500, and insert the employee
name, sal into a trace table.

/*Formattedon2013/07/2704:33(FormatterPlusv4.8.8)*/
DECLARE
TYPEenameISTABLEOFemp.ename%TYPE
INDEXBYBINARY_INTEGER;
TYPEpayISTABLEOFemp.sal%TYPE
INDEXBYBINARY_INTEGER;
nename;
ppay;
BEGIN
DELETEFROMemp1
WHEREdeptno=30
RETURNINGename,sal
BULKCOLLECTINTOn,p;
FORxIN1..n.COUNT
LOOP
IFp(x)>1500
THEN
INSERTINTOTRACE
(empno,ename,sal
)
VALUES(ex1.NEXTVAL,n(x),p(x)
);
ENDIF;
ENDLOOP;
COMMIT;
END;

O/P:: select * from trace


EMPN
O
3
4

ENAM
E
BLAKE
ALLEN

JOB

MGR

HIREDA
TE

SAL
2850
1600

COMM

DEPTN
O

BULK COLLECT WITH CUROSR::


/*Formattedon2013/07/2704:43(FormatterPlusv4.8.8)*/
DECLARE
TYPENAMEISTABLEOFemp.ename%TYPE
INDEXBYBINARY_INTEGER;
TYPEpayISTABLEOFemp.sal%TYPE
INDEXBYBINARY_INTEGER;
nNAME;
ppay;
CURSORc1
IS

SELECTename,sal
FROMemp
WHEREdeptnoIN(10,20);
BEGIN
OPENc1;
FETCHc1
BULKCOLLECTINTOn,p;
FORiIN1..n.COUNT
LOOP
DBMS_OUTPUT.put_line(RPAD(n(i),10)||''||p(i));
ENDLOOP;
END;

O/P::
KING
CLARK
JONES
SCOTT
FORD
SMITH
ADAMS
MILLER

5000
2450
2975
3000
3000
800
1100
1300

BULK bind example::


The difference b/W for and forall
forall performance is more than for

DECLARE
TYPEnesISTABLEOFVARCHAR2(20)
INDEXBYBINARY_INTEGER;
nnes;
xNUMBER:=0;
yNUMBER:=0;
zNUMBER:=0;
BEGIN
SELECT*
BULKCOLLECTINTOn
FROMsam;
EXECUTEIMMEDIATE'TRUNCATETABLESAM';
x:=DBMS_UTILITY.get_time;
FORiINn.FIRST..n.LAST
LOOP
INSERTINTOsam1
VALUES(n(i));
ENDLOOP;
y:=DBMS_UTILITY.get_time;
z:=yx;

DBMS_OUTPUT.put_line(z);
EXECUTEIMMEDIATE'TRUNCATETABLESAM1';
x:=DBMS_UTILITY.get_time;
FORALLiINn.FIRST..n.LAST
INSERTINTOsam1
VALUES(n(i));
x:=DBMS_UTILITY.get_time;
z:=yx;
DBMS_OUTPUT.put_line(z);
END;

O/P::
14
-11

RETURNING CLAUSE USING::


/*Formattedon2013/07/2705:10(FormatterPlusv4.8.8)*/
DECLARE
TYPEnesISTABLEOFVARCHAR2(20)
INDEXBYBINARY_INTEGER;
nnes;
BEGIN
DELETEFROMsam1
RETURNINGsno
BULKCOLLECTINTOn;
DBMS_OUTPUT.put_line(n.COUNT);
END;

O/P:: 2000
INDICES OF/VALUES OF ::(10G)
1) INDICES OF COLLECTIONNAME
Refers the index values of the other collections
2)VALUES OF COLLECTIONNAME
Referes the element values of other collections
Ex:: VALUES OF COLLECTIONNAME
DECLARE
TYPEnesISTABLEOFVARCHAR2(20)
INDEXBYBINARY_INTEGER;
TYPEnes1ISTABLEOFBINARY_INTEGER
INDEXBYBINARY_INTEGER;
vnesnes;
vnes1nes1;
BEGIN
vnes(1):='A';
vnes(2):='B';

vnes(3):='C';
vnes(4):='D';
vnes1(1):=1;
vnes1(2):=3;
vnes1(3):=4;
FORALLiINVALUESOFvnes1
INSERTINTOnstab
VALUES(vnes(i));
COMMIT;
END;
DELETENSTAB

O/P::

select * from nstab

NAME
A
C
D
NOTE:: At declaration time if we use both are varchar2(20), we will get below
error
PLS-00667: Element type of associative array should be pls_integer or
binary_integer
EX:: INDICES OF COLLECTIONNAME::
DECLARE
TYPEnesISTABLEOFVARCHAR2(20)
INDEXBYBINARY_INTEGER;
TYPEnes1ISTABLEOFBINARY_INTEGER
INDEXBYBINARY_INTEGER;
vnesnes;
vnes1nes1;
BEGIN
vnes(1):='A';
vnes(2):='B';
vnes(3):='C';
vnes(4):='D';
vnes1(1):=1;
vnes1(2):=3;
vnes1(3):=4;
FORALLiININDICESOFvnes1
INSERTINTOnstab
VALUES(vnes(i));
COMMIT;
END;

O/P::
NAME

select * from nstab

A
B
C

DYNAMIC SQL
DQL/DRL, DML, TCL languages are possible in Pl/Sql but DDL and DCL
are not possible in Pl/Sql
to resolve this problem, we need dynamic sql.
In Pl/sql, we can't be execute DDL and DCL statements
statically/Directly but by using EXECUTE IMMEDIATE statemt we can run
the DDL and DCL statements in Pl/Sql block.

CREATING THE TABLE USING DYNAMIC SQL::


DECLARE
aVARCHAR2(200):='CREATETABLEDTAB3(SNONUMBER(5))';
bVARCHAR2(200):='DECLAREBEGININSERTINTODTAB3VALUES(1);END;';
BEGIN
EXECUTEIMMEDIATEa;
EXECUTEIMMEDIATEb;
END;

CREATING THE PROCEDURE USING DYNAMIC SQL::


DECLARE
aVARCHAR2(200):='CREATEPROCEDUREPCISBEGINNULL;END;';
BEGIN
EXECUTEIMMEDIATEa;
END;

DROPING THE TABLE AT RUNTIME USING EXECUTE IMMEDIATE::

CREATEORREPLACEPROCEDUREDROP_OBJ(XVARCHAR2)
IS
BEGIN
EXECUTEIMMEDIATE'DROPTABLE'||X;
END;

PRAGMA AUTONOMUS_TRANSACTION::
CREATEORREPLACEPROCEDUREAUTO
IS
PRAGMAAUTONOMUS_TRANSACTION;
BEGIN
INSERTINTOAUTOTABVALUES(10);
COMMIT;
END;
CREATEORREPLACEPROCEDUREPARENT
IS
BEGIN
INSERTINTOPAUTOTABVALUES(12);
AUTO;
END;

TRIGGERS
A set of pl/sql statements executed automatically whenever the
DML operations performed on a table.
It is a pl/Sql block like procedure and it is associated with
table/View.
Unlike procedure and function triggers fires automatically when
event occurs on a table.
Triggers are advanced of constraint

It is not called explicitly and it is executed implicitly when ever


EVENT/DML operations performed on a table.
It is also an database object.
TRIGGER TYPES::
We have 4 types of trigger types
1) DML Triggers( Performed on Table)
2) Instead of triggers(Performed On a Views)
3)DDL Triggers(Performed on a Schema)
4)DB Triggers(Performed on a DB)

1) DML Triggers( Performed on Table)


It has two types
a) Row level Triggers
b) Statement Level Triggers
SYNTAX:
CREATE OR REPLCAE TRIGGER <triggername>
BEFORE/AFTER dml <INSERT/UPDATE/DELETE>
[OF <COLUMN NAME>] ON <TABLE NAME>
[DISABLE/ENABLE /FOLLOWS triggername]
[FOR EACH ROW ]
[WHEN CONDITION]
[DECLARE LOCAL VARIABLES]
BEGIN
code
exception
END [TRIGGERNAME];

TRIGGER PARTS::
Trigger parts indicates when to activate the trigger.
there are two parts of a trigger::
1) Before 2) After.
Trigger timings::
Before statement Level
Before Row level
After statement level
Before statement level

TRIGGER EVENTS::
It specify the when trigger has to fire
1)

Insert/update/delete

TRIGGER LEVELS::
they are two levels of triggers
a) Row level :: In row level triggers, triggers will fire or
executes for each of the row in a table. This trigger can be used with
FOR EACH ROW
b) Statement Level :: In statement level trigger, trigger will
fire only once for an entire table or bunch of records. It is a default
level trigger.
TRIGGER CONDITION/RESTRICTION:: (By using WHEN clause)
It provides the restriction on execution of the trigger.
TRIGGER BODY::
It specify the action, trigger has to perform.
NOTE::
Trigger can't be duplicate trigger name

Trigger can be attached one table(We can't create trigger on


multiple tables)
If when condition is true, the trigger will be executed otherwise
not executed by the WHEN condition.
TRIGGER QUALIFIERS:: There are two types of qualifiers
There are refers to the values available in the DML statements.
NOTE:: Valid in the ROW LEVEL trigger only.
EVENE
TS
INSER
T
UPDA
TE
DELET
E

NEW

OLD

EX1:: insert into dept values (50,SW,'xcxv');


:NEW.(columnname)
:OLD.( columnname)
:NEW.dname

:NEW.location

KINDS OF TRIGGERS::
there are two types
1) application triggers :: It is fired when the DML events
occur with in the application Ex:: Oracle forms
2) Databse Level triggers:: It is fired when the DML event
occuer on a table/View, no matter which user is connected.
USEAS OF TRIGGERS::
Prevent invalid transactions
Enforce complex security authorization
Enforce Referential Integrity.
COMPONENTS OF A TRIGGER:: Trigger Event+ Trigger restriction+
trigger parts+ Trigger action
NOTE:: We can create maxmum 12 triggers on a table
ROWLEVEL::
AFTER INSERT
AFTER UPDATE
AFTER DELETE

TABLE LEVL::
AFTER INSERT

BEFORE INSERT
BEFORE UPDATE
BEFIRE DELETE

BEFORE INSERT

AFTER UPDATE
AFTER DELETE

BEFORE UPDATE
BEFIRE DELETE

STATEMENT LEVEL TRIGGER EX::


WRITE A TRIGGER NOT TO ALLOW ANY DML OPERATIONS ON WEEK END
TO PARTICULAR TABLE
CREATEORREPLACETRIGGERSTTRIG
BEFOREINSERTONSAM
BEGIN
IFTO_CHAR(SYSDATE,'DY')IN('SAT','SUN')THEN
RAISE_APPLICATION_ERROR(20111,'WONTALLOWWEEKENDS');
ELSE
NULL;
ENDIF;
ENDSTTRIG;

If you insert the record on sat and sunady we will get the below error
message.
INSERTINTOSAMVALUES(1);
ORA20111:WONTALLOWWEEKENDS
ORA06512:at"APPS.STTRIG",line4
ORA04088:errorduringexecutionoftrigger'APPS.STTRIG'

ROW LEVEL TRIGGER EX::


For each of the row it will execute
pseudo record :: 1) Old 2) New
NOTE::
We have pseudo columns only in ROWLEVEL trigger, Show an error, if we
used in statement level trigger.
When condition is applicable only for row level triggers, show an error, if
we used in statement level trigger.
In WHEN clause if the condition is true, trigger perform the action else it
simply skips the trigger action. but DML statements takes place.
EX::
CREATEORREPLACETRIGGERTRIG_SAL_INC

BEFOREUPDATEONEMP1
FOREACHROW
BEGIN
IF:OLD.SAL>:NEW.SALTHEN
RAISE_APPLICATION_ERROR(20013,'SALCONTBEDECREASE');
ELSE
DBMS_OUTPUT.PUT_LINE('HELLO');

ENDIF;
ENDTRIG_SAL_INC;

UPDATEEMP1SETSAL=4500
WHEREEMPNO=7839

ORA20013:SALCONTBEDECREASE
ORA06512:at"APPS.TRIG_SAL_INC",line4
ORA04088:errorduringexecutionoftrigger'APPS.TRIG_SAL_INC'

WHEN CONDTION EXAMPLE::


CREATEORREPLACETRIGGERWHEN_TRIG
BEFOREUPDATEORINSERTONSAM
FOREACHROW
WHEN(TO_CHAR(SYSDATE,'HH24')BETWEEN10AND17)
BEGIN
IF:OLD.SNO>:NEW.SNOTHEN
DBMS_OUTPUT.PUT_LINE('HELLO');
ELSE
DBMS_OUTPUT.PUT_LINE('WELCOME');

ENDIF;
ENDWHEN_TRIG;

ENABLE and DISABLE the TRIGGERS:: (before 11g)


alter trigger trigger_name enable/disable;
DEFINING a Disabled trigger:: (11G)
When we create the disable trigger we will get the message like invalid
trigger name

CREATEORREPLACETRIGGERINS_TY
BEFOREUPDATEORINSERTONSAMDISABLE
BEGIN
DBMS_OUTPUT.PUT_LINE('cccccccc');
END;

11G FEATURES:: We can drop the unused columns by using this queries.
ALTERTABLEEMP1SETUNUSEDCOLUMNSAL;
ALTERTABLEEMP1DROPUNUSEDSAL;
ALTERTABLEEMP1READONLY;

NOTE:: If you run the above queries in before 11G version we will get
the error message below like
ORA00054:resourcebusyandacquirewithNOWAITspecifiedortimeout
expired

COMPOUND TRIGGER:: In Compound triggers we place the releated logic


and coding at one place for debugging and for modifications.
FOLLOWS:: (11G) http://www.oracle-base.com/articles/11g/triggerenhancements-11gr1.php
FOLLOWS guarantee the order of trigger execution
Prior to 11G there is guarantee for the order of the trigger
execution.
CREATEORREPLACETRIGGERTRIG1
BEFOREINSERTORUPDATEONSAM
BEGIN
DBMS_OUTPUT.PUT_LINE('xxxxxx');
ENDTRIG1;

CREATEORREPLACETRIGGERTRIG2
BEFOREINSERTORUPDATEONSAMFOLLOWSTRIG1
BEGIN
DBMS_OUTPUT.PUT_LINE('xxxxxxTRIG1');
ENDTRIG2;

INSTED OF TRIGGERS::(8i)
By using instead of trigger we can create a trigger on a view.

It is used to manipulate the data through join views


Instead of trigger is always row level trigger.
It will show an error when we using the on table or use it for table.
SYNTAX::
CREATE OR REPLACE TRIGGER triggername
INSTED OF INSERT/UPDATE/DELETE ON viewname
[FOR EACH ROW]
BEGIN
code;
END triggername;

Ex1::
CREATETABLETAB1(SNONUMBER(5),LOCATIONVARCHAR2(20));
CREATETABLETAB2(idNUMBER(5),NAMEVARCHAR2(20));
CREATEVIEWCOMVIEWASSELECTT1.SNO,T2.ID,T2.NAMEFROMTAB1T1,TAB2T2
INSERTINTOCOMVIEWVALUES(20,200,'YYY')

If we insert the above values into this view we will get the below error
message
ORA01779:cannotmodifyacolumnwhichmapstoanonkeypreserved
table

So to evolve this issue we have to use INSTEAD OF TRIGGER.


CREATEORREPLACETRIGGERinstrig
INSTEADOFINSERT
ONcomview
FOREACHROW
BEGIN
INSERTINTOtab1
(sno
)
VALUES(:NEW.sno
);
INSERTINTOtab2
(ID,NAME
)

VALUES(:NEW.ID,:NEW.NAME
);
ENDinstrig;

Now try to insert the query:


INSERTINTOCOMVIEWVALUES(10,100,'XXX')
INSERTINTOCOMVIEWVALUES(20,200,'YYY')

O/P::
SELECT*FROMCOMVIEW

SNO
10
20
10
20

ID
100
100
200
200

NAME
xxx
xxx
YYY
YYY

SELECT*FROMTAB1

SNO
10
20

LOCATION

SELECT*FROMTAB2

ID
100
200

NAME
Xxx
YYY

DELETING THE VALUES FROM COMPLEX VIEW::


CREATEORREPLACETRIGGERINSTRIG1
INSTEADOFDELETEONCOMVIEW
FOREACHROW
BEGIN
DELETEFROMCOMVIEWWHERESNO=:OLD.SNO;
ENDINSTRIG1;

When we are executing the below query we will get the below error
message.
DELETEFROMCOMVIEWWHERESNO=10

ORA00036:maximumnumberofrecursiveSQLlevels(50)exceeded

DDL TRIGGERS::
The only difference b/w DML and DDL triggers are firing the
event.
We will use the DDL triggers to enforce the rules or audit creation
of data base object.
It works on schemas.
NOTE:: We will use the DDL triggers mainly for auditing purpose.
SYNTAX::
CREATE OR REPLACE TRIGGER triggername
BEFORE/AFTER DDL COMMANDS ON SCHEMA
BEGIN
code;
END triggername;
DDL TRIGGER EVENTS/ATTRIBUTES::
1) ORA_SYS EVEN;
It will capture the event name (CAREATE, DROP, ALTER...)
2) ORA_DICT_OBJ_NAME;
It will capture the name of the object
3) ORA_DICT_OBJ_TYPE;
It will specify the type of the object(TABLE, PROCEDURE,
FUNCTION, VIEWS...)
Ex1::
CREATETABLEaudit_creation(
audit_creation_idNUMBER(10)CONSTRAINTpmkeyPRIMARYKEY,
audit_owaner_nameVARCHAR2(100)CONSTRAINTnn_oNOTNULL,
audit_obj_nameVARCHAR2(100)CONSTRAINTnn_nNOTNULL,
audit_dateDATECONSTRAINTnnNOTNULL
);
CREATESEQUENCEAUDIT_CREATION_SEQ

CREATEORREPLACETRIGGERaudit_creationt
BEFORECREATEONSCHEMA
BEGIN
INSERTINTOaudit_creation
VALUES(audit_creation_seq.NEXTVAL,ora_dict_obj_name,
ora_dict_obj_type,SYSDATE);
ENDaudit_creationt;
CREATETABLEVVV(SNONUMBER(10))
CREATETABLEVVV1(SNONUMBER(10))

SELECT*FROMAUDIT_CREATION

AUDIT_CREATIO
N_ID

AUDIT_OWANER_
NAME

AUDIT_OBJ_N
AME

1 VVV

TABLE

2 VVV1

TABLE

AUDIT_DATE
7/28/2013
8:30:34 AM
7/28/2013
8:31:53 AM

MUTATING TRIGGERS::
In oracle it is not possible(easy) to identify the things which are
under going changes.(mutation)
If trigger is raised by table which is under going same changes
MUTATIONS occur in such cases.
The table raise the trigger which is being used in the same trigger
body in such cases we have an error called "MUTATING ERROR" and that
trigger is called "MUTATING TRIGGER" and that table is called
"MUTATING TABLE"
NOTE: Mutating error will happen only in ROW LEVEL TRIGGERS
TO avoid the MUTATING errors we use PRAGMA AUTONUMS
TRANSACTIONS, Statement level triggers.
Ex1::
CREATEORREPLACETRIGGERmuttg
BEFOREUPDATE
ONtab2
FOREACHROW
BEGIN
UPDATEtab2
SETNAME='BNBN'
WHEREID=100;
END;

UPDATETAB2SETNAME='VNVN'WHEREID=100;

If we execute the above code we will get the below error meassage.
ORA04091:tableAPPS.TAB2ismutating,trigger/functionmaynotseeit

ELEMENATING MUTATING ERROR::


CREATEORREPLACETRIGGERMUT1TRG
BEFOREUPDATEONTAB2
FOREACHROW
DECLARE
PRAGMAAUTONOMUS_TRANSACTION;

BEGIN

UPDATETAB2SETNAME='VNVN'WHEREID=100;
COMMIT;
END;

EXPLAN PLAN
Explain Plan:: When you fire an SQL query to Oracle, Oracle database internally
creates a query execution plan in order to fetch the desired data from the tables.
The query execution plan is nothing but a set of methods on how the database
will access the data from the tables.
We have different execution plans like CBO(Cost based optimizer),
RBO(Root Based Optimizer)
There are two different optimizer options Rule based (RBO) and Cost based (CBO) Optimizer. For
Oracle 10g, CBO is the default optimizer. Cost Based optimizer enforces Oracle to generate the
optimization plan by taking all the related table statistics into consideration. On the other hand,
RBO uses a fixed set of pre-defined rules to generate the query plan. Obviously such fixed set of
rules may not always be able to create the plan that is most efficient in nature. This is because an
efficient plan will depend heavily on the nature and volume of tables data. Because of this reason,
CBO is preferred over RBO.
Analyze table product compute statistics;
1)
2)
3)
4)
5)

TABLE
INEDX
TABLE
INDEX
INDEX

ACCESS FULL/ FULL TABLE SCAN


UNIQUE SCAN
ACCESS BY INDEX ROWID
RANGE SCAN
FAST FULL SCAN

ANALIZE the table::


Oracle Full Table Scan(FTS)::
Lets start by creating a simple product table with the following structure.

CREATE TABLE product (ID NUMBER(10),


NAME VARCHAR2(100),
description VARCHAR2(255),
service VARCHAR2(30),
part_num VARCHAR2(50),
load_date DATE)
Next I will insert 15,000 records into this newly created table
BEGIN
FOR I IN 1..15000
LOOP
INSERT INTO product VALUES(I,'RAMESH','RAMESH123', 'SSS','1232242',
SYSDATE);
END LOOP;
COMMIT;
END;
Remember, currently there is no index on the table.
So Now we start our journey by writing a simple select statement on this table as
below.
EXPLAIN PLAN FOR SELECT * FROM product;
SELECT *
FROM TABLE (DBMS_XPLAN.display);

The point to note here is, Oracle is reading the whole table (denoted by TABLE
ACCESS FULL) which is very obvious because the select * statement that is being
fired is trying to read everything. So, theres nothing interesting up to this point.
INEDX UNIQUE SCAN::
Now lets add a WHERE clause in the query and also create some additional
indexes on the table.
CREATE UNIQUE INDEX idx_prod_id_1 ON product (ID)
EXPLAIN PLAN FOR SELECT ID FROM PRODUCT WHERE ID='100'
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY)

So the above statement indicates that CBO is performing Index Unique Scan.
This means, in order to fetch the id value as requested, Oracle is actually reading
the index only and not the whole table. Of course this will be faster than FULL
TABLE ACCESS operation shown earlier.
TABLE ACCESS BY INDEX ROWID::
EXPLAIN PLAN FOR SELECT * FROM PRODUCT WHERE ID=100
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY)

INDEX RANGE SCAN::


If we specify a >, or between criteria in the WERE clause instead of equality
condition? Like below.
EXPLAIN PLAN FOR SELECT * FROM PRODUCT WHERE ID<10;
SELECT * FROM TABLE (DBMS_XPLAN.DISPLAY);

INDEX FAST FULL SCAN::


EXPLAIN PLAN FOR SELECT ID FROM PRODUCT WHERE ID>10
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

How Can we find the number of active users in oracle database::


select * from DBA_USERS WHERE ACCOUNT_STATUS='OPEN'

Active Sessions/users::
select*fromgv$sessionwherestatus='ACTIVE';

Column to rows conversion:: we can by using decode,


sys_connect_by_path,
pivot(
in11g),LISTAGG(exp,,)
within
group(order by exp)(11g)
Wm_concat(In 9i onwards), listagg(In 11g)
Ex:: DECODE
SELECTMAX(DECODE(x,1,ename)),MAX(DECODE(x,2,ename)),
MAX(DECODE(x,3,ename))
FROM(SELECTename,ROWNUMx
FROMemp)

WM_CONCAT(column)::
SELECTwm_concat(ename)
FROMemp

LISTAGG::
SELECT LISTAGG(product_name, ', ') WITHIN GROUP (ORDER BY product_name DESC)
"Product_Listing"
FROM products;

PIVOT SYNTAX::
Mainselectquery
PIVOT(<AggregateFunction>(expression)[AS<alias>]
FOR(<ColumnList>)
in<subquery>)

Collections:: We can retrieve the data fastly at runtime.


Why fast:: every collection creates with an index, this is the
reason data reterving fast.

http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/composi
tes.htm#LNPLS00501

Multi Dimensional varrays/Collections::


DECLARE
XTYPEt1ISVARRAY(10)OFINTEGER;varrayofinteger

vat1:=t1(22,3,5);
TYPEnt1ISVARRAY(10)OFt1;varrayofvarrayofinteger

nvant1:=nt1(va,t1(55,6,73),t1(2,4),va);
iINTEGER;
va1t1;
BEGIN
i:=nva(2)(3);

DBMS_OUTPUT.PUT_LINE('i='||i);
i:=nva(1)(1);
DBMS_OUTPUT.PUT_LINE('i='||i);
nva.EXTEND;
nva(5):=t1(56,32);replaceinnervarrayelements
nva(4):=t1(45,43,67,43345);replaceaninnerintegerelement
nva(4)(4):=1;replace43345with1
nva(4).EXTEND;addelementto4thvarrayelement
nva(4)(5):=89;storeinteger89there
END;
/

External Tables

By using external table we can read the flat-files (Stored on OS) data using
SQl . They have been introduced in oracle 9i version as an alternative to
SQL* Loader. External tables are essentially stored SQL loader control files.
but because they are defined as tables, we can access our flat-file data
using all available read-only SQL and PL/SQL operations. We can also read
flat-files in parallel and join files to other files or tables, views and so on.
CREATING AN EXTRENAL TABLE::
We will begin by creating a simple external table that mimics the EMP
table. Before we can create the table, however, we require an Oracle
directory. A directory (also new in 9i) is an Oracle object that "points" to a
filesystem location where our source flat-files are stored (as an aside, note
that directory objects can also be used to replace utl_file_dir in UTL_FILE
read-write operations). In the following example, we will create a directory
named XT_DIR.
SQL> CREATE DIRECTORY xt_dir AS 'd:\oracle\dir';
Directory created

Note that to create a directory, we require the CREATE ANY DIRECTORY system privilege. Directories are
system-wide, so if we cannot get the privilege, a DBA can create the directory and grant READ or WRITE to our
users as required (READ for external table users and READ/WRITE as appropriate for UTL_FILE users).

CREATETABLEemp_xt
(empnoNUMBER(4)
,enameVARCHAR2(10)
,jobVARCHAR2(9)
,mgrNUMBER(4)
,hiredateDATE
,salNUMBER(7,2)
,commNUMBER(7,2)
,deptnoNUMBER(2)
)
ORGANIZATIONEXTERNAL
(
TYPEORACLE_LOADER
DEFAULTDIRECTORYxt_dir
ACCESSPARAMETERS
(
RECORDSDELIMITEDbyNEWLINE
BADFILE'emp_xt.bad'

LOGFILE'emp_xt.log'
NODISCARDFILE
FIELDSTERMINATEDBY','
(empno
,ename
,job
,mgr
,hiredateCHAR(20)DATE_FORMATDATEMASK"DD/MM/YYYY"
,sal
,comm
,deptno
)
)
LOCATION('emp.dat')
)
REJECTLIMITUNLIMITED;

Table created.

NOTE::
ORGANIZATIONAL EXTERNAL ::

The ORGANIZATION EXTERNAL clause tells Oracle that

we are creating an external table

ORACLE_LOADER::

The ORACLE_LOADER driver is a new type that "powers" external tables;

DEFAULT DIRECTORY::

If we wish, we can set a DEFAULT DIRECTORY once for the entire table.

This states that, unless we tell Oracle otherwise, all files created or read as part of this table will reside in this named
directory. In most cases, we will wish to write log/bad/discardfiles to a logging directory and read our incoming data files
from a data directory. For simplicity, we have used a single XT_DIR in our examples for all files;

UTL FILES::
By using the UTL FILES we are printing the log
message to know the transactions results whether it is
Failed/Success.
To print the log files we have written one function the function
name is logmessage. This function will have the parameters like
P_FILE_NAME,
P_ERROR_CODE,
P_ERROR_MESSAGE,
P_MESG_STRING,
P_SITE_ID,

P_COMP_ID,
P_EBIZ_APPOWN_NO

Ex::
FUNCTIONlogmesg
(p_filename
p_errcode
p_errmesg
p_msg_string
p_site_id
p_comp_id
p_procname
p_process_type
null,
p_ebiz_user_no
RETURNnumberis

in
in
in
in
in
in
in
in

varchar2defaultnull,
trn_logtab.errcode%type,
trn_logtab.errmesg%type,
varchar2defaultnull,
trn_logtab.site_id%typedefaultnull,
trn_logtab.comp_id%typedefaultnull,
trn_logtab.procname%type,
trn_logtab.process_type%typedefault

in

trn_logtab.ebiz_user_no%type)

l_filename

varchar2(200);

l_in_file

UTL_FILE.file_type;

Begin
l_filename := p_filename;
l_date := to_char(sysdate, 'mmddyyyy');
l_filename
:=
l_date||'.log';

l_filename||'_'||to_char(p_ebiz_appown_no)||'_'||

l_in_file := UTL_FILE.fopen(g_dir_name, l_filename, 'a');


UTL_FILE.put_line(l_in_file,
l_pipe_buf_len(100)));

p_msg_string,

l_offset(1),

utl_file.fclose(l_in_file);
End;

SIZE OF BUFFER:
The maximum size for the buffer in any PUT_LINE procedure is 32767
Characters.
The maximum size for the buffer in any GET_LINE procedure is 32767
Characters.

EXCEPTIONS OF UTL_FILE

1.

UTL_FILE.INVALID_PATH:ThisExceptionOccursWhenPathSpecifiedis

Invalid.

2.

UTL_FILE.INVALID_FILEHANDLE:ThisExceptionOccursbecauseofInvalid

FileHandlerforexampleIusedfilehandlerinmyProcedurenamel_in_file

3.

UTL_FILE.INVALID_MODE:ModeofFileisInvalid.UTLhaveonlythree

modeRead(R),Write(W),Append(A)

4.

UTL_FILE.INVALID_OPERATION:Youreceivedanunhandled

UTL_FILE.INVALID_OPERATIONexception.Thefilecannotbecreatedbecauseof
permissionsingivendirectoryorwhenyouaretryingtowriteto
someoneelse'sfilewithouthavingProperpermissions.

5.

UTL_FILE.WRITE_ERROR:Writeerror.

6.

UTL_FILE.READ_ERROR:ReadError.

7.

UTL_FILE.INTERNAL_ERROR:InternalErrr.

COMMANDS OF UTL_FILE

UTL_FILE.FOPEN(ForopeningofFile)
UTL_FILE.Put_line(Write a line of text)
UTL_FILE.FCLOSE(ClosingtheFile)
UT_FILE.GET_LINE(For Reading File)

MODE OF UTL_FILE
1.

Read(R)For Reading the File From server.

2.

Write(W)For Writing the File.

3.

Append(A)For adding records in Exciting File.

SDLC::
SDLC stands for Software Development Life Cycle. SDLC is the process consisting of a series of planned
activities to develop the software products.
SDLC MODLES::

Waterfall Model
Iterative Model
Spiral Model
V-Model
Big Bang Model
Agile Model
RAD model

Waterfall Model design::


Waterfall approach was first SDLC Model to be used widely in Software Engineering to ensure
success of the project. In this the whole process of software development divided into separate phases. In this
model, the outcome of one phase acts as the input for the next phase sequentially.

Following is a diagrammatic representation of different phases of waterfall model.

Requirement Gathering and analysis: All possible requirements of the system to be


developed are captured in this phase and documented in a requirement specification doc.

System Design: The requirement specifications from first phase are studied in this phase

and system design is prepared. System Design helps in specifying hardware and system
requirements and also helps in defining overall system architecture.

Implementation: With inputs from system design, the system is first developed in small

programs called units, which are integrated in the next phase. Each unit is developed and tested for its
functionality which is referred to as Unit Testing.

Integration and Testing: All the units developed in the implementation phase are integrated

into a system after testing of each unit. Post integration the entire system is tested for any faults and
failures.

Deployment of system: Once the functional and non functional testing is done, the product
is deployed in the customer environment or released into the market.

Maintenance: There are some issues which come up in the client environment. To fix those
issues patches are released. Also to enhance the product some better versions are released.
Maintenance is done to deliver these changes in the customer environment.

SQL * LOADER::
SQL*Loader loads data from external files into tables of an Oracle
database

SQL*Loader takes as input a control file, which controls the behavior of


SQL*Loader, and one or more datafiles. Output of the SQL*Loader is an
Oracle database (where the data is loaded), a log file, a bad file, and
potentially a discard file.
I have worked many scenarios like::
Input File/Data File ::
This contains the data, which is need to be loaded to oracle data base
table.
Control File::
Control file controls the behavior of the sql loader. Means it tells, from
where the date file need to read and to where the data need be load.
Control files start with
LOAD DATA
INFILE /home/ramesh/employee.txt
INTO TABLE emp
FIELDS TERMINATED BY ,
(id,name,dept,sal)

SCENARIOS::
1.Basic Upload Example Using SQL*Loader
2. Inserting Additional Records(By using append)
3. Data inside the Control File using BEGINDATA
4. Date format and Different Delimiter
( id, name terminated by "$", dept terminated by "^", salary,
hiredon DATE "dd-mon-yyyy" )
5. Fixed Length Data Upload
( id position(1:3), name position(4:8), dept position(9:18), salary
position(19:22) )

7. Load data from multiple files(by using two 2 infile)


infile '/home/ramesh/employee.txt'
infile '/home/ramesh/newemployee.txt'

8. Load data to Multiple Tables(By using position)

9. Handling Bad (Rejected) Records(If data is invalid)


10. Load Specific Rows from a data file (By when condition)

10 Oracle SQLLDR Command Examples (Oracle SQL*Loader Tutorial)


by RAMESH NATARAJAN on JUNE 25, 2012

If you are using Oracle database, at some point you might have to deal
with uploading data to the tables from a text file.
This article provides 10 practical examples on how to upload data from a
flat file to Oracle tables.

Input data file for SQL*Loader


This is the input text file that contains the data that needs to be loaded
into an oracle table. Each and every records needs to be in a separate
line, and the column values should be delimited by some common
delimiter character. For some of the examples mentioned below, well use
the following employee.txt file to upload the data to the employee table.
$ cat employee.txt
100,Thomas,Sales,5000
200,Jason,Technology,5500
300,Mayla,Technology,7000
400,Nisha,Marketing,9500
500,Randy,Technology,6000

501,Ritu,Accounting,5400

SQL*Loader Control File


This contains the instructions to the sqlldr utility. This tells sqlldr the
location of the input file, the format of the input file, and other optional
meta data information required by the sqlldr to upload the data into oracle
tables.
$ cat example1.ctl
load data
infile '/home/ramesh/employee.txt'
into table employee
fields terminated by ","
( id, name, dept, salary )

The above control file indicates the following:

infile Indicates the location of the input data file


into table Indicates the table name where this data should be
inserted
fields terminated by Indicates the delimiter that is used in the
input file to separate the fields
( id, name, dept, salary ) Lists the name of the column names in
the table into which the data should be uploaded

1. Basic Upload Example Using SQL*Loader


First, create the employee table as shown below.
SQL> create table employee

(
id integer,
name varchar2(10),
dept varchar2(15),
salary integer,
hiredon date
)

Next create the control file that explains what needs to be upload and
where.
$ cat sqlldr-add-new.ctl
load data
infile '/home/ramesh/employee.txt'
into table employee
fields terminated by ","
( id, name, dept, salary )

Note: If you have the values inside the data file enclosed with double
quote, use this in your control file: fields terminated by , optionally
enclosed by

Note: If you dont have the table created, youll get the following error
message:
SQL*Loader-941: Error during describe of table EMPLOYEE
ORA-04043: object EMPLOYEE does not exist

You can pass the userid and password to the sqlldr command using any
one of the following format. As you see below, both of these will prompt
you for control file location, as it was not given in the command line.
$ sqlldr scott/tiger

(or)

$ sqlldr userid=scott/tiger
control =
SQL*Loader-287: No control file name specified.

Execute the sqlldr command to upload these new record to the empty
table by specifying both uid/pwd and the control file location as shown
below.
$ sqlldr scott/tiger control=/home/ramesh/sqlldr-add-new.ctl
SQLLDR ebiznet@ebizxprs control= C:/lldr/ex1.ctl
Commit point reached - logical record count 5

Verify the the records are created in the database


SQL> select * from employee;

ID NAME

DEPT

SALARY HIREDON

---------- ---------- --------------- ---------- ------100 Thomas

Sales

5000

200 Jason

Technology

5500

300 Mayla

Technology

7000

400 Nisha

Marketing

500 Randy

Technology

9500
6000

This will create the output log file in the same name as the data file, but
with the .log extension (instead of .ctl). Partial output shown below.
$ cat sqlldr-add-new.log

Control File: /home/ramesh/sqlldr-add-new.ctl


Data File:

/home/ramesh/employee.txt

Table EMPLOYEE:

5 Rows successfully loaded.


0 Rows not loaded due to data errors.
0 Rows not loaded because all WHEN clauses were failed.
0 Rows not loaded because all fields were null.

Elapsed time was:


CPU time was:

00:00:00.04
00:00:00.00

2. Inserting Additional Records


Let us say you want to add two new employees to the employee table
from the following newemployee.txt file.
$ vi newemployee.txt
600,Ritu,Accounting,5400
700,Jessica,Marketing,7800

If you create a similar control file like the previous example, you might get
the following error message.
$ sqlldr scott/tiger control=/home/ramesh/sqlldr-add-more.ctl
SQL*Loader-601: For INSERT option, table must be empty. Error on table
EMPLOYEE

The above indicates that the table should be empty before you can upload
data using sql*loader.
If you like to insert more data to the tables without having to delete the
existing rows, use the append command as shown in the following
control file.
$ vi sqlldr-append-more.ctl
load data
infile '/home/ramesh/newemployee.txt'
append
into table employee
fields terminated by ","
( id, name, dept, salary )

Now, if you do sqlldr this will append the data.


$ sqlldr scott/tiger control=/home/ramesh/sqlldr-append-more.ctl
Commit point reached - logical record count 2

Verify that the records are appended successfully


SQL> select * from employee;

ID NAME

DEPT

SALARY HIREDON

---------- ---------- --------------- ---------- ------100 Thomas

Sales

5000

200 Jason

Technology

5500

300 Mayla

Technology

7000

400 Nisha

Marketing

500 Randy
600 Ritu
700 Jessica

Technology

9500
6000

Accounting

5400

Marketing

7800

3. Data inside the Control File using BEGINDATA


You can also specify the data directly inside the control file itself using
BEGINDATA keyword. i.e Anything that comes after BEGINDATA will be
treated as data to be uploaded to the table as shown below.
$ cat sqlldr-add-new-with-data.ctl
load data
infile *
into table employee
fields terminated by ","
( id, name, dept, salary )

begindata
100,Thomas,Sales,5000
200,Jason,Technology,5500
300,Mayla,Technology,7000
400,Nisha,Marketing,9500
500,Randy,Technology,6000

Note: The infile will say * in this case, as there is no input data file name
for this example.
Execute sqlldr to upload the data from the control file.
$ sqlldr scott/tiger control=/home/ramesh/sqlldr-add-new-with-data.ctl

4. Date format and Different Delimiter


This example shows how to specify a date format in the control file and
how to handle different delimiters in a data file
The following example has different delimiters ($ after name, ^ after
department).
$ cat employee-date.txt
100,Thomas$Sales^5000,31-JAN-2008
200,Jason$Technology^5500,01-Feb-2005
300,Mayla$Technology^7000,10-Aug-2000

400,Nisha$Marketing^9500,12-Dec-2011
500,Randy$Technology^6000,01-JAN-2007

Create the following control file and indicate the field delimiters for each
and every field using terminated by as shown below.
$ cat sqlldr-date.ctl
load data
infile '/home/ramesh/employee-date.txt'
into table employee
fields terminated by ","
( id, name terminated by "$", dept terminated by "^", salary, hiredon
DATE "dd-mon-yyyy" )

Load the data using sqlldr as shown below.


$ sqlldr scott/tiger control=/home/ramesh/sqlldr-date.ctl

Verify that the data got loaded properly as shown below.


SQL> select * from employee;

ID NAME

DEPT

SALARY HIREDON

---------- ---------- --------------- ---------- ---------

100 Thomas

Sales

5000 31-JAN-08

200 Jason

Technology

5500 01-FEB-05

300 Mayla

Technology

7000 10-AUG-00

400 Nisha

Marketing

500 Randy

Technology

9500 12-DEC-11
6000 01-JAN-07

5. Fixed Length Data Upload


If you have a data file without data that are fixed length (i.e without any
delimiter), you can use this example to upload this data.
For this example, let us use the following file which has data that are of
fixed length. For example, 1st three characters are always employee
number, Next 5 characters are always employee name, etc.
$ cat employee-fixed.txt
200JasonTechnology5500
300MaylaTechnology7000
400NishaTechnology9500
500RandyTechnology6000

Create the following control file, where you specific the position of each
and every field as shown below usig the Position(start:end) syntax.
$ cat sqlldr-fixed.ctl
load data

infile '/home/ramesh/employee-fixed.txt'
into table employee
fields terminated by ","
( id position(1:3), name position(4:8), dept position(9:18), salary
position(19:22) )

Load this fixed length data using the sqlldr as shown below.
$ sqlldr scott/tiger control=/home/ramesh/sqlldr-fixed.ctl

Verify that the data got loaded.


SQL> select * from employee;

ID NAME

DEPT

SALARY HIREDON

---------- ---------- --------------- ---------- --------200 Jason

Technology

5500

300 Mayla

Technology

7000

400 Nisha

Technology

9500

500 Randy

Technology

6000

6. Change the data during upload


You can also massage the data and change it during upload based on
certain rules.
In the following control file:
id is incremented by 999 before uploading. i.e if the emp id is 100 in
the data file, it will be loaded as 1099
Convert the name to upper case and load it. This uses the upper
function.
If the department contains the value Technology change it to
Techies. This uses decode function

$ cat sqlldr-change-data.ctl
load data
infile '/home/ramesh/employee.txt'
into table employee
fields terminated by ","
( id ":id+999",
name "upper(:name)",
dept "decode(:dept,'Technology','Techies', :dept)",
salary
)

Load the data using this control file which will massage the data before
uploading it.

$ sqlldr scott/tiger control=/home/ramesh/sqlldr-change-data.ctl

Verify that the data got changed while loading as per our rules.
SQL> select * from employee;

ID NAME

DEPT

SALARY HIREDON

---------- ---------- --------------- ---------- --------1099 THOMAS

Sales

5000

1199 JASON

Techies

5500

1299 MAYLA

Techies

7000

1399 NISHA

Marketing

1499 RANDY

Techies

9500
6000

7. Load data from multiple files


To load data from multiple files, you just have to specify multiple infile in
the control file.
The following control file loads data from two different data files
(employee.txt and newemployee.txt) to the employee table.
$ sqlldr-add-multiple.ctl
load data

infile '/home/ramesh/employee.txt'
infile '/home/ramesh/newemployee.txt'
into table employee
fields terminated by ","
( id, name, dept, salary )

Load the data using this control file which will upload data from multiple
data files as shown below.
$ sqlldr scott/tiger control=/home/ramesh/sqlldr-add-multiple.ctl
Commit point reached - logical record count 5
Commit point reached - logical record count 7

8. Load data to Multiple Tables


Create another table called bonus which will have employee id and bonus
columns.
create table bonus
( id integer,
bonus integer
);

Create the employee-bonus.txt data file that contains the fields: id, name,
department, salary, bonus

$ cat employee-bonus.txt
100 Thomas Sales

5000 1000

200 Jason Technology 5500 2000


300 Mayla Technology 7000 2000
400 Nisha Marketing 9500 1000
500 Randy Technology 6000 3000

Create the control file as shown below, which will upload the data from the
above file to two different tables. As shown below, you should have two
into table commands, and specify the position of the data which needs
to be used to upload the data to that column.
$ cat sqlldr-multiple-tables.ctl
load data
infile '/home/ramesh/employee-bonus.txt'
into table employee
( id position(1:3),
name position(5:10),
dept position(12:21),
salary position(23:26))
into table bonus

( id position(1:3),
bonus position(28:31))

Load the data to multiple tables using this control file as shown below.
$ sqlldr scott/tiger control=/home/ramesh/sqlldr-multiple-tables.ctl

Verify that the data got loaded to multiple tables successfully.


SQL> select * from employee;

ID NAME

DEPT

SALARY HIREDON

---------- ---------- --------------- ---------- --------100 Thomas

Sales

5000

200 Jason

Technology

5500

300 Mayla

Technology

7000

400 Nisha

Marketing

500 Randy

Technology

SQL> select * from bonus;

9500
6000

ID

BONUS

---------- ---------100

1000

200

2000

300

2000

400

1000

500

3000

9. Handling Bad (Rejected) Records


In the following example, we have two bad records. Employee id 300 and
500 has salary column which is not numeric.
$ cat employee-bad.txt
100,Thomas,Sales,5000
200,Jason,Technology,5500
300,Mayla,Technology,7K
400,Nisha,Marketing,9500
500,Randy,Technology,6K

Use the following control file for this example.


$ cat sqlldr-bad.ctl

load data
infile '/home/ramesh/employee-bad.txt'
into table employee
fields terminated by ","
( id, name, dept, salary )

Load the data (including the invalid records) using this control file as
shown below.
$ sqlldr scott/tiger control=/home/ramesh/sqlldr-bad.ctl
Commit point reached - logical record count 5

As you see from the abvoe output, it still says logical record count 5, but
you should check the log files to see if it has rejected any records.
The log file indicates that 2 records are rejected as shown below:
Control File: /home/ramesh/sqlldr-bad.ctl
Data File:
Bad File:

/home/ramesh/employee-bad.txt
/home/ramesh/employee-bad.bad

Discard File: none specified

Table EMPLOYEE:

3 Rows successfully loaded.


2 Rows not loaded due to data errors.

By default the rejected records are stored in a file that has the same name
as the data file (but with .bad extension)
$ cat employee-bad.bad
300,Mayla,Technology,7K
500,Randy,Technology,6K

As you see below, the employee table has only 3 records (as 2 of them
were rejected).
SQL> select * from employee;

ID NAME

DEPT

SALARY HIREDON

---------- ---------- --------------- ---------- --------100 Thomas

Sales

5000

200 Jason

Technology

5500

400 Nisha

Marketing

9500

10. Load Specific Rows from a datafile


If you want to load only a specific records from a data file use the WHEN in
the control file.

Add the line when next to into table line. In the following control file,
the when clause indicates that it will load only the records that have dept
as Technology.
$ cat sqlldr-when.ctl
load data
infile '/home/ramesh/employee.txt'
into table employee
when dept = 'Technology'
fields terminated by ","
( id, name, dept, salary )

Load the selective data (only the Technology records) using this control
file as shown below.
$ sqlldr scott/tiger control=/home/ramesh/sqlldr-when.ctl
Commit point reached - logical record count 5

As you see from the above output, it still says logical record count 5, but
you should check the log files to see how many records were loaded, and
how many records were discarded because it didnt match the when
condition.
The following from the log file shows that 5 records were read, and 2 of
them were discarded as it didnt match the when condition.
Discard File: none specified

Total logical records read:


Total logical records discarded:

5
2

Verify that only the selective records were loaded into the table.
SQL> select * from employee;

ID NAME

DEPT

SALARY HIREDON

---------- ---------- --------------- ---------- --------200 Jason

Technology

5500

300 Mayla

Technology

7000

500 Randy

Technology

6000

SQL*Loader Options
SQL*Loader provides the following options, which can be specified either on the command line or within a
parameter file:
bad A file that is created when at least one record from the input file is rejected. The rejected data records are
placed in this file. A record could be rejected for many reasons, including a non-unique key or a required column
being null.
bindsize [256000] The size of the bind array in bytes.
columnarrayrows [5000] Specifies the number of rows to allocate for direct path column arrays.
control The name of the control file. This file specifies the format of the data to be loaded.
data The name of the file that contains the data to load.

direct [FALSE] Specifies whether or not to use a direct path load or conventional.
discard The name of the file that contains the discarded rows. Discarded rows are those that fail the WHEN
clause condition when selectively loading records.
discardmax [ALL] The maximum number of discards to allow.
errors [50] The number of errors to allow on the load.
external_table [NOT_USED] Determines whether or not any data will be loaded using external tables. The
other valid options include GENERATE_ONLY and EXECUTE.
file Used only with parallel loads, this parameter specifies the file to allocate extents from.
load [ALL] The number of logical records to load.
log The name of the file used by SQL*Loader to log results.
multithreading The default is TRUE on multiple CPU systems and FALSE on single CPU systems.
parfile [Y] The name of the file that contains the parameter options for SQL*Loader.
parallel [FALSE] Specifies a filename that contains index creation statements.
readsize The size of the buffer used by SQL*Loader when reading data from the input file. This value should
match that of bindsize.
resumable [N] Enables and disables resumable space allocation. When Y, the
parameters resumable_name andresumable_timeout are utilized.
resumable_name User defined string that helps identify a resumable statement that has been
suspended. This parameter is ignored unless resumable = Y.
resumable_timeout [7200 seconds] The time period in which an error must be fixed. This parameter is
ignored unlessresumable = Y.
rows [64] The number of rows to load before a commit is issued (conventional path only). For direct path
loads, rows are the number of rows to read from the data file before saving the data in the datafiles.
silent Suppress errors during data load. A value of ALL will suppress all load messages. Other options
include DISCARDS, ERRORS, FEEDBACK, HEADER, and PARTITIONS.
skip [0] Allows the skipping of the specified number of logical records.
skip_unusable_indexes [FALSE] Determines whether SQL*Loader skips the building of indexes that are in
an unusable state.
skip_index_maintenance [FALSE] Stops index maintenance for direct path loads only.
streamsize [256000] Specifies the size of direct path streams in bytes.

userid The Oracle username and password.

You might also like