plsql course ware

176
System Consultant 1 ORACLE 9i PL/SQL By System Consultant

Upload: naga5825

Post on 15-Oct-2014

76 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: PLSQL Course Ware

System Consultant

1

ORACLE 9iPL/SQL

By System Consultant

Page 2: PLSQL Course Ware

System Consultant

2

Table of Contents

Serial No. Topic Name Page No.

1 Programming Basics 32 PLSQL Records 213 Cursors 254 PLSQL Tables 345 Exceptions 416 Procedures 497 Functions 618 Oracle Supplied Packages 669 Packages 7910 Ref Cursors 9411 Types 9612 Varrays 9913 Nested Table 10514 Bfile and LOBs 11115 Triggers 118

Assignments 133

Page 3: PLSQL Course Ware

System Consultant

3

Programming Basics with PL/SQL

PL/SQL features --- PL/SQL is an extension of SQL It is an application development language containing procedural statements and

commands along with SQL commands It bridges the gap between database technology and procedural programming

languages It allows you to process data using flow control statements like iterative loops and

conditional branching Uses procedural techniques of control, looping and branching Supports SQL i.e. cursor operations, exceptions, functions and transactional

commands Variables and constants, robust error handling and functions Adds functionality to non-procedural tools such as SQL*Forms Developers using SQL*Forms can enter an entire PL/SQL block using a single

trigger

Structure of PL/SQL Standard PL/SQL code segment is called a Block A block consists of three parts or sections

– Declaration Part– Executable Part– Exception Handling Part

Declaration Part– optional part where variables are defined

Executable Part– mandatory part which consists of executable statements

Exception Handling Part– optional part which consists of code for handling errors (runtime)

Page 4: PLSQL Course Ware

System Consultant

4

Pl/SQL Files - PL/SQL programs can be written in any editor and saved as files with .sql

extension Can also use “ED” command in SQL*Plus to create a PL/SQL program file Use the “@ <filename>” command to execute a PL/SQL program file

o Variables -- Used to store results of a query for later processing, or to calculate values to be

inserted into database tables Can be used anywhere in an expression, either in SQL or PL/SQL statements Must be declared before referencing it in other statements, including other

declarative statements Are declared by specifying the name along with the datatype Can be declared to be of any datatype native to Oracle Examples

oldfare NUMBER(5); m_name VARCHAR(15);

(Note – Set Serveroutput On has to be given when a session starts for displaying the output statements_)declare x number; begin x := 67; dbms_output.put_line(x); dbms_output.put_line('The value of x is '|| x); end;Declaring variable in declare block. Assigning value in in begin block using := . Output statement is dbms_output.put_line Concatenation operator is || Command terminator is ; after end

Declaring and initializing variables together declare y number := 100; begin dbms_output.put_line('The value of y is '|| y);end;-------------------------------------------------------------------------------Taking value from the user using &

declare

Page 5: PLSQL Course Ware

System Consultant

5 z number; a varchar2(10); begin z := &z; a := '&a'; dbms_output.put_line('Z is '|| z); dbms_output.put_line('A is '|| a); end;-------------------------------------------------------------------------------

/*Cannot declare or initialize more than one variable simultaneously*/declare a number; b number; c number;begin a := 67; b := 90; c := 87; dbms_output.put_line(a); dbms_output.put_line(b);end;

A constant number has to declared and initialized in the declare block only usingCONSTANT keyword. Value cannot be changed

declare r CONSTANT number :=100; begin /* r := r + 100; Not possible*/ dbms_output.put_line(r);end;

/*Assigning value to variable from a column of a table using select into clause*/declare x number;begin

Select sal Into x from emp where ename = 'SMITH'; dbms_output.put_line('Salary of Smith is '|| x); end;

Page 6: PLSQL Course Ware

System Consultant

6/* Selecting ename,sal from emp Use of more than one columns value with Into clause*/declare n varchar2(50); s number;begin select ename, sal Into n, s from emp where ename = 'SMITH'; dbms_output.put_line(n); dbms_output.put_line(s);end;

% Type Attribute – Provides datatype of a variable or column Useful when declaring a variable that refers to a column in a database

– exact datatype of column need not be known– if column definition changes, variable datatype changes accordingly at

runtime Example

oldfare fare.first_fare%TYPE;newfare oldfare%TYPE;

declare a emp.ename%type; b emp.sal%type; c emp.deptno%type; /*Using %TYPE attribute for variable data type*/begin select ename,sal,deptno into a,b,c from emp where ename = 'KING'; dbms_output.put_line(a ||'-'|| b ||'-' || c); end;

%RowType Attribute – Useful when declaring a record variable having same structure as a row in a

table or view, or as a row fetched from a cursor Fields in the record have same names and datatypes as the columns in the

table/view Example

emp_rec employee%ROWTYPE; A specific field can be referenced using

emp_rec.emp_num;

Page 7: PLSQL Course Ware

System Consultant

7declare E emp%rowtype; /*rowtype attribute holds the datatype of the columns of the entire row*/begin select * INTO E from emp where ename = 'MARTIN'; dbms_output.put_line(E.sal); dbms_output.put_line(E.ename); dbms_output.put_line(e.deptno); end;

Conditional Statements – IF The selection structure tests a condition, then executes one sequence of statements

instead of another, depending on the condition There are three forms of statements

– IF-THEN– IF-THEN-ELSE– IF-THEN-ELSIF

Sequence of statements is executed only if the condition evaluates to TRUE If condition evaluates to FALSE or NULL, it does nothing In either case control passes to next statement after the IF-THEN structure

IF <condition> THENstatements;END IF;

Sequence of statements in the ELSE clause is executed only if the condition evaluates to FALSE or NULL

IF <condition> THENstatements;ELSEstatements;END IF;--------------------------------------------------------------------------------declare /*Simple if condition */ x number; begin x := &x; if x >= 35 then dbms_output.put_line('Passed'); else dbms_output.put_line('Failed'); end if;end;-----------------------------------------------------

Page 8: PLSQL Course Ware

System Consultant

8IF-THEN-ELSIF Structure

This construct allows selection of action from several mutually exclusive alternatives

The IF statement can have any number of ELSIF clauses The final ELSE is optional Conditions are evaluated one by one from top to bottom

SyntaxIF <condition1> THENstatements;ELSIF <condition2> THENstatements;ELSIF <condition3> THENstatements;ELSEstatements;END IF;Example 1 –Declare y number; /*Multiple ifs */ Begin y := &y; if y >= 70 then dbms_output.put_line('Distinction'); elsif y >= 60 then dbms_output.put_line('First class'); elsif y >= 50 then dbms_output.put_line('Second class'); elsif y >= 35 then dbms_output.put_line('Passed'); else dbms_output.put_line('Failed'); end if;end;

Example 2 create table adm(Name varchar2(30),Marks number(3), College varchar2(30), Fees number(5));

Page 9: PLSQL Course Ware

System Consultant

9/*Use of multiple if's Accept name and marks from user. Depending upon marks entered the college and fees should be decided and the record should be entered in the adm table.*/

Declare n adm.name%type; m adm.marks%type; c adm.college%type; f adm.fees%type;

Begin n := '&n'; m := &m;

if m >= 95 then c := 'COEP'; f := 10000; elsif m >= 90 then c := 'MIT'; f := 15000; elsif m >= 85 then c := 'VIT'; f := 22000; elsif m >= 80 then c := 'D Y Patil'; f := 27000; elsif m >= 75 then c := 'Pune Vidyarthi'; f := 33000; else dbms_output.put_line('Cannot get admission'); end if;

if c is not null and f is not null then dbms_output.put_line('Your College is '|| c || ' and fees are ' || f); Insert into adm values(n,m,c,f); commit; end if;

end;

Page 10: PLSQL Course Ware

System Consultant

10

Nested Blocks

declare x number;

begin x := 80;dbms_output.put_line(‘abc’); declare y number; begin y := 90; dbms_output.put_line('Inner Block variable value ' || y); end;

dbms_output.put_line('Outer Block variable value ' || x);end;

Scope of variables

A variable declared in the outer block is accessible in the inner block. But a variable declared in the inner block is accessible only in the inner block.

declare outer number;begin outer := 80; declare inner number; begin inner := 90; dbms_output.put_line('Inner Block variable value ' || inner); dbms_output.put_line('Outer block variable is accessible in the inner block’); dbms_output.put_line('Outer block variable value ' || outer); end;

dbms_output.put_line('Outer Block variable value ' || outer);dbms_output.put_line('Inner Block variable value ' || inner);end;/

Page 11: PLSQL Course Ware

System Consultant

11

Labels

If the variables names of the outer and inner blocks are same then labels have to be used within the inner block to avoid ambiguity.

<<outer_block>>declare x number;begin

<<inner_block>> declare x number := 100; begin dbms_output.put_line('Value of the inner block x is ' || x); -- Giving value of x of the inner block to the outer block x outer_block.x :=inner_block. x; end;

x := x + 500;dbms_output.put_line('Value of the outer block x is ' || x);end;/LOOPS

The ability to repeat or skip sections of a block can be achieved with the usage of LOOP or GOTO statements

There are three forms of the LOOP statement– LOOP– WHILE-LOOP– FOR-LOOP

LOOP Statement LOOP repeats a sequence of statements Statements to be repeated are placed between keyword LOOP and END LOOP With each iteration of the loop, the sequence of statements is executed, then

control resumes at the top of the loopLOOPstatements;END LOOP;

EXIT Statement Used to complete a loop if further processing in a loop is undesirable or

impossible There are two forms of the EXIT statement

– EXIT– EXIT-WHEN

Forces a loop to complete unconditionally

Page 12: PLSQL Course Ware

System Consultant

12

Must be placed inside a loopLOOPstatements;IF <condition> THENEXIT; -- exit loop immediatelyEND IF;END LOOP;-- control resumes here

Example of Loop –/*To show 1 to 10 on screen*/

Declare x number;Begin x := 1; Loop dbms_output.put_line(x); x := x + 2; exit when x > 10; End Loop;dbms_output.put_line(‘end’); End;

create table five(no number);/*Inserting multiples of five in table five*/

Declare x number;Begin x := 5; Loop Insert into five values(x); x := x + 5; exit when x > 50; End Loop;End;

FOR LOOP Advantages -- 1) No need of declaring loop variable 2) No need of giving condition 3) No need of updation statement (increment or decrement ) 4)Code becomes small and compact

Page 13: PLSQL Course Ware

System Consultant

13

Disadvantage -- Updation can be done by only one. Syntax – FOR <counter> IN [REVERSE] lower_bound .. higher_bound LOOPstatements;END LOOP

Example 1 of for loop /*To show 1 to 10 on screen*/

begin for x in 1..10 Loop dbms_output.put_line(x); End Loop;end;

Example 2 /*Reverse for loop 10,9,8 … 1*/

Begin for i in REVERSE 1 ..10 Loop dbms_output.put_line(i); End Loop;end;

Example 3 – Calculating compound interest for a principal of Rs.100 @10% for each year. Values will be shown of the CI after each year.

create table CI_100(year number(2),total number(4));----------------------------------Declare p number := 100; tot number;/*Calculation of compound interest. Rs.100 is principal.

Page 14: PLSQL Course Ware

System Consultant

14

Rate of interest is 10%. Period is 5 years. */Begin for y in 1..5 Loop /* Tot variable is getting 10% more than p */ tot := p + p * 0.10; Insert into CI_100 values(y,tot); /*Since the next interest is based on the current interest so the tot will be considered as p for the next year*/ p := tot; End Loop;end;

WHILE-LOOP Statement

Associates a condition with a sequence of statements enclosed within LOOP-END LOOP

Condition evaluated before each iteration If condition evaluates to TRUE, sequence of statements is executed and control

resumes at the top of the loop If condition evaluates to FALSE or NULL, loop is bypassed and control passes to

next statement Number of iterations depends on the condition and is unknown until the loop

completesWHILE <condition>LOOPstatements;END LOOP;

Example 1 of while loop to show 1 to 15

declare x number;Begin x := 1; while x <=15

Page 15: PLSQL Course Ware

System Consultant

15

Loop dbms_output.put_line(x); x := x + 1; End Loop;end;

Example 2 Forces a loop to complete unconditionallydeclare z number;/*Using break after z reaches to 8*/Begin z := 1; while z <=15 m Loop dbms_output.put_line(z); z := z + 1; exit when z = 8; End Loop;end;

While Loop v/s Basic LoopWhile Loop

declare x number;Begin x := 1; while x > 15 Loop dbms_output.put_line(x); x := x + 1; End Loop; dbms_output.put_line('End of program');end;/

The loop will never get executed since the condition is wrong from the start of the iteration.

Basic Loop

Declare x number; Begin x := 1; Loop

Page 16: PLSQL Course Ware

System Consultant

16

dbms_output.put_line(x); exit when x = 1; x := x + 1; End Loop;dbms_output.put_line('End of program'); End;/

The loop gets executed at least once.

Nested Loops

create table discount_details (quarter number(2), month number(2), discount varchar2(5));

Expected Output –

QUARTER MONTH DISCOUNT

1 1 12% 1 2 11% 1 3 10% 2 4 9% 2 5 8% 2 6 7% 3 7 6% 3 8 5% 3 9 4% 4 10 3% 4 11 2% 4 12 1%

12 rows selected.

declare q number; m number; d number; dis varchar2(10); c number;

Page 17: PLSQL Course Ware

System Consultant

17

begin q := 1; m := 0; d := 12; loop exit when q > 4; c := 0;

loop exit when c >= 3; m := m + 1; dis := d || '%'; insert into discount_details values(q,m,dis); d := d - 1; c := c + 1; end loop;

q := q + 1; end loop;

end;

GOTO Statement Branches to a label unconditionally When executed, it changes the flow of control in a PL/SQL block Two parts needed to code a GOTO statement

– Define a label name– Use the GOTO statement to pass control to the label

Label name– optionally used to name a PL/SQL block or statements within the block– Defined using angular brackets (<< >>)

<<if_fare_label>>IF condition THENstatements;END IF;statements;GOTO if_fare_label;

Transfer of control using GOTO statement is allowed in the following places– from a block to an executable statement– branch from an exception handler into an enclosing block

Transfer of control using GOTO statement is NOT allowed in the following places

– from within one IF statement or loop clause to another– from an enclosing block into a sub-block– from an exception handler into the current block– out of a subprogram

