PLSQL
PLSQL
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;
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
STEP2:: save the text pad as sql and copy the path of text pad(By
using f3) and paste on the sqlplus.
Copy the path and paste the path after @ symbol in sqlplus.
outputwillnotcomewithoutusinganystatemtsanditwillnotexecute
END;
BEGIN
null;
Wecanusenullalsointhecodesection
END;
2) Using Constant::
block
Ex::
Declare
aconstantnumber(5,3):=3.14;
bnumber(5):=100;
Begin
b:=50;
dbms_output.put_line(a+b);
End;
O/P::53.14
bnumber(5):=&b;
Begin
dbms_output.put_line(a+b);
End;
O/P::
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
I/P::7654
O/P::MARTIN , SALESMAN , 1250
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
Search Case
CASE[Columns/Expressions]
WHENconditionTHEN
execseqofstmts;
whencondtionthen
execseqofstmts;
whencondtionthen
execseqofstmts;
else
execseqofstmts;
ENDCASE;
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
I/P::7839
O/P::sal=5000
I/P::7654
O/P::sal=1250
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
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.
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
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::
7788,SCOTT,3000,20
7902,FORD,3000,20
7369,SMITH,800,20
7876,ADAMS,1100,20
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
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
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
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)
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
||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
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
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.
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.
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.
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.
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;
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
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
O/P::
TheSCOTT is working for 20
There is unhandled exception while processing a program
I/P::1111
O/P::Thegivenempnoisnotexist
I/P::
ORA20345:Thesalislessthan2000,Noupdationsdone
NOTE::Ifweusewhenothersintheexceptionhandlersectionwewillget
thebelowmessage.
I/P::7369
O/P::Anunhandledexceptionoccurwhileprocessingtheprogram
RAISE_APPLICATION_ERROR
ERROR FUNCTIONS/
COLUMNS::
QUALIFIERS
in
EXCEPTIONS
PSEDEO
I/P::7369
O/P::Theemployeedetailsare::SMITH920
as
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.
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
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.
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
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;
/
Maximum
32
arguments
supported
by
(<parametername>[parametermode]<datatype>)
Execution at Sqlplus::
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
BEGIN
proc_sqcb(v_n,:rs,:rc);
DBMS_OUTPUT.put_line(:rs||','||:rc);
END;
I/P:3
O/P::9,27
dbms_output.put_line(noe||'eployeesareavailableinthedepartment');
ENDproc_cnt;
Callingtheaboveprogram::
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
Ex::
execproc_add_dept(p_loc=>'HYD');
select*fromadd_dept_tab
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;
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
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;
At SQL prompt::
execvariablename:=fun1(arg1,arg2);
At SQL PROMPT::
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;
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);
=> 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
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;
/
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;
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
Unbounded
we can delete
No
No Need initialization
Valid only in plsql
collection.limit = null
Collection Methods::
S.N
.
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
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
NO_DATA_FOUND
VALUE_ERROR
SELECT*FROMnsetab
INSERTINTOnsetabVALUES(1,NES('XYZ'))
INSERTINTOnsetabVALUES(2,NES('123'))
INSERTINTOnsetabVALUES(3,NES('XYZ','123','456'))
SELECT*FROMnsetab
Output::
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
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
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)
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.
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>
)
O/P::
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
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
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
/*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
/*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;
ENAM
E
BLAKE
ALLEN
JOB
MGR
HIREDA
TE
SAL
2850
1600
COMM
DEPTN
O
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
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
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::
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
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.
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
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
NEW
OLD
: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
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'
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'
ENDIF;
ENDWHEN_TRIG;
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
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.
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
VALUES(:NEW.ID,:NEW.NAME
);
ENDinstrig;
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
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
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
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)
Active Sessions/users::
select*fromgv$sessionwherestatus='ACTIVE';
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>)
http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/composi
tes.htm#LNPLS00501
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 ::
ORACLE_LOADER::
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)||'_'||
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.
2.
3.
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
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
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) )
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.
501,Ritu,Accounting,5400
(
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
ID NAME
DEPT
SALARY HIREDON
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
/home/ramesh/employee.txt
Table EMPLOYEE:
00:00:00.04
00:00:00.00
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 )
ID NAME
DEPT
SALARY HIREDON
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
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
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" )
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
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
ID NAME
DEPT
SALARY HIREDON
Technology
5500
300 Mayla
Technology
7000
400 Nisha
Technology
9500
500 Randy
Technology
6000
$ 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.
Verify that the data got changed while loading as per our rules.
SQL> select * from employee;
ID NAME
DEPT
SALARY HIREDON
Sales
5000
1199 JASON
Techies
5500
1299 MAYLA
Techies
7000
1399 NISHA
Marketing
1499 RANDY
Techies
9500
6000
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
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
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
ID NAME
DEPT
SALARY HIREDON
Sales
5000
200 Jason
Technology
5500
300 Mayla
Technology
7000
400 Nisha
Marketing
500 Randy
Technology
9500
6000
ID
BONUS
---------- ---------100
1000
200
2000
300
2000
400
1000
500
3000
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
Table EMPLOYEE:
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
Sales
5000
200 Jason
Technology
5500
400 Nisha
Marketing
9500
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
5
2
Verify that only the selective records were loaded into the table.
SQL> select * from employee;
ID NAME
DEPT
SALARY HIREDON
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.