Page 18: PLSQL Course Ware

System Consultant

18

– to keywords

Examples of GOTO –1) create table prec(name varchar2(20), dept varchar2(20));

create table mahrec(name varchar2(20), dept varchar2(20), city varchar2(30));

/*Pune records should go in both the tables prec and mahrec. Any other city record should go in mahrec table only.*/

declare n prec.name%type; d prec.dept%type; c mahrec.city%type;

begin n := '&n'; d := '&d'; c := '&c'; if c = 'Pune' then goto s1; else goto s2; end if; <<s1>> Insert into prec values(n,d); <<s2>> Insert into mahrec values(n,d,c); end;

Wrong usage of goto

declarex number;beginx := 90;<<s1>>

Page 19: PLSQL Course Ware

System Consultant

19

dbms_output.put_line('S1'); if x = 90 then dbms_output.put_line('Condition is true'); goto s1; else dbms_output.put_line('Condition is false'); end if;end;/

PL/SQL Records

Objects of type RECORD are called PL/SQL records PL/SQL records have uniquely named fields, which can belong to different

datatypes Define a RECORD type

TYPE <typename> IS RECORD(fieldname1 <fieldtype> : fieldnameN <fieldtype> ;(%TYPE and %ROWTYPE can be used to specify <fieldtype>]

Example 1 of Record Type –

Declare TYPE empdetails IS RECORD(eno Emp.Empno%type, name Emp.Ename%type, s Emp.Sal%type);

VE empdetails;Begin

Select empno,ename,sal Into VE from Emp where ename = 'SMITH'; dbms_output.put_line(VE.eno || ' - ' || VE.name || '-' ||VE.s);End;

Example 2 of Record Type –

Declare TYPE si IS RECORD (p number,

Page 20: PLSQL Course Ware

System Consultant

20

n number, r number := 4.5);/* r variable of si type has been given value. */VSI si;x number;Begin VSI.p := 5000; VSI.n := 6; x := (VSI.p * VSI.n * VSI.r) / 100; dbms_output.put_line(x);End;

Using a record type in another record type.

Declare

type Address_details is record (sector char(3), colony varchar2(50), bldg_name varchar2(25), pincode number(7));

type personal_details is record (name varchar2(60), Addr Address_Details, age number);

V personal_details;

Begin V.name := 'John'; V.Addr.sector := 'S1'; V.Addr.colony := 'Model'; V.Addr.bldg_name := 'Hill View'; V.Addr.pincode := 6775; dbms_output.put_line('The building name is ' || V.Addr.bldg_name); dbms_output.put_line('The pincode is ' ||V.Addr.pincode);

End;

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

Page 21: PLSQL Course Ware

System Consultant

21

%Rowtype with Recorddeclare

type t1 is record(ed emp%rowtype, dd dept%rowtype);

VT1 t1;Begin

select * into VT1.edfrom empwhere ename = 'KING';

select * into VT1.ddfrom deptwhere dname = 'ACCOUNTING';

dbms_output.put_line(VT1.ed.ename);dbms_output.put_line(VT1.dd.dname);

end;

Cursors To process a SQL statement, PL/SQL opens a work area called a context area. PL/SQL uses this area to execute SQL statements and store processing

information A PL/SQL construct called ‘Cursor’ allows you to name a context area, access its

information and in some cases, control its processing

Explicit CursorsDefined by the user to keep track of which row is being processed, when a query returns multiple rows

Defining a Cursor A cursor is defined in the declarative part of the PL/SQL block by naming it and

associating it with a queryCURSOR <cursorname> IS<SELECT statement>;

ExampleCURSOR emp_cur ISSELECT empno, ename, job, salFROM emp;

A Cursor can be manipulated using– OPEN– FETCH

Page 22: PLSQL Course Ware

System Consultant

22

– CLOSE Cursor must be declared before it can be referenced using the OPEN, CLOSE or

FETCH statements

The OPEN Statement Initializes or opens a cursor Cursor must be opened before any rows are returned by the query

OPEN <cursorname>Example --

OPEN emp_cur;

The FETCH Statement Can be executed repeatedly until all rows have been retrieved

FETCH <cursorname> INTO var1, …, varN;ORFETCH <cursorname> INTO record_variable;

ExampleFETCH emp_cur INTO mrec;

The CLOSE Statement Closes the cursor and makes the active set undefined

CLOSE <cursorname>; Example

CLOSE emp_cur;

Once a cursor is closed, it can be reopened by using the OPEN statement

Attributes of Explicit Cursors

Every cursor has four attributes that can be used to access the cursor’s context area

– %NOTFOUND– %FOUND– %ROWCOUNT– %ISOPEN

To use these attributes, simple append them to the name of the cursor %NOTFOUND

– evaluates to TRUE if last FETCH failed because no more rows were available

– evaluates to FALSE if last FETCH returned a row %FOUND

– evaluates to TRUE if last FETCH returned a row– evaluates to FALSE if last FETCH failed because no more rows were

available %ROWCOUNT

– returns the number of rows FETCHed from the active set so far

Page 23: PLSQL Course Ware

System Consultant

23

%ISOPEN– evaluates to TRUE if an explicit cursor is open– evaluates to FALSE if an explicit cursor is closed

Examples of Cursor – 1)To transfer names and sal of employees from emp table where sal >= 2500 in table try1create table try1(no number,ename varchar2(50),sal number);

Declare Cursor cf is select ename,sal from emp where sal >= 2500; M cf%rowtype; N number;Begin Open cf; N := 0; Loop Fetch cf into M; Exit when cf%notfound; N := cf%rowcount;

Insert into try1 values(N,M.ename,M.sal); End Loop;

Close cf;End;

2) Use of %FOUND attribute

Accepting the job from user and finally showing how many such jobs are there.

Declare Cursor cf is select * from emp where job ='&J';

M cf%rowtype;

Page 24: PLSQL Course Ware

System Consultant

24

N number;

J Emp.Job%type;

Begin Open cf; N := 0; Loop Fetch cf into M; Exit when cf%notfound; If cf%found then N := N + 1; End if; End Loop; Close cf; If N > 0 then dbms_output.put_line('Total number of job ' || J || ' is '|| N); else dbms_output.put_line('No such job'); End If;End; ----------------------------------------------------------------------

3) Use of IsOpen attribute Declare Cursor cf is select ename, deptno from emp where deptno = 20; M cf%rowtype;/*The cursor is not opened before Loop. So using IsOpen attribute to open the cursor if it is not open.*/ Begin/* Cursor is not opened!!! */ Loop If cf%IsOpen then Fetch cf into M; else Open cf; dbms_output.put_line('Cursor is now opened'); End if; exit when cf%notfound;

Page 25: PLSQL Course Ware

System Consultant

25

dbms_output.put_line(M.ename ||'--' || M.deptno); End Loop;End; --------------------------------------------------------------------------------------4) Transferring the first five records from emp table into another table FirstFive

create table firstfiveas select empno,ename,sal,deptno from emp where 1=2;

Declare Cursor cf is Select * from emp; M cf%rowtype; N number; Begin Open cf; N := 1; while N <= 5 Loop Fetch cf into M; Insert into firstfive values(M.empno,M.ename,M.sal,M.deptno); N := N +1; End Loop;End;

5) Displaying the 3rd record entered in the table emp –

Declare Cursor cf is select * from emp; M cf%rowtype;Begin Open cf; Loop fetch cf into M; if cf%rowcount = 3 then dbms_output.put_line(M.empno||'-'||M.ename||'-'||M.sal||'-'||M.deptno); end if; exit when cf%notfound;

Page 26: PLSQL Course Ware

System Consultant

26

End Loop;End;

6) To see the first person( or first record entered) who has got salary > 2800Declare Cursor cf is select * from emp where sal > 2800; M cf%rowtype;Begin Open cf; Loop fetch cf into M; if cf%rowcount = 1 then dbms_output.put_line(M.empno||'-'||M.ename||'-'||M.sal||'-'||M.deptno); exit; end if;

End Loop;End;

Cursor FOR Loop Implicitly declares its loop index as a record of %ROWTYPE, Implicitly opens the cursor Repeatedly fetches rows of values from the active set into fields in the record Implicitly closes the cursor when all rows have been processed or the loop is

exited The statements in the loop construct are executed once for each row that satisfies

the query associated with the cursor name Cursor FOR loop is used to simplify coding No need of --1)Open cursor2)Fetch3)Exit 4)Close cursor

7) To show records where salary is > 3000Declare Cursor cf is select * from emp where sal >= 3000;Begin For mrec in cf

Page 27: PLSQL Course Ware

System Consultant

27

Loop dbms_output.put_line(mrec.ename||' '||mrec.sal||' '||mrec.deptno); End Loop;End;

For Loops using sub queries No need of declaring cursor.

A private cursor within an anonymous block can be created.

To show names of employees who have job MANAGER.

begin for MREC in (select * from emp) Loop if MREC.job = 'MANAGER' then dbms_output.put_line('Name is ' ||MREC.ename); end if; END LOOP; end;Parameterized CursorThe same cursor can be reopened and closed with different active sets.

declarecursor cf(pjob emp.job%type)isselect empno,ename,job,salfrom empwhere job = pjob;M cf%rowtype;begin open cf('ANALYST'); LOOP FETCH CF INTO M; EXIT WHEN CF%NOTFOUND; dbms_output.put_line(M.ename); end loop; close cf;open cf('CLERK'); LOOP FETCH CF INTO M; EXIT WHEN CF%NOTFOUND; dbms_output.put_line(M.ename); end loop;

Page 28: PLSQL Course Ware

System Consultant

28

close cf;open cf(‘MANAGER’);LOOP FETCH CF INTO M; EXIT WHEN CF%NOTFOUND; dbms_output.put_line(M.ename); end loop; close cf;

END;

Page 29: PLSQL Course Ware

System Consultant

29

Cursor FOR UPDATE OF and CURRENT OF CURRENT OF clause is used in an UPDATE or DELETE statement to refer to

the current row of the cursor The cursor must be declared with the FOR UPDATE OF clause and must be open

and positioned on a row If the cursor is not open, CURRENT OF clause results in an error

8) Example of Cursor FOR UPDATE OF and CURRENT OF create table esal(empno number, sal number);

insert into esalvalues(1,16000);insert into esalvalues(2,14000);insert into esalvalues(3,8000);insert into esalvalues(4,6500);insert into esalvalues(5,9000);insert into esalvalues(6,11000);insert into esalvalues(7,5500);insert into esalvalues(8,3500);insert into esalvalues(9,2200);insert into esalvalues(10,7000);

Multiple updations depending on the salary clause in one pl/sql block –

Declare Cursor cf is select * from esal

For Update of sal; M cf%rowtype;

Begin Open cf; Loop Fetch cf into M;

Page 30: PLSQL Course Ware

System Consultant

30

exit when cf%notfound;

If M.Sal >= 16000 Then M.Sal := 20000;

ElsIf M.Sal >= 14000 Then M.Sal := 18200;

ElsIf M.Sal >= 12000 Then M.Sal := 16700;

ElsIf M.Sal >= 10000 Then M.Sal := 13500;

ElsIf M.Sal >= 8000 Then M.Sal := 11000; ElsIf M.Sal >= 6000 Then M.Sal := 9500; ElsIf M.Sal >= 4000 Then M.Sal := 7500;

Else M.Sal := 5000; End If; Update esal set sal = M.Sal

Where Current Of cf; End Loop;End;

Implicit Cursors• Automatically defined and opened, by Oracle, to process each

SQL statement• most recently opened context area is referred to as a ‘SQL%’

cursor

Attributes of Implicit Cursors

Page 31: PLSQL Course Ware

System Consultant

31

Although OPEN, CLOSE and FETCH statements cannot be used to manipulate the SQL% cursor, the attributes can be used to access its context area

Attributes evaluate to NULL, before the cursor is opened automatically The following four cursor attributes can be used to access the SQL%

cursor’s context area SQL%NOTFOUND SQL%FOUND SQL%ROWCOUNT SQL%ISOPEN

SQL%NOTFOUND evaluates to TRUE if an INSERT, UPDATE or DELETE statement

affected no rows, else it evaluates to FALSE SQL%FOUND

logical opposite of SQL%NOTFOUND evaluates to TRUE if an INSERT, UPDATE or DELETE affected one or

more rows, else it evaluates to FALSE

SQL%ROWCOUNT– returns the number of rows affected by an INSERT, UPDATE or

DELETE statement SQL%ISOPEN

– Oracle automatically closes an implicit cursor after executing its associated SQL statement

– For an implicit cursor SQL%ISOPEN always evaluates to FALSE

9) Example of Implicit CursorsBegin

Delete from emp where ename = '&name';

If SQL%Found Then dbms_output.put_line('Record found and it is deleted'); End If;

If SQL%NotFound Then dbms_output.put_line('No record is present of the given name.'); End If;

End;

10) Implicit Cursor for rowcount

Page 32: PLSQL Course Ware

System Consultant

32

DeclareC number; := 0;Begin Update Emp set sal = sal + 500 where deptno = &deptno;

/*If no record is updated since the deptno supplied is wrong then giving the customised error message.*/ If SQL%Rowcount = 0 then dbms_output.put_line('No records are updated since the department number entered is not in the table.'); End if;

/*To prevent sal to be updated where deptno is > 3 */ If SQL%RowCount > 3 then Rollback; dbms_output.put_line('Cannot update since there are more than 3 deptnos'); End If;

If SQL%RowCount Between 1 and 3 then c := SQL%RowCount; dbms_output.put_line(c || ' records updated.'); End If;End;

PL/SQL Tables

Features of PL/SQL tables are as follows –1) It is a composite data type.2) They are modeled as similar to database tables, but they are not permanent tables.

So they can be created and manipulated only in a PL SQL block.3) They can have only one column but any data type4) It will have a primary key which is compulsory for the reference of values5) There is no name to the column and primary key6) The data type of the primary key is BINARY_INTEGER. BINARY_INTEGER is a special data type which can be given only to the column of PL/SQL table for it’s indexing purpose to store and retrieve values.

Page 33: PLSQL Course Ware

System Consultant

33

Range of binary_integer is -2147483647 to + 21474836477) Size is unconstrained (Table size grows as the rows are added to the table).8) Can visualize a Pl/SQL table as a single dimensional vertical array, which can

hold unlimited elements.9) Suitable for storing and displaying the values of one column of a table given

by a cursor.

Example of PL SQL Table –

Each name from the emp table is given to the vname plsql table by using cursor. Then those names from vname table are displayed .

Declare Type nametable IS TABLE OF CHAR(10) INDEX BY BINARY_INTEGER;/*Creating variable vname of nametable type.*/ vname nametable; Cursor cf is select ename from emp; i number; vrows number; /*i is for the loop and vrows is for displaying the total names from the vname table*/Begin Open cf; i := 1; Loop Fetch cf into vname(i); /*Transferring each ename into vname table*/ Exit when cf%NotFound; vrows := cf%rowcount; i := i + 1; End Loop;

Page 34: PLSQL Course Ware

System Consultant

34

Close cf;

/*Now retrieving the names from the vname plsql table using for loop.*/ For n in 1..vrows Loop dbms_output.put_line('Name is '||vname(n)); End Loop;End;

Properties of a PL SQL table --- Exists Count First Last Next Prior Delete

declareType discount is TABLE OF number INDEX By Binary_Integer;d discount;Begin d(5) := 90; d(2) := 50; d(8) := 70; d(11) := 67; d(14) := 68; d(1) := 1; d(23) := 5; d(23) := 51; dbms_output.put_line('The value at 23 index number is ' || d(23)); dbms_output.put_line('The value at index number 6 is ' || d(6)); --dbms_output.put_line('The value at index number 2 is ' || d(2)); if d.EXISTS(6) Then dbms_output.put_line(d(6)); else dbms_output.put_line('There is no element in the sixth row'); end if; dbms_output.put_line('The total number of elements in d are '|| d.count);

Page 35: PLSQL Course Ware

System Consultant

35

/*dbms_output.put_line('The first index number is ' || d.FIRST); dbms_output.put_line('The last index number is ' || d.LAST); dbms_output.put_line('The index number after 2 is ' || d.next(2)); dbms_output.put_line('The index number before 8 is ' || d.prior(8)); d.delete(5); dbms_output.put_line('The total number of elements in d are '|| d.count); d.delete(11,14); dbms_output.put_line('The total number of elements in d are '|| d.count); d.delete; dbms_output.put_line('The total number of elements in d are '|| d.count); */ end;

Page 36: PLSQL Course Ware

System Consultant

36

EXCEPTIONS

Introduction to Exceptions

An error condition is called an Exception When an error occurs, an exception is raised i.e. normal execution stops and

control transfers to the exception handling part of the PL/SQL block or subprogram

To handle raised exceptions, separate routines called exception handlers are written

There are two types of exceptions– Pre-defined exceptions (Internal Exceptions)– User-defined exceptions

You cannot declare an exception twice in the same block, but can declare the same exception in two different blocks

Exceptions declared in a block are local to that block and global to all its sub-blocks

Enclosing blocks cannot reference exceptions declared in a sub-block because blocks can only reference local or global exceptions

Predefined Exceptions Are implicitly raised whenever a PL/SQL block violates an Oracle rule or exceeds

a system-dependent limit Every Oracle error has a number, but exceptions must be handled by name PL/SQL predefines some common Oracle errors as exceptions These predefined exceptions are declared globally by PL/SQL Some Pre-defined Exceptions

CURSOR_ALREADY_OPEN NO_DATA_FOUND TOO_MANY_ROWS VALUE_ERROR ZERO_DIVIDE

More than one exception can be handled in a single exception handler by separating them with the keyword OR

EXCEPTIONWHEN NO_DATA_FOUND OR TOO_MANY_ROWS THENstatements; WHEN OTHERS THENstatements;END;

Page 37: PLSQL Course Ware

System Consultant

37

Examples of Exception handling –1) NO_DATA_FOUND error (Variable is not having any value.)

declare n emp.ename%type; s emp.sal%type;begin select sal into s from emp where ename = '&n';dbms_output.put_line('Salary is '|| s);

/* Exception When NO_DATA_FOUND then dbms_output.put_line('No record'); */end;

2) TOO_MANY_ROWS error (Variable is having more than one value)

declare s emp.sal%type; begin select sal into s from emp; dbms_output.put_line('The salary is '|| s ); Exception When TOO_MANY_ROWS then dbms_output.put_line('Variable can hold only one value at a time'); dbms_output.put_line('Please specify the name of person for getting the salary');end;

3) ZERO_DIVIDE error (A number divided by zero)declare x number; y number; z number;begin x := &x; y := &y; z := x/y; dbms_output.put_line('The answer is ' || z);

Exception

Page 38: PLSQL Course Ware

System Consultant

38

When ZERO_DIVIDE then dbms_output.put_line('Cannot divide by zero!!!'); end;

4) DUP_VAL_ON_INDEX error (When a duplicate value is entered in a column having Unique constraint)

declare e emp.empno%type;begin e := &e; insert into emp (empno ) values(e); dbms_output.put_line('Successful');Exception When DUP_VAL_ON_INDEX then dbms_output.put_line('Value already exists');end;

5) VALUE_ERROR (Error in conversion of string to number)

declare n number;beginn := '&n';dbms_output.put_line(n);Exception When VALUE_ERROR then dbms_output.put_line('Please enter number only');end;

6) OTHERS (If no error handler works then at least OTHERS will work)

declare x number; y number; z number;begin x := &x; y := &y; z := x/y; dbms_output.put_line('The answer is ' || z);

Exception

Page 39: PLSQL Course Ware

System Consultant

39

When too_many_rows then dbms_output.put_line('More than one value'); When no_data_found then dbms_output.put_line('No value'); /*When OTHERS then dbms_output.put_line('Some run time error has occurred'); dbms_output.put_line('Please execute the program again with proper values.'); rollback;*/end;

Pragma Exception

create table dept1(deptno number primary key, dname varchar2(10));create table emp1(empno number, ename varchar2(10), deptno number references dept1(deptno));insert into dept1 values(10,'Acc');insert into emp1 values(1,'abc',10);

PRAGMA PRAGMA EXCEPTION_INIT tells the compiler to associate an exception name with an Oracle error number. That allows you to refer to any internal exception by name and to write a specific handler for it.

declare referential_integrity EXCEPTION; PRAGMA EXCEPTION_INIT( referential_integrity, -2292); begin Delete from dept1 where deptno = &deptno; commit; exception when referential_integrity then dbms_output.put_line('The record cannot be deleted, because related record found in emp1 table');end;

SQLCODE AND SQLERRMSQLCODE Returns the numeric value for the error code.SQLERRM Returns the message associated with the error number.

create table error_log(error_number number, error_message varchar2(255));

Page 40: PLSQL Course Ware

System Consultant

40

declare s emp.sal%type; v_error_code number; v_error_message varchar2(255);beginselect sal into s from emp;exception when others then v_error_code := SQLCODE; v_error_message := SQLERRM; Insert into error_log values(v_error_code, v_error_message); commit;end;

Exception Handlers in nested block to continue after run time error comes

declare loan_amt number; no_of_months number; installment_rate number; roi number; tot_amt number;begin loan_amt := &loan_amt; no_of_months := & no_of_months;

begin installment_rate := loan_amt / no_of_months; exception when zero_divide then no_of_months := 3; installment_rate := loan_amt / no_of_months; end;

/* In any case the last 3 lines will get executed */ roi := installment_rate * 0.2; -- 20% roi tot_amt := roi + loan_amt; dbms_output.put_line('The total amount to be paid is '|| tot_amt);end;

Page 41: PLSQL Course Ware

System Consultant

41

User-defined Exceptions

User-defined exceptions need to be defined in the declarative part of a PL/SQL block, subprogram or database trigger

Declared by naming the exception and defining it as datatype EXCEPTION ExampleDECLAREpast_due EXCEPTION;zero_error EXCEPTION;

Like variables, user-defined exceptions must be given names Unlike variables, user-defined exceptions cannot be assigned values and cannot

be used in SQL statements They need to be raised explicitly using the RAISE statement

A block should RAISE an exception only when an error makes it impossible or impractical to finish processing

RAISE statement for a given expression can be coded anywhere within the scope of that expression

IF mrec.ss_fare <= 0 THENRAISE zero_error;END IF;

An exception raised inside a handler immediately propagates to the enclosing block, which is searched to find a handler for the newly raised exception

From there on, the exception propagates normally To re-raise an exception place a RAISE statement in its local handler

Page 42: PLSQL Course Ware

System Consultant

42

Example of Exception variable using Raise key worddeclare p number; n number := 6; si number; r number := 10.5; EX exception;

Begin p := &p; if p < 100 then raise EX; else si := (p * n * r) / 100; dbms_output.put_line('The Simple Interest is '|| si); end if;Exception When EX then dbms_output.put_line('The principle amt should be greater than or equal to 100.'); end; --------------------------------------------------------------------------------------

RAISE_application_error

This can be used to create user defined error message, which can be more descriptive than named exceptions.

Syntax - :Raise_application_error(error number,error message);

where error number is any parameter between -20,000 and -20,999.Error message is text that is associated with this error. The message parameter must be less than 512 characters.

Example of Raise_application_errordeclare maths number; Begin maths := &maths; if maths < 35 then raise_application_error(-20001,'Failed'); else dbms_output.put_line('Passed'); end if;

Page 43: PLSQL Course Ware

System Consultant

43

end; ---------------------------------------------------------------------------------------------------Example of Raise_application_error and error handling together –

declare x number; begin x := '&x'; if x < 0 then raise_application_error(-20009,'ty'); end if; exception when value_error then dbms_output.put_line('ff'); end;

Page 44: PLSQL Course Ware

System Consultant

44

PROCEDURES Advantages of Subprograms

Provide Extensibility– PL/SQL language can be tailored to suit the needs of the application

Promote reusability and maintainability– Once validated, they can be used with confidence in any number of

applications– Simplifies maintenance/enhancement, as subprogram is only affected if

definition changes Provide Modularity

– Program can be broken down into manageable, well-defined logical modules

– Supports top-down design and stepwise refinement approach to problem solving

Aid in abstraction– Allow mental separation from particulars– Stubs allow programmers to defer definition of procedures/functions until

main program is tested and debugged

Procedure performs specific action Stored in database and can be invoked or called by any anonymous block Can take parameters Datatype specifier in parameter declaration must be unconstrained

Has two parts– Specification

• begins with keyword PROCEDURE, ends with procedure name or parameter list

– Body• begins with keyword IS, ends with keyword END followed by

optional procedure name

CREATE [OR REPLACE] PROCEDURE <procedurename> [(parameter1, … parameterN)] IS[local declarations]BEGINexecutable statements;[EXCEPTIONexception handlers]END [<procedurename>];

parameter stands for

Page 45: PLSQL Course Ware

System Consultant

45

variablename [IN|OUT|IN OUT] datatype [{:= | DEFAULT} value] When a procedure is created, Oracle automatically performs these steps

– Compiles the procedure– Stores the compiled code– Stores the procedure in the database

The PL/SQL compiler used to compile the code If an error occurs, the procedure is created but it is invalid

Enforce Data Security– Can grant users access to a procedure that queries a table, but not

grant access to the table itself Improve Database Performance

– Less amount of information sent over network– Compilation not required to execute code– Procedure present in shared pool so retrieval from disk not required

Memory Savings– Only one copy of procedure needs to be loaded in memory for

execution by multiple users Increase in Development Productivity

– Can avoid redundant coding and increase productivity, by writing a single procedure

Integrity– Procedures need to be tested only once, to guarantee that it returns

accurate results

Calling a Stored Procedure

Can call a procedure in a PL/SQL statement– Example

branch_sum(‘NYK’); Can call a procedure from SQL*Plus

– ExampleSQL> EXECUTE branch_sum(‘NYK’);

Examples of Procedures –

Page 46: PLSQL Course Ware

System Consultant

46

1) --Procedure without parameterscreate or replace procedure pr1ass emp.sal%type;Beginselect sal into sfrom empwhere ename = 'SMITH';dbms_output.put_line(s);end;

Parameter Modes for Procedures and Functions Used to define the behavior of formal parameters Can be used with any subprogram Three parameter modes

– IN (Default)– OUT– IN OUT

IN– allows values to be passed to the subprogram being called– inside the subprogram it acts like a constant– actual corresponding parameter can be a constant, literal, initialized

variable or expression– can be initialized to default values

2) --Supplying parameters to a procedure which are by default of IN type

create or replace procedure pr2(En IN Emp.Empno%type, Name IN Emp.ename%type, S Emp.Sal%type)isBegin Insert into Emp(empno,ename,sal) Values(En,Name,S); dbms_output.put_line('One record inserted through procedure');End;

3) Giving default values to the parametersDue to default value given the parameter becomes optional also.But if any other value is given then it takes it.

create or replace procedure pr3 (Eno emp.empno%type, N emp.ename%type, S emp.sal%type, dno emp.deptno%type DEFAULT 10)is

Page 47: PLSQL Course Ware

System Consultant

47

BeginInsert into emp (empno,ename,sal,deptno)values(Eno,N,S,dno);dbms_output.put_line('Record inserted');End;

-- While executing--exec pr3 (1,'o',800) -----> (No deptno parameter given!!!)

4) --Cannot give size to the parameterscreate or replace procedure pr4 (name char, marks number)isBegin if marks >= 35 then dbms_output.put_line('Passed'); else dbms_output.put_line('Failed'); end if; dbms_output.put_line(name);End;

Named notations

create or replace procedure dept_rec(p_deptno in number, p_dname in dept.dname%type default 'Accounts', p_loc dept.loc%type)isbeginInsert into dept values(p_deptno, p_dname, p_loc);dbms_output.put_line('Done');end;

To exceute such a parameter we have to use the named notation

exec dept_rec(p_loc => 'Pune', p_deptno => 10);

Mutiple ways of passing the parameters --1. Positional Method -- exec dept_rec(20,'Purchase','Mumbai');2. Named Method –

a. exec dept_rec(p_loc => 'Bangalore',p_deptno => 30);b. exec dept_rec(p_deptno =>20, p_dname => 'Inspection', p_loc =>

'Pune');

Page 48: PLSQL Course Ware

System Consultant

48

c. exec dept_rec(p_dname =>'Stores', p_loc => 'Mumbai', p_deptno => 10);

3. Combination Method – After positional there can be named parameters, but after named there cannot be positional parameters.

a. exec dept_rec(10, p_loc =>'Mumbai', p_dname =>'Marketing');b. exec dept_rec(p_deptno =>20, 'Pune','Research'); -- Wrong

OUT parameter– allows values to be returned to the caller of a subprogram– inside the subprogram it acts like an uninitialized variable– actual corresponding parameter must be a variable; it cannot be a

constant or expression– its value cannot be assigned to another variable or reassigned to itself

5) create or replace procedure pr5(Name IN varchar2, Salary OUT number)IsBegin Select sal into Salary from emp where ename = Name;End;--Steps for displaying the OUT parameter--1) Compiling the procedure.--2) Declare the bind variable on SQL prompt as variable payment number-- Bind variables are of SQL* plus environment which are used to hold the return--value given by the procedure or function.--3)Now execute the proc -- exec pr5('SMITH', :payment)--4)To display the value of payment -- print payment--5)Bind variables are session specific.Their existence is removed as the session --ends.

Using local variable for out parameter when procedure is called inside another block.

Page 49: PLSQL Course Ware

System Consultant

49

create or replace procedure p1(n in emp.ename%type, s out emp.sal%type)isbeginselect sal into sfrom empwhere ename = n;end;

declarex emp.sal%type;beginp1('SMITH',x);dbms_output.put_line(x);end;

6) IN OUT parameter – allows initial values to be passed and returns updated values to the

caller– inside the subprogram it acts like an initialized variable– actual corresponding parameter must be a variable; it cannot be a

constant or expression– can be assigned a value and its value can be assigned to another

variable

a) create or replace procedure pr6(x IN OUT number) Is Begin x := (x * x); End;

/*pr6 procedure cannot be executed independently on sql prompt.It has to be called inside a plsql block. It actually gives the square value to the variable of that plsql block. In short IN OUT type of paramter makes a procedure similar to function, as the function also returns the value to the calling environment.*/b)

declare

Page 50: PLSQL Course Ware

System Consultant

50

a number;Begin a := &a; pr6(a);

/*When a is given as a parameter , it's status is of IN OUT. So IN means the user input value and OUT means the changes square figure due to the procedure pr6. After the procedure is called with a as parameter then a value gets changed. At this time a acts as a OUT parameter, since the procedure is giving the changed value to a.*/

dbms_output.put_line(a);

End;

Page 51: PLSQL Course Ware

System Consultant

51

7) IN OUT example from with respect to databasea)create or replace procedure salrise(salary IN OUT number) isBeginsalary := salary + (salary * 0.20);End;/*Salrise procedure will increment the sal by 20% and give the value to the calling plsql block.*/

b) Declaren emp.ename%type;s emp.sal%type;Beginn := '&n';select sal into s from empwhere ename = n; dbms_output.put_line('The old salary is ' || s);/*Now calling the procdure Salrise and giving s as a IN parameter*/ Salrise(s);/*After giving the salary as a parameter the salary value gets incremented by 20% */ dbms_output.put_line('The changed salary is '|| s);/*updating the table*/ Update emp set sal = swhere ename = n; dbms_output.put_line('Salary of ' || n || ' is updated in the table.'); Exception When NO_DATA_FOUND then dbms_output.put_line('No such name');end;

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

Page 52: PLSQL Course Ware

System Consultant

52

Declaring Sub procedures

Create table log_table(username varchar2(30), log_date date);

Create or replace procedure delete_emp(p_ename emp.ename%type)Is /*Creating a sub procedure */ Procedure log_emp is Begin Insert into log_table Values(user, SYSDATE); End;

Begin

Delete from emp where ename = p_ename;

log_emp;

End;

Page 53: PLSQL Course Ware

System Consultant

53

Handled or Unhandled Exceptions for a procedure getting called in another.

create or replace procedure innerproc(x number,y number)isbegindbms_output.put_line(x/y);exception when zero_divide thendbms_output.put_line('y cannot be negative'); end;

create or replace procedure outerprocasbegindbms_output.put_line('AA');/*Calling the innerproc precedure.*/innerproc(4,0);dbms_output.put_line('cc’);

exceptionwhen others thendbms_output.put_line('A Run Time Error has occurred.');end;

If the innerproc procedure is not having any error handler then the error handler outer procedure gets executed.

AUTHID CURRENT_USER

If a procedure reads data from table and performs some DML then AUTHID CURRENT_USER is applicable. Due to this clause the owner of the procedure only can execute this procedure and read or perform DML. Even if the owner has given execute privilege of such a procedure to any other user, still the other user cannot execute the procedure. So from data security point of view this clause is helpful.The following scenario will explain this concept.

Case study ----

Log on as System/Manager (DBA Login)

create user a1 identified by a1;grant resource, create session to a1;-------------------------------------------------------create user a2 identified by a2;

Page 54: PLSQL Course Ware

System Consultant

54

grant resource, create session to a2;----------------------------------------------------------Without AUTHID CURRENTUSER

conn a1/a1create table t1(a number);insert into t1 values(1);commit;----------------------------------------------------------- create or replace procedure t1_data is x number; begin select a into x from t1; dbms_output.put_line(x); end; ----------------------------------------------grant execute on t1_data to a2;-------------------------------------------------conn a2/a2 exec a1.t1_data --- Data is shown.

With AUTHID CURRENTUSER

conn a1/a1

create or replace procedure t1_data1 AUTHID CURRENT_USER is x number; begin select a into x from t1; dbms_output.put_line(x); end;---------------------------------------- grant execute on t1_data1 to a2;

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

conn a2/a2exec a1.t1_data1 -- Data is not shown. Throws error.

Page 55: PLSQL Course Ware

System Consultant

55

Page 56: PLSQL Course Ware

System Consultant

56

Functions

Subprogram that returns a value Have a RETURN clause Stored in database and can be invoked or called by any anonymous block Generally take parameters Datatype specifier in parameter declaration must be unconstrained Has two parts

Specification begins with keyword FUNCTION, ends with RETURN clause

Body begins with keyword IS, ends with keyword END followed by

optional function name

Syntax –

CREATE [OR REPLACE] FUNCTION <functionname> [(argument1, … argumentN)] RETURN datatype IS[local declarations]BEGINexecutable statements;[EXCEPTIONexception handlers]END [<functionname>];

argument stands forvariablename [IN|OUT|IN OUT] datatype [{:= | DEFAULT} value]

Format –

CREATE FUNCTION day_fn(mday NUMBER) RETURN CHAR ISdisp_day CHAR(15);BEGINexecutable statements;RETURN disp_day;EXCEPTIONstatements;END day_fn;

Calling a Function

Can call a function as a PL/SQL statement– Example

chardays := day_fn(3);

Page 57: PLSQL Course Ware

System Consultant

57

Can call a function as part of an expression– Example

IF day_fn(3) = ‘TUESDAY’ THENstatements;END IF;

The RETURN Statement

Immediately completes execution of subprogram and returns control to caller In procedures

– cannot contain an expression– returns control to the caller before normal end of procedure is reached

In functions– must contain an expression, evaluated when it is executed

Examples of Functions –1) a) create or replace function eo ( n number) RETURN char isdisp char(30);Begin If Mod(n,2) = 0 Then disp := 'Number is even'; else disp := 'Number is odd'; End If; dbms_output.put_line(disp);

RETURN disp;

End;

Select eo(9) from dual;OR

Page 58: PLSQL Course Ware

System Consultant

58

Declare x number; y char(30);Begin x := &x; /*Calling the function eo, supplying the parameter x and giving the value to y*/ y := eo(x);

end;

2) Database examplea) create or replace function Remarks ( x number)RETURN char isdisp char(30);Begin If x >= 70 Then disp := 'Distinction';

Elsif x >= 60 Then disp := 'First Class'; Elsif x >= 50 Then disp := 'Second Class';

Elsif x >= 35 Then disp := 'Passed';

Else disp := 'Failed';

End If;

RETURN disp;

End;

c) Using this function to insert values for a column of a tablecreate table st(name varchar2(10),marks number,result char(30));

Page 59: PLSQL Course Ware

System Consultant

59

Directly calling the function inside Insert statement Insert into st values(‘John’, 90, Remarks(90)); -- Directly calling the function in the values clause

b) Calling a function in select statement

create or replace function raise_sal(s number) return number is begin return s + 8000; end;

Select ename,deptno,job,sal, raise_sal(sal) From emp;

create or replace function f1(s number) return number is begin delete from emp; return 0; end; Wrong usage of functionsselect ename,sal,f1(sal) from emp;

3) Returning more than one value using OUT parametera) create or replace function getdetails(no number,name OUT varchar2)RETURN varchar2 asvloc varchar2(30);beginselect dname,loc into name,vlocfrom deptwhere deptno = no;

RETURN vloc;End;

b)-- First declare two bind variables location and deptname--SQL> variable deptname varchar2(100) (size is imp)--SQL> variable location varchar2(100)

Page 60: PLSQL Course Ware

System Consultant

60

Begin:location := getdetails(30, :deptname);End;

-- To see both the values-- print deptname location-------------------------------------------------------------------------

Page 61: PLSQL Course Ware

System Consultant

61

ORACLE SUPPLIED PACKAGES

DBMS_SQL

DBMS_DDL

DBMS_JOB

UTL_FILE

Page 62: PLSQL Course Ware

System Consultant

62

DBMS_SQL PackageWhat Is Dynamic SQL?

Dynamic SQL enables you to write programs those reference SQL statements whose full text is not known until runtime. Before discussing dynamic SQL in detail, a clear definition of static SQL may provide a good starting point for understanding dynamic SQL. Static SQL statements do not change from execution to execution. The full text of static SQL statements are known at compilation, which provides the following benefits:

Successful compilation verifies that the SQL statements reference valid database objects.

Successful compilation verifies that the necessary privileges are in place to access the database objects.

Performance of static SQL is generally better than dynamic SQL.

Because of these advantages, you should use dynamic SQL only if you cannot use static SQL to accomplish your goals, or if using static SQL is cumbersome compared to dynamic SQL. However, static SQL has limitations that can be overcome with dynamic SQL. You may not always know the full text of the SQL statements that must be executed in a PL/SQL procedure. Your program may accept user input that defines the SQL statements to execute, or your program may need to complete some processing work to determine the correct course of action. In such cases, you should use dynamic SQL.

For example, a reporting application in a data warehouse environment might not know the exact table name until runtime. These tables might be named according to the starting month and year of the quarter, for example INV_01_1997, INV_04_1997, INV_07_1997, INV_10_1997, INV_01_1998, and so on. You can use dynamic SQL in your reporting application to specify the table name at runtime.

You might also want to run a complex query with a user-selectable sort order. Instead of coding the query twice, with different ORDER BY clauses, you can construct the query dynamically to include a specified ORDER BY clause.

Dynamic SQL programs can handle changes in data definitions, without the need to recompile. This makes dynamic SQL much more flexible than static SQL. Dynamic SQL lets you write reusable code because the SQL can be easily adapted for different environments.

Dynamic SQL also lets you execute data definition language (DDL) statements and other SQL statements that are not supported in purely static SQL programs.

Page 63: PLSQL Course Ware

System Consultant

63

Why Use Dynamic SQL?

You should use dynamic SQL in cases where static SQL does not support the operation you want to perform, or in cases where you do not know the exact SQL statements that must be executed by a PL/SQL procedure. These SQL statements may depend on user input, or they may depend on processing work done by the program. The following sections describe typical situations where you should use dynamic SQL and typical problems that can be solved by using dynamic SQL

Executing DDL and SCL Statements in PL/SQL

In PL/SQL, you can only execute the following types of statements using dynamic SQL, rather than static SQL:

Data definition language (DDL) statements, such as CREATE, DROP, GRANT, and REVOKE

Session control language (SCL) statements, such as ALTER SESSION and SET ROLE

Executing Dynamic Queries

You can use dynamic SQL to create applications that execute dynamic queries, whose full text is not known until runtime. Many types of applications need to use dynamic queries, including:

Applications that allow users to input or choose query search or sorting criteria at runtime

Applications that allow users to input or choose optimizer hints at run time Applications that query a database where the data definitions of tables are

constantly changing Applications that query a database where new tables are created often

Page 64: PLSQL Course Ware

System Consultant

64

DBMS_SQL is used to write dynamic SQL in stored procedure and to parse DDL statements.

Some Procedures and Functions in DBMS_SQL package are –Open_Cursor – Opens a new cursor and assigns a cursor ID number.

PARSE – Parses the DDL or DML statements, i.e. it checks the syntax and associates it with the opened cursor. In case of DDL statements they are executed immediately after parsing.

PARSE (ID number of the cursor, DDL or DML statement, language_flag)

language_flag

 Determines how Oracle handles the SQL statement. The following options are recognized:

V6 (or 0) specifies version 6 behavior. NATIVE (or 1) specifies normal behavior for the database to

which the program is connected.

V7 (or 2) specifies Oracle7 behavior.

EXECUTE – Executes the SQL statement and returns the number of rows processed.Especially suitable for keeping track of count of rows affected by a DML statement.

create or replace procedure drop_table(p_tablename in varchar2)isC NUMBER;beginc := DBMS_SQL.OPEN_CURSOR;DBMS_SQL.PARSE(C,'DROP TABLE ' || p_tablename, DBMS_SQL.NATIVE);exception when others then dbms_output.put_line('Table name to be dropped does not exist');end;

Page 65: PLSQL Course Ware

System Consultant

65

create or replace procedure delete_rows(table_name varchar2)is c number; rows_deleted number;begin c := DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE(c, 'Delete from ' || table_name, DBMS_SQL.NATIVE); rows_deleted := DBMS_SQL.EXECUTE(c); dbms_output.put_line('The total number of rows deleted are ' || rows_deleted);Exception when others then dbms_output.put_line('No rows deleted'); end;

Page 66: PLSQL Course Ware

System Consultant

66

DBMS_DDL Package

Scenario of recompilation for a procedure –

drop table tx1;

create table tx1(a number);

insert into tx1 values(1);

create or replace procedure px1iss number;beginselect a into sfrom tx1;end;

select status from user_objectswhere object_name='PX1';

alter table tx1add b number

select status from user_objectswhere object_name='PX1';

alter procedure px1 compile; OR Exec px1;

select status from user_objectswhere object_name='PX1';

Page 67: PLSQL Course Ware

System Consultant

67

DBMS_DDL.ALTER_COMPILE(‘object_type’, ‘owner name’, object_name)

Object_type can be a procedure, function, package specification, package body or a trigger only.

create or replace procedure compile_procedure(procedure_name varchar2)asbegin DBMS_DDL.ALTER_COMPILE('PROCEDURE','SCOTT', procedure_name); dbms_output.put_line('The procedure ' || procedure_name || ' is recompiled');end;

exec compile_procedure('PX1');

select status from user_objectswhere object_name='PX1';

Page 68: PLSQL Course Ware

System Consultant

68

DBMS_JOB Package

Enables the scheduling and execution of PL/SQL programs.

Submit is the procedure of DBMS_JOB package.The parameters of Submit procedure are ---

JOB – Unique identifier of the job (Out parameter)WHAT – PL/SQL code to execute as a jobNEXT_DATE – Next execution date of the jobINTERVAL – Date function to compute the next execution date of a job.

Example –Every next day a new record should get added in the table djt1.

Create table djt1(a number);

Create sequence jobseq;

Create or replace procedure p1 Is Begin Insert into djt1 Values(jobseq.nextval); End;/

Variable jobno number

begin dbms_job.submit ( job => :jobno, what => 'P1;', next_date => trunc(sysdate), interval => 'trunc(sysdate + 1)' ); commit;end;

Page 69: PLSQL Course Ware

System Consultant

69

In the init.ora file JOB_QUEUE_PROCESSES = n has to be setted n can be between 1 and 36.

Change the system date to the next date. The t1 table gets the next value of the sequence.Again repeat the process.

Imp setting – job_queue_processes = n (n between 1 and 36) in the init.ora file

Select job,what from user_jobs;

Exec dbms_job.Broken(1,true) – 1 is job no

Exec dbms_job.Remove(1)

Dbms_job.change(jobno, what, next_date, interval)

Jobno cannot be changed.If there is no change for what, next_date, interval then specify NULL

For having interval of 60 seconds it will be ‘Sysdate + (59/ (24*60*60))’

Page 70: PLSQL Course Ware

System Consultant

70

UTL_FILE Package

UTL_FILE package is used to write data to operating system files such as text files, word files, excel files, etc.

The data from the oracle table is transferred to the o.s. files. So we can generate a report of Oracle data in a non-oracle format.

Members of UTL_FILE Package are as follows –

FOPEN function

This function opens a file for input or output. The file location must be an accessible directory, as defined in the instance's initialization parameter UTL_FILE_DIR. The complete directory path must already exist; it is not created by FOPEN.

It takes 3 parameters1. Directory name The path2. File name (.txt, .doc,.xls,)3. Open_Mode

a. ‘r’ – Read Textb. ‘w’-- Write Textc. ‘a’ – Append Text

PUTF procedure

This procedure is a formatted PUT procedure. It works like a limited printf(). The format string can contain any text, but the character sequences '%s' and '\n' have special meaning.

%s

 Substitute this sequence with the string value of the next argument in the argument list.  

\n

 Substitute with the appropriate platform-specific line terminator.  

Page 71: PLSQL Course Ware

System Consultant

71

FCLOSE procedureThis procedure closes an open file identified by a file handle.

NEW_LINE procedure (Can specify how many blank lines are required. Default is 1)This procedure writes one or more line terminators to the file identified by the input file handle. This procedure is separate from PUT because the line terminator is a platform-specific character or sequence of characters.

Syntax UTL_FILE.NEW_LINE ( file IN FILE_TYPE, lines IN NATURAL := 3);

Page 72: PLSQL Course Ware

System Consultant

72

Example of generating a text file of salary status from the emp table.

create or replace procedure sal_status(p_filedir in varchar2, p_filename in varchar2)isv_filehandle UTL_FILE.FILE_TYPE; Cursor emp_info is select ename,sal,deptno from emp order by sal desc;Begin v_filehandle := UTL_FILE.FOPEN(p_filedir,p_filename,'w'); UTL_FILE.PUTF(v_filehandle,'SALARY REPORT : GENERATED ON %s\n',SYSDATE); UTL_FILE.NEW_LINE(v_filehandle); for v_emp_rec in emp_info LOOP UTL_FILE.PUTF(v_filehandle,'DEPARTMENT: %s \n', v_emp_rec.deptno); UTL_FILE.PUTF(v_filehandle,' Employee:%s earns: %s\n', v_emp_rec.ename,v_emp_rec.sal);

END LOOP; UTL_FILE.PUTF(v_filehandle, '*** END OF REPORT ***'); UTL_FILE.FCLOSE(v_filehandle);EXCEPTION WHEN UTL_FILE.INVALID_FILEHANDLE THEN raise_application_error(-20001,'Invalid File'); WHEN UTL_FILE.WRITE_ERROR THEN raise_application_error(-20002,'Unable to write file'); End;

Page 73: PLSQL Course Ware

System Consultant

73

Steps for executing the procedure are as follows –1. In the init.ora file of the database, the file location has to be defined

as a value of UTL_FILE_DIR

Open the init.ora file and add the property as follows-UTL_FILE_DIR = C:\ABC

(Step 1 is only required for early version. If directory object is not created then UTL_FILE_DIR path is required)2. Create a folder ABC in C drive.

3. Create a directory object in database as –

create directory D1 as 'C:\ABC'

Directory is a nonschema database object that provides a way for administering the o.s. files through Oracle Server 9i.A Directory specifies an alias for the actual o.s. path .

4. Execute the procedure Exec Sal_Status('D1','a1.txt'); -- a1.txt is the new text file getting generated.

Query the following dictionary views to get information on directories in the database

ALL_DIRECTORIES - all directories accessible to the database user

Page 74: PLSQL Course Ware

System Consultant

74

Packages

Database objects that group logically related PL/SQL types, objects and subprograms

They cannot be called, passed parameters to or nested There are two parts

– Specification– Body

Advantages of Packages Modularity

– allows encapsulation of related types, objects and subprograms in a named PL/SQL module

– easy to understand with simple, clear and well defined interfaces– helps in application development

Easier Application Design– when designing applications, only interface information in package

specifications initially required– can code and compile specification without body– stored subprograms referencing the package can be compiled as well– need not define package bodies until ready to complete the application

Information Hiding– can specify which types, items, and subprograms are public or private– definition of private subprograms is hidden so that only the package (not

the application) is affected if the definition changes– simplifies maintenance and enhancement and protects integrity of the

package Better performance

– when a packaged subprogram is called for the first time, the whole package is loaded into memory

– later calls to related subprograms in the package require no disk I/OPackage Specification

Is an interface to the applications Declares the types, variables, constants, exceptions, cursors and subprograms

available for use Holds public declarations, visible to the application Can be thought of as an operational interface Scope of the declarations are local to the database schema and global to the

package Lists the package resources available to applications Created using CREATE PACKAGE command

Page 75: PLSQL Course Ware

System Consultant

75

Syntax for Package Specification –

CREATE [OR REPLACE] PACKAGE <packagename> ASGlobal variables declaration;Procedure specifications;Function specifications;Type Definitions;Cursor DeclarationsEND [<packagename>];

Package Body

Implements the package specification Fully defines cursors and subprograms Holds implementation details and private declarations, hidden from the

application Can be thought of as a ‘black body’ Can be replaced, enhanced or replaced without changing the interface Can be changed without recompiling calling programs Scope of the declarations are local to the package body Declared types and objects are inaccessible except from within the package body Initialization part of a package is run only once, the first time the package is

referenced

Syntax for Package Body –

CREATE [OR REPLACE] PACKAGE BODY <packagename> AS Private members (variables and procedure/functions/cursors/types)Procedure Code;Function Code;Implementation of Types;Use of Cursors;Using Global variables in the members of the package.END [<packagename>];

Referencing Package Objects

Packaged objects and subprograms must be referenced using the dot notationpackagename.typenamepackagename.objectnamepackagename.subprogramname

E.g - DBMS_OUTPUT.PUT_LINE

Page 76: PLSQL Course Ware

System Consultant

76

Maintaining a Package

Can drop a package using the DROP commandDROP PACKAGE <packagename> ExampleDROP PACKAGE airlines;To drop just one construct, remove it from the package and then recompile the package

Examples of Packages -

1) Creating a package of 3 procedures -

Package Specification –

create or replace package pk1 isprocedure x(a number);procedure y(b number);procedure z(c number);end PK1;

Package Body -create or replace package body pk1is procedure x(a number) is Begin dbms_output.put_line('Procedure p1'); End x; procedure y(b number) is Begin dbms_output.put_line('Procedure p2'); End y;/*Suppose in the package body if all the procedures are not written then it will give error.*/ /*procedure z(c number) is Begin dbms_output.put_line('Procedure p3'); End z; */

Page 77: PLSQL Course Ware

System Consultant

77

End pk1;------------------------------- Using the Package pk1- SQL > Execute PK1.X(4);

2) Use of global variable in a function and procedure -

Package Specification -

create or replace package pk2asg number;function m(a number) return number;procedure n;end pk2;

Package Body -

create or replace package body pk2asfunction m(a number) return numberisBegin g := a;return g;End m;

procedure nis Begin if g >= 100 then dbms_output.put_line('Discount is 20%'); else dbms_output.put_line('Discount is 10%'); end if;end n;End pk2;

Using the package in a PL/SQL block -

Declare x number;Begin x := pk2.m(700); pk2.n;End;

Page 78: PLSQL Course Ware

System Consultant

78

Page 79: PLSQL Course Ware

System Consultant

79

3) Use of Type in a Procedure -

Package Specification -

create or replace package pk3 asType t1 is RECORD(e1 Emp.Empno %Type,e2 Emp.Ename%Type,e3 Emp.Sal%Type);Procedure p1;end pk3;

Package Body -

create or replace package body pk3 asprocedure p1is v t1; /*Using the type of the package directly inside the procedure.*/Begin select empno,ename,sal into v from emp where ename = 'SMITH'; dbms_output.put_line(v.e1 || '-' || v.e2 || '-' || v.e3);End;End pk3;

4) Use of Cursor in Procedure -

Package Specification -

create or replace package pk4ascursor cf is select * from empwhere job = 'MANAGER';m cf%rowtype;procedure CP;End pk4;

Page 80: PLSQL Course Ware

System Consultant

80

Package Body -

create or replace package body pk4 asprocedure CPis Begin Open cf; Loop fetch cf into m; /*Showing the first entry of manager*/ if cf%rowcount = 1 then dbms_output.put_line(m.empno || '-' || m.ename || '-' || m.sal); else exit; end if; End Loop; Close cf; End CP;End pk4;

5) Example of a body less package – (Persistent state of variables)

create or replace package bodyless is x number := 200; y number := 100; /*Variables needs to be initialized if it is in a body less package*/end;

begin bodyless.x := bodyless.x + 100; dbms_output.put_line('Now the value of the x variable of bodyless package is ' || bodyless.x); bodyless.y := bodyless.y + 500;dbms_output.put_line('Now the value of the y variable of bodyless package is ' || bodyless.y); end;/* Note-- Execute the block 3-4 times, you will see that the values of x and y are getting changed.But disconnect or close the session and start the session again.The original values of the x and y from the package gets initialized.*/

Page 81: PLSQL Course Ware

System Consultant

81

6) Example of private members in package body –

create or replace package prvmembersisprocedure m1;end;

create or replace package body prvmembersis/*Creating Private Procedure in the body*/procedure m2is begindbms_output.put_line('This is the private member of the package body');end m2;

procedure m1is beginm2;end;end;

Example of forward declaration of a private member

create or replace package body prvmembersis

procedure m2; /* Forward declaration of m2 */procedure m1isbeginm2;end;

/*Creating Private Procedure in the body*/

procedure m2is begindbms_output.put_line('This is the private member of the package body');end m2;end;

Page 82: PLSQL Course Ware

System Consultant

82If the private member is not getting called in any global members then forward declaration is not required.

create or replace package body prvmembersisprocedure m1isbegindbms_output.put_line('abc');end;/*Creating Private Procedure in the body*/procedure m2is begindbms_output.put_line('This is the private member of the package body');end m2;end;/

7) Example of one time only procedure (Procedure in package body)

Useful for setting remote connectivity for front ends.In the session for the first time any of the members of the package is called then the procedure will be implicitly invoked. Then for the future calls of the members of the same package in the same session the procedure will not get executed.

create or replace package pk1isprocedure p1;procedure p2;end;

Page 83: PLSQL Course Ware

System Consultant

83

create or replace package body pk1is procedure p1 is begin dbms_output.put_line('p1'); end p1;

procedure p2 is begin dbms_output.put_line('p2'); end p2;

begin dbms_output.put_line('Welcome to my package'); end pk1;

create or replace package pk1is type namelist is table of emp.ename%type index by binary_integer; v namelist; cursor cf is select ename from emp; M cf%rowtype; procedure first_five; procedure next_five;

end;

Page 84: PLSQL Course Ware

System Consultant

84

create or replace package body pk1is i Number; procedure first_five is begin for i in 1..5 loop dbms_output.put_line(v(i)); end loop;

end first_five;procedure next_fiveis begin for i in 6..10 loop dbms_output.put_line(v(i)); end loop; end next_five;

begin i := 0; open cf; loop i := i + 1; fetch cf into M; v(i) := M.ename; exit when cf%notfound;

end loop;end

To initialize the global variable by taking value from table

Page 85: PLSQL Course Ware

System Consultant

85

create or replace package pk1is average_sal number; function calc_sal_deviation(s number) return number; procedure sal_status(s number);end;

create or replace package body pk1is /*function calc_sal_deviation(s number) return number; procedure sal_status(s number);*/ function calc_sal_deviation(s number) return number is begin if average_sal > s then return (average_sal - s); else return 0; end if; end; procedure sal_status(s number) is begin if average_sal > s then dbms_output.put_line('On Lower Side'); else dbms_output.put_line('On Higher Side'); end if; end; begin select avg(sal) into average_sal from emp;end;

exec pk1.SAL_STATUS(800);

exec pk1.SAL_STATUS(4000);

select sal, pk1.CALC_SAL_DEVIATION(sal) "Deviation" from emp;

Page 86: PLSQL Course Ware

System Consultant

86

8) Example of Overloaded Members

create or replace package pk1is procedure p(a number, b number); procedure p(x varchar2,y varchar2); procedure p(z number); procedure p;end pk1;

create or replace package body pk1is procedure p(a number, b number) is c number; begin c := a + b; dbms_output.put_line(c); end p;

procedure p(x varchar2, y varchar2) is begin dbms_output.put_line(x ||y); end p; procedure p(z number) is begin if z > 0 then dbms_output.put_line('The number is positive'); else dbms_output.put_line('The number is negative'); end if; end p;

procedure p is begin dbms_output.put_line('No parameter is passed'); end p;end pk1;

Page 87: PLSQL Course Ware

System Consultant

87Example of overloaded members –Parameter data types can be same, but names should be different.

create or replace package pk2asprocedure p(salary number, commission number);procedure p(salary number, tax number);end pk2;

create or replace package body pk2as procedure p(salary number, commission number) is total number; begin total := salary + commission; dbms_output.put_line(total); end; procedure p(salary number, tax number) is take_home number; begin take_home := salary - tax; dbms_output.put_line(take_home); end;end pk2;

While executing such procedure the parameters need to be called by named method only.

exec pk2.p(salary => 4000, commission => 500);

exec pk2.p(salary => 4000, tax=> 200);

Page 88: PLSQL Course Ware

System Consultant

88Example of Persistent Cursors –

create or replace package pciscursor cf is select * from emp;procedure pp1;procedure pp2;c cf%rowtype;end ;

create or replace package body pc isprocedure pp1 is begin open cf; loop fetch cf into c; dbms_output.put_line(c.empno||'-'||c.ename||'-'||c.sal); exit when cf%rowcount >= 3; end loop; end pp1;procedure pp2 is begin loop fetch cf into c; dbms_output.put_line(c.empno||'-'||c.ename||'-'||c.sal); exit when cf%rowcount >= 6; end loop; close cf; end pp2;end;

Page 89: PLSQL Course Ware

System Consultant

89

PURITY LEVELS

PRAGMA RESTRICT_REFERENCES

WNDS - Write No Database State

RNDS - Read No Database State

WNPS - Write No Package State

RNPS - Read No Package State

Example of WNDS and RNDScreate table pt1(a number);

Insert into pt1 values(1);

Package Specification Code –

create or replace package pragma_packageas function getTotal(commission in number) return number;

PRAGMA RESTRICT_REFERENCES (getTotal, WNDS, RNDS);

end;

Page 90: PLSQL Course Ware

System Consultant

90

Package Body Code -

create or replace package body pragma_packageas function getTotal(commission in number) return number is salary number := 0; begin select a into salary from pt1 where a = 1; -- Throws error return (commission + salary); end;end;

PLS-00452: Subprogram 'GETTOTAL' violates its associated pragma

Example of WNPSPackage Code –

create or replace package purity_levelsas pi number := 3.14; function circle_area(radius number) return number; PRAGMA RESTRICT_REFERENCES (circle_area, WNPS); end;Package Body code -create or replace package body purity_levelsas function circle_area(radius number) return number is area number; begin pi := pi + 5.4; -- Throws error area := pi *radius *radius;

Page 91: PLSQL Course Ware

System Consultant

91

return area; end;end;

Example of RNPS

Package Specification Code –

create or replace package purity_level1as selling_price number := 4000; tax number := 50; procedure cust_details; PRAGMA RESTRICT_REFERENCES (cust_details, RNPS);end;

Package Body Code -- create or replace package body purity_level1as procedure cust_details is begin Insert into pt1 values(purity_level1.selling_price); end;end;

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

Page 92: PLSQL Course Ware

System Consultant

92

REF CURSORSLimitations of a normal cursors are --1) A PL/SQL program cannot pass a cursor as a parameter to another program.2) A PL/SQL program can only open the cursor and process the information within the program itself.

To overcome these limitations there is a concept of REF CURSOR.

Features of REF CURSOR --1) There can be a TYPE of ref cursor. The variable of this TYPE can be used to pass the parameters to a program and return value from the cursor.2) The variable of REF CURSOR type returns the same data type as the cursor variable.3) The cursor variable is passed as a parameter to a procedure. 4) The cursor variable takes all the rows from the specified table.5) These rows are given to the bind variable. So the parameter passed should satisfy two conditions -- a) The parameter should be taken from the TYPE of Ref Cursor. b) It should be of IN OUT mode.6) Finally the data retrieved by the cursor variable can be seen through the bind variable. For this the data type of the bind variable should be REFCURSOR.7) While executing the procedure bind variable should be directly given. And then by print statement the data is displayed.8) The cursor variable's data structure and the procedure block's data structure should be same.

Advantage of REF CURSOR-- Actually we can get the view of the entire data of the table with simplicity using REF CURSOR. Without using ref cursor if we have to achieve this then, the parameter passed will be of variable typeand then the user has to manual loop using cursor to fetch all the records. Here in REF CURSOR there is no need of looping.

Page 93: PLSQL Course Ware

System Consultant

93

Example of REF CURSOR –

Package Specification –

create or replace package PRC as

TYPE EmpRC IS REF CURSOR RETURN emp%rowtype;TYPE DeptRC IS REF CURSOR RETURN dept%rowtype;

Procedure EmpDetails(ve IN OUT EmpRC);Procedure DeptDetails(vd IN OUT DeptRC);

End PRC;Package Body –

create or replace package Body PRC as Procedure EmpDetails(ve IN OUT EmpRC) is Begin Open ve FOR select * from emp; End EmpDetails;

Procedure DeptDetails(vd IN OUT DeptRC) is Begin Open vd FOR select * from dept;

End DeptDetails;

End PRC;

For executing the procdure –1) SQL > variable E REFCURSOR SQL > variable D REFCURSOR

2) To see the data from the bind variable -- SQL > Set AutoPrint ON

3) SQL > Execute PRC.EmpDetails(:E); 4) SQL > Execute PRC.DeptDetails(:D);

Page 94: PLSQL Course Ware

System Consultant

94

TYPES

Users can create their own data types by combining previously defined data types Also called Object types Object types made up of attributes and members

Creating type Info which holds the attributes –

Create or replace type Info as OBJECT( Name varchar2(30), Address varchar2(30), City varchar2(20), Phone number(7));

To see the structure of the object -Desc Info

Creating Relational Table with User-Defined Type

Using this type in table E. E table becomes a relational table due to the use of Info user defined datatype.

Create table E (Empno number, Emp_Det Info, Sal number);

See the structure of this relational table E

Desc E

To see the attributes in the Desc command for a relational table

To see the attributes and the datatypes of the user defined datatype set describe depth 2

Desc E

Inserting data in the table E

Insert into EValues (1, Info(‘abc’,’kothrud’,’Pune’,7876), 7000);

Page 95: PLSQL Course Ware

System Consultant

95

Validations to the Column of user defined datatype—Only Not Null can be given.

create table f57 (a number, b info not null)

Note – Primary key, Unique, Foreign Key and check constraint cannot be given to the column of user defined data type.

Constraint can be given to the attributes of the column for that specific table.For the name attribute of det column giving constraint –Syntax -- ColumnName.AttributeName

create table j1 (roll number, det info, constraint ccc unique(det.name));

Accessing the values of the attribute columns -

To see the name and city for Empno 1 --- To view an attribute’s value from user-defined types, dot notation is used Alias name is a must for the table Values of the tables can be referred using dot notation prefixed with table alias

Select X.Emp_Det.Name, X.Emp_Det.City, Empno from E X where Empno = 1;

To see the records when the condition is having an attribute column -

Select * from E X where X.Emp_Det.Name = ‘abc’;

Page 96: PLSQL Course Ware

System Consultant

96

Altering types

Dropping the type—To drop a type first all the tables in which that type is used should be dropped , then only the type can be dropped.

User_Types is the in built table for type information.select type_name,typecode from user_types;

Altering types –

The attribute’s data type size can be increased at any time.

create or replace type h as object (x number(3), y number(4));

/*Can increase the size.*/alter type h modify attribute x number(10);

/*Cannot decrease the size. */alter type hmodify attribute x number(9);

Once a attribute is defined in the type then in future it’s data type cannot be changed. Only its size can be increased.

Can drop an attribute provided the type is not used in a table.

alter type hdrop attribute x;

Adding an attribute after type creation.create or replace type t1as object(a number);

alter type t1add attribute b number;

Page 97: PLSQL Course Ware

System Consultant

97

VARRAY

Also known as varying arrays It is an aggregation of values stored in a single column A single column in the database would point to a group of elements Can associate a single identifier with an entire collection Can reference the entire collection as a whole or access the elements individually To access individual elements, use standard subscripting syntax i.e.

array_name(subscript) Maximum size must be specified at time of definition Index has a fixed lower bound of 1 and an extensible upper bound A varying array allows to store repeating attributes of a record in a single

row.

Steps for Creating VARRAYs Create a type which will hold information for a single line item Create an array of type known as Varray type, holding multiple values of a

particular type Create a table having one of the columns, known as varray column, based on the

Varray type

The SYNTAX for creating a VARRAY

CREATE TYPE <varray_type_name>AS VARRAY(limit) OF <type>;

Example – In a factory table there are workers using different tools. Each worker is using say 3 numbers of tools. Thus if a single worker is taking 3 tools then that worker’s name will come thrice in the table. So there will be data redundancy. Varrays will repeat values that change for a particular column which will save the storage space.

A set of rows is repeated in one column in varray. Step 1 – Create an varray holding 3 elements of varchar2(20).

create or replace type TOOLS_VA as varray(3) of varchar2(20);

Step 2 - Create a table having one of the column as the varray column based on the varray type.

create table factory (name varchar2(20) primary key, tools TOOLS_VA);

Page 98: PLSQL Course Ware

System Consultant

98

Step 3 – Inserting record in the factory table

Insert into factory values ('John', TOOLS_VA ('Hammer', 'Sledge', 'Drill'));Insert into factory values ('Smith', TOOLS_VA ('Screw Gauge', 'Hammer', 'AX'));Insert into factory values ('Martin', TOOLS_VA (null, 'Sledge', null));

To see names of tools for each worker.

select F.Name, V.* from Factory F, TABLE(F.Tools) V;

V is an alias table created for the tool names. TABLE function is used to simplify the process of selecting data from varying arrays.

Conditional records

To see records of persons having Hammer tool

select F.Name, V.* from Factory F, TABLE(F.Tools) Vwhere V.Column_Value = 'Hammer'

Summary records

To see count of tools for each person

select F.Name, Count(Column_Value) from Factory F, TABLE(F.Tools) VGroup By F.Name

Updating VARRAYs

Individual elements cannot be updated Entire VARRAY has to be updated if one of the elements has to be changed

To change the value of first index tool of Martin from null to Vernier C

update factoryset tools = tools_va('Vernier C','Sledge', NULL)where name = 'Martin';

Page 99: PLSQL Course Ware

System Consultant

99

Creating customized and advance report using PL/SQL blocks

Displaying data from the varray column –declare cursor cf is select * from factory; vcf cf%rowtype;begin for vcf in cf loop /*This loop is for the normal column name.*/ dbms_output.put_line('Contact Name '|| vcf.name); for i in 1..vcf.tools.count loop /*This loop is for the number of tools for the current row's name*/ dbms_output.put_line('-------------' || vcf.tools(i)); end loop; dbms_output.put_line('----------------------------------'); end loop;end;/------------------------------------------------------------------------------------------------------Displaying status for each record whether Hammer is given or not—declare cursor cf is select * from factory; vcf cf%rowtype; x number;begin for vcf in cf loop x := 0; dbms_output.put_line('Contact Name -- '|| vcf.name); for i in 1..vcf.tools.count loop if vcf.tools(i) = 'Hammer' then x := x + 1; end if; end loop; if x > 0 then dbms_output.put_line('Hammer is supplied'); else dbms_output.put_line('Hammer is not supplied'); end if; dbms_output.put_line('--------------------------- ');

Page 100: PLSQL Course Ware

System Consultant

100

end loop;end;/ To display the second tool provided for each persondeclare cursor cf is select * from factory; vcf cf%rowtype; x number;begin for vcf in cf loop x := 0; dbms_output.put_line('Contact Name -- '|| vcf.name); for i in 1..vcf.tools.count loop if i = 2 then dbms_output.put_line(vcf.tools(i)); end if; end loop; x := x + 1; end loop;end;/

Displaying the names of workers who have been given shafts.declare cursor cf is select * from factory; vcf cf%rowtype; countOfShaftHolders number;begin dbms_output.put_line('The Shaft holders are --> '); countOfShaftHolders := 0; for vcf in cf loop for i in 1..vcf.tools.count loop if vcf.tools(i)='Shaft' then dbms_output.put_line(vcf.name); countOfShaftHolders := countOfShaftHolders + 1; end if; end loop;

Page 101: PLSQL Course Ware

System Consultant

101

end loop; if countOfShaftHolders = 0 then dbms_output.put_line('Sorry, there are no shaft holders'); end if; end;

Page 102: PLSQL Course Ware

System Consultant

102

Creating a varray from a type

Multiple attributes for a single record and multiple sets of attributes for a single record.

create or replace type Monthly_Sales as Object (Month Varchar2(3), Sales Number(6)); /

create or replace type Monthly_Sales_VA as varray(4) of Monthly_Sales; /

create table city_details(name varchar2(15), performance Monthly_Sales_VA)/

Insert into city_detailsvalues('Pune', Monthly_Sales_VA(Monthly_Sales('Jan',9000), Monthly_Sales('Feb',7500), Monthly_Sales('Mar',8000), Monthly_Sales('Apr',10000)) )/

select A.name, V.* from city_details A, TABLE(A.Performance) V;

To see details of varray query the view user_coll_types

select type_name,COLL_TYPE, UPPER_BOUNDfrom user_coll_types

Page 103: PLSQL Course Ware

System Consultant

103

Nested Table Table within a table A table is represented as a column within another table There is no limit to the number of rows in the nested table for each

row in the main table. Basically used for mapping master-detail relationships between tables.

i.e. In the parent table there would be one column, which will store the location of the nested table.

Steps for Creating Nested Tables Create a type which will hold information for a single line item (this

represents the nested table details) Create Type of Table to hold details for the multiple rows of the nested

table (this will be the nested details - nested table type) Create the master table with one of the columns which will hold the nested

table typeCreating a Nested Table

SYNTAXCREATE TYPE <nested_table_type_name>AS TABLE OF <typename>;

Example --There is main table Fare_Tab1. It has columns such as Route_Coe,Route_Desc,Origin,Destination, Firts_Fare, Bus_Fare,Eco_Fare and journey_hrs.There is a type as table Fs_Nst_Type. This type table holds column such as Flightno, Airbusno,Deprt_Time, Flight_Day1 and Flight_Day2.

Now we are trying to establish the relation between Fare_Tab1 table and this type table Fs_Nst_Type.

One route_code from Fare_Tab1 table can hold multiple Flightno, Airbusno,Deprt_Time, Flight_Day1 and Flight_Day2. For this purpose we will create a column in Fare_Tab1 table which will show details of the Fs_Nst_Type for a particular route_code. So that column actually represents the nested table.

Page 104: PLSQL Course Ware

System Consultant

104

Step 1 -- Create a type Flight_Sch_type to hold details for a single flight.

Create or replace type Flight_Sch_Type as OBJECT(Flightno char(4), Airbusno char(4), Deprt_time char(6),Flight_day1 number(1),Flight_day2 number(1));

Step 2 -- Create a type of table which will hold the multiple rows of the nested table.

Create type Fs_Nst_Type as TABLE of Flight_Sch_Type;

Step3 -- Create the main table which will have the nested table through a column of the main table

Create table Fare_Tab( Route_Code char(7), Route_Desc varchar2(30), Origin varchar2(15), Destination Varchar2(15), First_fare number(5), Bus_Fare number(5), Eco_Fare number(5), Journey_Hrs char(5), Flight_Sch_Det Fs_Nst_Type) Nested Table Flight_Sch_Det store as Fs_Store_Tab;

Fs_Store_Tab is system generated table for oracle's reference.

Inserting records in the nested table through the main table

SYNTAXINSERT INTO <master_table_name>VALUES(<master_table_column1_value>,…

<master_table_columnN_value,nested_table_type(nested_column(attribute1_value>,...<attributeN_value>),nested_column(attribute1_value>,…

<attributeN_value>)));

Page 105: PLSQL Course Ware

System Consultant

105

Insert into Fare_TabValues ('Goa-Ban', 'Goa - Bangalore', 'Goa', 'Bangalore', 450, 300, 200, 3, Fs_Nst_Type ( Flight_Sch_Type('F2', 'AB01',' 9:00',1,3), Flight_Sch_Type('F3','AB02', '11:00', 3, 5) ) );

Here in this insert statement for one route_code 'Goa-Ban' 2 nested rows of F2 and F3 are inserted.

Displaying the data of the nested table columns --

SYNTAX in Oracle 8iSELECT <master_table_columns>,<nested_alias>.<attributes_from_type>FROM THE (SELECT <nested_column>FROM <master_table>WHERE <master_table_condition>) <nested_alias>, <master_table>WHERE <nested_table_condition>;

To display the nested row for the route code 'Goa-Ban' for flighno F1

Select NT.flight_day1, NT.flight_day2 ,Nt.Deprt_Time, route_code from THE (Select Flight_Sch_Det from Fare_Tab1 where route_code = 'Goa-Ban') NT, Fare_Tab1 where NT.Flightno = 'F2';

In Oracle 9i Table function is used instead of THE clause which makes the query very easy to understand

select route_code, NT.flight_day1, Nt.flight_day2,NT.Deprt_Time,NT.flightno from Fare_Tab, Table(Fare_Tab.Flight_Sch_Det) NT where route_code = 'Goa-Ban' And NT.flightno = 'F3'

So Syntax in 9i isSelect master_table_cols, Alias.Neste_Table_ColsFrom Master_Table, Table(Master_Table.Nested_Table) Alias

To see all attribute columns of the Nested Table we can use * with alias name of the nested table –select route_code, NT.*from Fare_Tab1, Table(Fare_Tab1.Flight_Sch_Det) NTwhere route_code = 'Goa-Ban' And NT.flightno = 'F3'

Page 106: PLSQL Course Ware

System Consultant

106

Updating the nested row in 8i

SYNTAXUPDATE THE (SELECT <nested_column>FROM <master_table>WHERE <master_table_condition>) <nested_alias>SET <nested_alias>.<attribute1_name> = <value>,...,WHERE <nested_table_condition>;

To change the value of flight_day1 from 3 to 5 for the Flightno F3 on the route_code 'Goa-Ban'

Update THE (Select Flight_Sch_Det from Fare_Tab1 F where F.route_code = 'Goa-Ban') NT Set NT.Flight_day1 = 5 where NT.Flightno = 'F3';

F is the alias name for the master table Fare_TabNT is the alias name for the nested table.

In 9i the same Update statement will be as follows –

To change the Flightno of the nested table to F11

update TABLE(select FLIGHT_SCH_DET from Fare_Tab where route_code = 'Goa-Ban') NTSet NT.Flightno = 'F11'where NT.Flight_Day2 = 5;

Syntax in 9i –

Update TABLE(select nested_table_name) From Master_Table Where master_table condition) Alias for Nested_Table Set Alis.Nested_Col = <new value>Where Alias.Nested_Col Condition;

Page 107: PLSQL Course Ware

System Consultant

107

Deleting a row from the nested table

SYNTAX in 9iDELETE FROM THE (SELECT <nested_column>FROM <master_table>WHERE <master_table_condition>) <nested_alias>WHERE <nested_table_condition>;

To delete the details of flightno 'F2' for the route_code 'Goa-Ban'

Delete From THE (Select Flight_Sch_Det from Fare_Tab1 F where F.Route_Code = 'Goa-Ban') NT where NT.Flightno = 'F2';

Deleting a row in 9i – To delete a nested row of Flight_day2 having value 5 for a route_code ‘Goa-Ban’

Delete Table(select FLIGHT_SCH_DET from Fare_Tab where route_code = 'Goa-Ban') NT where NT.Flight_Day2 = 5;

Inserting a nested row to route_code ‘Goa-Ban’ – (9i)

Insert into TABLE (Select FLIGHT_SCH_DET from Fare_Tab where route_code = 'Goa-Ban')Values(Flight_Sch_Type ('F22','AB02','3',3,5))

To see number of records in the nested table

select count(*) from Fare_Tab, Table(Fare_Tab.Flight_Sch_Det) NT;

Page 108: PLSQL Course Ware

System Consultant

108

Difference Between VARRAYs and Nested Tables

VARRAYs Maximum size specified at

time of definition Data is stored in-line Retain their ordering and

subscripts when stored in database

Nested Tables No maximum size Data is stored out-of-line in a

store table Do not retain ordering and

subscripts when stored in database

When to use Nested Tables instead of VARRAYs

When the order of the data elements is not important When indexing is required on an attribute of the nested table type When there is no set limit to the number of entries for the data elements When the data elements need to be queried

Page 109: PLSQL Course Ware

System Consultant

Bfile and LOBsBfile – Binary file (text, sound, image or video) is stored outside the database. The locator to that file is stored in the database. Bfile data is read only for oracle.

LOB – BLOB and CLOB are the tow types of LOBs. B is binary and C is character data. LOB files are stored inside the database. Since the files are inside db, they can be manipulated thorough oracle. A max of 4GB data can be stored in a BLOB or CLOB data type.

Directory is a non-schema object owned by “SYS” user. It is used for managing the operating system files (that are external to oracle). Directory object will help to write data into external file or read data from an external file.

BfileName function – It initializes a Bfile column to point to an external file. Use the BfileName function as part of an Insert statement to initialize a Bfile column by associating it with a physical file in the server file system. A Bfile can be initialized to NULL and updated later by using the BFILENAME function.

FileOpen -- To open an external file.

LOADFROMFILE – To load Bfile data into an internal LOB.

Empty_CLOB – It is a special function, which can be used in Insert or Update statement of SQL DML to initialize a NULL.

FileClose – To close an external file

Example of Reading data from a Bfile and writing it in Oracle

Step 1- There is file mytextfile.txt in C:\MyData path. The mytextfile.txt has some sample text.

Step 2 – A user should have create any directory and read directory privileges. These privileges are taken from SYS user.

Step 3 - Create directory

109

Page 110: PLSQL Course Ware

System Consultant

Step 4 – Create a table mytable with two fields file_id and file_data

Create table mytable(file_id number, file_data clob);

Step 5 – A procedure will take file_id and filename from user and transfer data of that file into the table mytable.

110

Page 111: PLSQL Course Ware

System Consultant

CREATE OR REPLACE PROCEDURE insertclob (p_file_id number, filename VARCHAR2)AS v_clob CLOB; v_bfile BFILE;BEGIN INSERT INTO mytable VALUES (p_file_id,empty_clob()); COMMIT; v_bfile:=BFILENAME('EXTERNAL_FILE11',filename);

select file_data INTO v_clob FROM mytable WHERE file_id=p_file_id FOR UPDATE; DBMS_LOB.FILEOPEN(v_bfile); DBMS_LOB.LOADFROMFILE(v_clob,v_bfile,DBMS_LOB.GETLENGTH(v_bfile)); DBMS_LOB.FILECLOSE(v_bfile);END;/

Now execute the procedure by providing file id and file name

exec insertclob(1,'mytextfile.txt');

The data of mytextfle.txt has been transferred in the file_data column

111

Page 112: PLSQL Course Ware

System Consultant

(Note – In a session, the number of BFILEs that can be opened in one session is limited by the parameter session_max_open_files and total number of files that can be open is limited by the parameter max_open_files. These parameters are to be setted in the init.ora filesession_max_open_files=10max_open_files=20)

The DBMS_LOB.READ ProcedureReads data from LOB starting at specified offset

DBMS_LOB.READ(loc, num, offset, buff)

Whereloc is locator of the LOBnum is number of bytes/characters to be readoffset is offset in bytes/characters from the start of the LOBbuff is output buffer for the read operation

Example – To retrieve a part of data from the first record’s file_data column

declarev_clob clob;num number;offset number;vstore varchar2(20);beginnum := 7;offset :=1;select file_data into v_clobfrom mytable

112

Page 113: PLSQL Course Ware

System Consultant

where file_id = 1;DBMS_LOB.READ(v_clob,num,offset,vstore); dbms_output.put_line(vstore);end;/

The DBMS_LOB.GETLENGTH FunctionGets the length of the LOB value

DBMS_LOB.GETLENGTH(loc)

Whereloc is locator of the LOB

Example – To get the length of the file_data

declare loc clob; len number;Begin select file_data into loc from mytable where file_id = 1; len := DBMS_LOB.GETLENGTH(loc); dbms_output.put_line(len);end;/

The DBMS_LOB.WRITE Procedure

Writes data to the LOB from specified offsetDBMS_LOB.WRITE(loc, num, offset, buff)

Whereloc is locator of the LOBnum is number of bytes/characters to writeoffset is offset in bytes/characters from the start of the LOB for write operation

113

Page 114: PLSQL Course Ware

System Consultant

buff is input buffer for the write operation

Example of Write and getLength function –--DBMS_LOB.Write and getLength Functions-- To add some text to CLob.-- It is going to update the original clob--Syntax DBMS_LOB.Write(Source, Length of new text, From which character or point to be added, New Text)

Declare loc clob; num number; offset number; vstore varchar2(80); lenlob number; vlen number; Begin -- In the Select statement For Update clause is must, so that the row gets locked. select file_data into loc from mytable where file_id=1 for update; -- To get the total number of characters in a lob. -- Use getlength function of DBMS_LOB lenlob := DBMS_LOB.getLength(loc); -- vstore is having the additional text vstore := 'This is new line'; -- Now the length of the new text to be added should also be known since that value is one vlen := Length(vstore); -- Length of the new text in vstore variable offset := lenlob + 1; -- Due to +1 in offset the text starts from --one space next DBMS_LOB.Write(loc,vlen,offset,vstore); end;/

exec insertclob(2,'mytextfile.txt');

114

Page 115: PLSQL Course Ware

System Consultant

Example1of Erase method –

DBMS_LOB.Erase

Syntax - DBMS_LOB.Erase(Source, No. of characters to erase, Position from where it has to erase)

To remove some text from clob columnRemoving the first 5 characters of file_data column for file_id 2

Declare loc clob; num number; offset number;Begin num := 5; offset := 1;

select file_data into loc from mytable where file_id = 1;

DBMS_LOB.Erase(loc,num,offset);End;/

115

Page 116: PLSQL Course Ware

System Consultant

116

Page 117: PLSQL Course Ware

System Consultant

TRIGGERS

It is a stored PL/SQL program unit associated with a specific database table

Oracle executes (fires) the trigger automatically whenever a given SQL operation affects the table

They are invoked implicitly They are useful for customizing a database They should be used only when necessary Can automatically generate derived column values Can prevent invalid transactions Can enforce complex security authorizations Can enforce referential integrity across nodes in a distributed database Can enforce complex business rules Can provide transparent event logging Can provide sophisticated auditing Can maintain synchronous table replicates Can gather statistics on table access Can derive column values automatically Can restrict DML operations to regular business hours

Syntax --CREATE [OR REPLACE] TRIGGER <triggername>BEFORE|AFTERINSERT|DELETE|UPDATE OF <columnnames> ON <tablename>[FOR EACH ROW]WHEN (<condition>)<PL/SQL Block>

Name in the ON clause identifies the database table associated with the triggerThe trigger event specifies the SQL DML statement (INSERT, DELETE or UPDATE) that affects the tableAFTER specifies that the trigger fires after the manipulation is done

BEFORE specifies that the trigger fires before the manipulation is done

By default, a trigger fires once per table FOR EACH ROW specifies that the trigger fires once per row

117

Page 118: PLSQL Course Ware

System Consultant

For the trigger to fire, the Boolean expression in the WHEN clause must evaluate to TRUE

REPLACE can be added to the CREATE statement to drop and re-create the trigger automatically

CREATE TRIGGER flight_updateAFTER INSERT ON reservationFOR EACH ROWBEGINIF :new.class = ‘F’ THENstatements;ELSIF :new.class = ‘B’ THENstatements;END IF;END;

Prefix :new is a correlation name that refers to the newly updated column value

Within a trigger, the :new and :old values of changing rows can be referenced

A single trigger can handle more than one operation Use conditional predicates to identify the type of statement used to

invoke the section of code

Examples of Triggers - Row Level AFTER clause

1)-- Main tablecreate table tempasselect * from emp;

-- Table to transfer inserted recordcreate table instempasselect ename,sal

118

Page 119: PLSQL Course Ware

System Consultant

from empwhere 1=2;

Whenever a row is inserted in the temp table then that new row should be transferred in the instemp table

Create or replace trigger trig1After INSERT on tempFor Each RowBegin Insert into InsTemp Values(:new.ename, :new.sal); Dbms_output.put_line('Record inserted');End;

2 ) Table to transfer deleted recordcreate table deltempasselect ename,salfrom empwhere 1=2;--Whenever a row is deleted from temp table then that row should be transferred --in Deltemp table

Create or replace trigger Trig2After DELETE on TempFor Each RowBegin Insert into Deltemp Values(:old.ename, :old.sal);End;

3) Table to transfer the old record before updations

create table uptempasselect ename,salfrom emp

119

Page 120: PLSQL Course Ware

System Consultant

where 1=2;

Whenever a record is updated from the temp table then the old record shoul go in uptemp table

create or replace trigger trig3After UPDATE on tempFor Each RowBegin Insert into Uptemp Values(:old.ename, :old.sal);End;

Referencing old and new values with some other identifier.

create or replace trigger on1after insert on tempreferencing old as o new as nfor each rowbegin if :n.sal <= 4000 then raise_application_error(-200012,'sss'); end if;end;

Use Of Before Clause1) When a new record is inserted then it should have sal >= 5000

Create or replace trigger trig7Before INSERT on tempFor Each RowBegin If :new.sal < 5000 then raise_application_error(-20009,'New record sal should be above 5000'); End If;End;

2) --To prevent user from deleting records of sal >= 3500

120

Page 121: PLSQL Course Ware

System Consultant

Create or replace trigger trig4Before DELETE on tempFor Each RowBegin if :old.sal >= 3500 Then raise_application_error(-20005,'Cannot delete records of sal greater than or equal to 3500'); End if;End;

3) If a salary is updated then it should be always greater than the old salary.

create or replace trigger check_salbefore update of salon tempfor each rowbeginif :new.sal < :old.sal then raise_application_error(-20009,'Not possible');end if;end;

4) Whenever a new record is inserted then the cost value should be always greater than all the existing cost values in the table.

create table cost_chart(year varchar2(20) unique, cost number);

create or replace trigger check_costbefore insert on cost_chartfor each rowdeclare v_cost number;begin select max(cost) into v_cost from cost_chart; if :new.cost < v_cost then raise_application_error(-20010,'Cost cannot be less than the previous cost');end if;end;

121

Page 122: PLSQL Course Ware

System Consultant

Use of When Cluase

create or replace trigger useofwhenafter insert on tempfor each rowwhen (new.job = 'CLERK')

/*After any clerk record is inserted in the temp table, the date and time of entry will be inserted in the table recofclerk*/

begininsert into recofclerkvalues(sysdate, to_char(sysdate,'hh:mi:ss'));dbms_output.put_line('All the tables are populated.');end;

Demo of sequence of execution of row level and statement level triggers

create table trigtab(a number);

create or replace trigger tt1before insert on trigtabbegindbms_output.put_line('Before statement level');end;

create or replace trigger tt2before insert on trigtabfor each rowbegindbms_output.put_line('Before row level');end;

create or replace trigger tt3after insert on trigtabfor each rowbegindbms_output.put_line('After row level');

122

Page 123: PLSQL Course Ware

System Consultant

end;

create or replace trigger tt4after insert on trigtabbegindbms_output.put_line('After Statement level');end;

Statement OR Table Level Triggers

1) -- To prevent a new record to be inserted in temp table

create or replace trigger trig6Before INSERT on tempBegin raise_application_error(-20006,'Cannot insert a new record');End;

2) -- To prevent any record to get deleted from temp table

create or replace trigger trig8Before DELETE on tempBegin raise_application_error(-20011,'Cannot delete');End;

3) -- No transaction should take place on SUNDAY

create or replace trigger trig9 Before INSERT or UPDATE or DELETE on temp Begin If to_char(Sysdate,'DAY') = 'SUNDAY' Then raise_application_error(-20015,'No transactions on Sunday'); End If; End;

123

Page 124: PLSQL Course Ware

System Consultant

4) Whenever a record is deleted from emp table then the count of records remaining should be refreshed in the a log table count_emp

create table count_emp (no_of_records number);

create or replace trigger EmpCountAfter Delete On EmpDeclare n number;Begin select count(*) into n from emp; Delete from count_emp; Insert into count_emp values(n); dbms_output.put_line('There are now ' || n || ' employees in theemp table');end;

124

Page 125: PLSQL Course Ware

System Consultant

Combining DML events in one Trigger

--Combining all 3DML in one Begin block--Any DML should be traced in the table KeepTracecreate table KeepTrace(username varchar2(30), Operation varchar2(30), Date_of_Operation date, Time_of_operation varchar2(40));

Create or replace trigger trig10 After INSERT or DELETE or UPDATE On TempFor each row Begin If Inserting Then Insert into KeepTrace Values(user, 'Record is Inserted', Sysdate, to_char(sysdate,'hh:mi:ss')); ElsIf Deleting Then Insert into KeepTrace Values(user, 'Record is Deleted',Sysdate, to_char(sysdate,'hh:mi:ss')); ElsIf Updating Then Insert into KeepTrace Values(user,'Record is Updated',Sysdate, to_char(sysdate,'hh:mi:ss')); End If;End;

125

Page 126: PLSQL Course Ware

System Consultant

Calling a procedure inside a trigger –

create table EmpSummary(Total_Salary number);

Procedure Code –

create or replace procedure TotSalisvsal number;Begin delete from EmpSummary; Select sum(sal) into vsal from emp; Insert into EmpSummary Values(vsal);End;

create or replace trigger EmpUpdatesAfter insert or update on emp

CALL TOTSAL

Mutating table errorWhen a row level trigger is based on a table then the trigger body cannot read data from the same table. Also DML on the same table is not possible.

create or replace trigger trig11 after delete on temp1 for each row declare x number; begin select sal into x from temp1 where ename = 'SMITH'; dbms_output.put_line(x); end;

delete from temp1;

126

Page 127: PLSQL Course Ware

System Consultant

create or replace trigger trig11 after delete on temp1 for each row begin insert into temp1 (empno,ename) values(78,'pqr'); end;

delete from temp1 where ename = 'KING';

For a statement level trigger there will be no error.

create or replace trigger trig11 after delete on temp1 declare x number; begin select sal into x from temp1 where ename = 'SMITH'; dbms_output.put_line(x); end;

delete from temp1where ename = 'MARTIN';

create or replace trigger trig11 after delete on temp1 begin insert into temp1 (empno,ename) values(78,'pqr'); end; /

delete from temp1 where ename = 'KING';

127

Page 128: PLSQL Course Ware

System Consultant

On Update Cascade

Similar to on delete cascade built in for primary and foreign key integrity.

create table st(roll number, name varchar2(40));

create table res(roll number, marks number);

insert into st values(1,'A');insert into st values(2,'B');insert into st values(3,'C');insert into res values(1,90);insert into res values(2,92);insert into res values(3,94);

Commit;

create or replace trigger on_update_cascadeafter update of roll on stfor each rowBegin Update res set res.roll = :new.roll where res.roll = :old.roll;End;

128

Page 129: PLSQL Course Ware

System Consultant

Instead Of Triggers

Provides a transparent way of modifying views that cannot be modified directly through INSERT, UPDATE or DELETE statements because underlying tables contain joins

It is called INSTEAD OF because Oracle fires the trigger instead of the triggering statement(s)

Users can be transparent to the trigger because they write normal DML statements against the view and the INSTEAD OF trigger is used to take care of the modifications

It can be placed on Object Views to insert, update or delete data in the underlying relational tables

CREATE TRIGGER emp_insertINSTEAD OF INSERT ON emp_viewBEGINstatements;END;

1) Example on Instead of Update on View - --Instead of triggers can be used only with views.--Effective for joins which are based on equi join-- To have an cascading effect of update on both the tables if columns are --matching--Also to update uncommon columns through equi join views--Step 1 Creating tables s and r;create table s(rollno number,name varchar2(20));create table r(rollno number,marks number);

--Step 2 Inserting records in s and r.insert into svalues(1,'a');insert into svalues(2,'b');

insert into r

129

Page 130: PLSQL Course Ware

System Consultant

values(1,90);insert into rvalues(2,87);

--Step 3 Creating an Equijoin View on s and r

Create or replace view SRasselect s.rollno,s.name,r.marksfrom s,rwhere s.rollno =r.rollno;

--Step 4 Now creating the Instead of Trigger for update on the view SR

Create or replace trigger tig12 Instead Of UPDATE on SR For Each Row Begin /* Updating roll numbers from both the tables s and r */ Update s set rollno = :new.rollno where rollno = :old.rollno; Update r set rollno = :new.rollno where rollno = :old.rollno;

/* Updating name column of s table through view.*/ Update s set name = :new.name where name = :old.name;

/*Updating marks column of r table through view.*/ Update r set marks = :new.marks where marks = :old.marks; End;--

130

Page 131: PLSQL Course Ware

System Consultant

2) Example of Instead of InsertCreate or replace trigger tig14 Instead Of INSERT on SR For Each Row Begin /*Inserting the new record into both the tables s and r.*/ Insert into s values(:new.rollno, :new.name); Insert into r values(:new.rollno, :new.marks);

End;

3) Example of Instead of Delete

create or replace trigger trig15Instead of DELETE on SRFor Each RowBegin /*Deleting the record from both the tables s and r.*/

Delete from s where rollno = :old.rollno; Delete from r where rollno = :old.rollno;

End;

131

Page 132: PLSQL Course Ware

System Consultant

DDL EVENT TRIGGERS (Can be created by DBA)

1) To prevent Scott from dropping table TTcreate or replace trigger prevent_dropBefore Drop on Scott.SchemaBegin If ora_dict_obj_owner = 'SCOTT' and ora_dict_obj_name = 'TT' and ora_dict_obj_type = 'TABLE' Then raise_application_error(-20020,'Cannot drop table TT'); End If;End;

2) --To keep a track of Scott new objects --The new objects should get added in a table ScottObjects --ScottObjects is owned by DBA

create table ScottObjects(Object_name varchar2(30), Date_of_Creation date);

create or replace trigger Put_New_ObjsAfter CREATE ON Scott.SchemaBegin Insert into ScottObjects Values(ora_dict_obj_name,Sysdate);End;

3) --To keep a track of Scott's dropped objects --The dropped objects should get added in a table ScottDrop

create table ScottDrop(Object_name varchar2(30), Date_of_Creation date);

132

Page 133: PLSQL Course Ware

System Consultant

create or replace trigger Put_Drop_ObjsAfter DROP ON Scott.SchemaBegin Insert into Scottdrop Values(ora_dict_obj_name,Sysdate);End;4) --Preventing Scott to drop column h2 of table hh --Step 1 Login as scott--create table hh--(h1 number,--h2 number,--h3 number);

-- Step 2 Log in as sysdba

Create or Replace Trigger Prev_Drop_ColBefore ALTER on Scott.SchemaBegin If ora_dict_obj_name = 'HH' and ora_is_drop_column('H2') Then raise_application_error(-20067,'Cannot drop column h2'); End If;End;

5) --To prevent Scott from modifying the data type of column h3 of hh table --Log in as DBAcreate or replace trigger Prev_ModifyBefore ALTER on Scott.SchemaBegin If ora_dict_obj_name = 'HH' and ora_is_alter_column('H3') Then raise_application_error(-20045,'Cannot modify column H3'); End If;End;

133

Page 134: PLSQL Course Ware

System Consultant

Assignments

Note – All the programs are based on the demonstration tables emp and dept. Before executing the queries please ensure that the standard records (default) are present.

1) If the 4th record in the emp table of the job ‘MANAGER’ then display the entire record, (each value separated by an hyphen). If the fourth record is not of MANAGER then display message ‘Manager record not found’.

2) Display the names of the top 3 salary figures from the emp table.

3) Calculate the compound interest and display it if the principal amount is 50000, rate of interest is 5 % and duration is 7 years.

4) Accept job type from the user. Display the message depending upon whether no rows or one row or several rows are selected. The message should be any one from the below 3 as per the situation. JOB TYPE FOUND ONCE JOB TYPE FOUND MORE THAN ONCE JOB TYPE NOT FOUND

5) Display the records of the emp table in the reverse order. It means the last record should be displayed first and the first record should be displayed at the last.

6) Check whether the 3rd Clerk’s salary is greater than the 2nd Clerk’s salary. If it is so, then display message as “ Third has more salary than the second” otherwise display message as “Second has more salary than the first”

7) Display the highest salary programmatically without using the max() function

8) Display the lowest salary programmatically without using the min() function

9) Display the sum of first five sum of the salary.

10) Accept empno from the user. If the salary is less than 1500, increase it by 1000. If the salary is equal to 1500, increase it by 1500. If the salary is greater than 1500, increase it by 2500. Ensure that run time errors are properly taken care of.

11) The management has decided to increase salary of employees by 10%. Starting with lowest paid earner and working up. If at any time salary bill exceeds 35000/- then no further employees are to be given an increase. Write a PL/SQL block using CURSOR.

134

Page 135: PLSQL Course Ware

System Consultant

12) Using while loop technique display all the multiples of 7 between 31 and 48.

13) Create a table Inspection_Details that has one column Readings of numeric type. Using pl/sql block add numbers, which has the difference of 0.1. The numbers should be between 0.1 and 6.8.

14) Display the names of the employees who are earning salary less than the average salary of their own jobs.

15) Display the difference of salary between the oldest and the latest employee.

16) Create a procedure that will take department name as a parameter. The procedure should delete the record of the employees from the emp table only for the department name passed.

17) Create a function, which will show 20% of the raised salary for each employee.

18) Create a procedure, which will show the total, highest, lowest and average of the salary for the job. (Job type is the parameter to be passed.)

19) Create a trigger, which will not allow records to be entered between 1 and 2 pm on weekdays.

20) Create one trigger which will allow insert, update and delete for a view which is based on an inner join between tables emp and dept.

21) Create a trigger, which will not allow records getting inserted in table ‘T1’ if the number of records in that table is exceeding 50.

135