Oracle 9i Database Server: PL/SQL
Oracle 9i Database Server: PL/SQL
PL/SQL
Procedural Language/Structured Query
Language
PL/SQL engine
PL/SQL Procedural
PL/SQL PL/SQL statement
block block SQL
executor
Oracle server
Benefits of PL/SQL
Improved performance
PL/SQL can be used to group SQL statements together within a
single block and to send the entire block to the server in a single
call, thereby reducing networking traffic.
SQL
SQL
Application Other DBMSs
SQL
SQL
SQL
IF...THEN
SQL Oracle with
Application ELSE PL/SQL
SQL
END IF;
SQL
Benefits of PL/SQL
Modularize program development
PL/SQL Block Structure
Every unit of PL/SQL comprises one or more blocks.
The basic units (procedures, functions, and anonymous
blocks) make up a PL/SQL program.
…
DECLARE
…
BEGIN
…
EXCEPTION
END;
Modularized Program Development
•Group logically related statements within blocks.
•Nest sub-blocks inside larger blocks to build powerful
programs.
•Break down a complex problem into a set of
manageable, well-defined, logical modules and
implement the modules with blocks.
other benefits are :-
•PL/SQL is portable. Can be invoked from other env.
•You can declare variables
•You can program with procedural language control
structures.
•PL/SQL can handle errors.
Benefits of PL/SQL
Subprograms
Stored procedures and functions have many benefits in
addition to modularizing application development:
•Easy maintenance that enables you to modify:
•Improved data security and integrity.
•Improved performance allows you to :
–Avoid reparsing for multiple users by exploiting
the shared SQL area
–Avoid PL/SQL parsing at run time by parsing at
compile time
–Reduce the number of calls to the database and
decrease network traffic by bundling commands
Invoking Stored Procedures and Functions
Scott LOG_EXECUTION
procedure
1 xxxxxxxxxxxxxx
vvvvvvvvvvvvvv
xxxxxxxxxxxxxx
2 vvvvvvvvvvvvvv
xxxxxxxxxxxxxx
vvvvvvvvvvvvvv
xxxxxxxxxxxxxx
xxxxxxxxxxxxxx
vvvvvvvvvvvvvv
3 vvvvvvvvvvvvvv
xxxxxxxxxxxxxx
xxxxxxxxxxxxxx vvvvvvvvvvvvvv
Oracle vvvvvvvvvvvvvv
xxxxxxxxxxxxxx
Forms vvvvvvvvvvvvvv
xxxxxxxxxxxxxx
Developer vvvvvvvvvvvvvv
xxxxxxxxxxxxxx
vvvvvvvvvvvvvv
4
Scott
PL/SQL Block Structure
DECLARE (Optional)
Variables, cursors, user-defined exceptions
BEGIN (Mandatory)
– SQL statements
– PL/SQL statements
EXCEPTION (Optional)
Actions to perform when errors occur
END; (Mandatory)
…
DECLARE
…
BEGIN
…
EXCEPTION
END;
Block Types
Syntax :
identifier [CONSTANT]* datatype [NOT NULL]*
[:= | DEFAULT expr];
* value must be assigned while declaring
Example :
DECLARE
v_hiredate DATE;
v_deptno NUMBER(2) NOT NULL := 10;
v_location VARCHAR2(13) := 'Atlanta';
c_comm CONSTANT NUMBER := 1400;
v_mgr NUMBER(6) DEFAULT 100;
Photo
(BLOB)
Movie
(BFILE)
NCLOB
LOB Types
BFILE, BLOB, CLOB, and NCLOB let you store blocks of
unstructured data (such as text, graphic images, video clips,
and sound waveforms) up to 4 gigabytes in size.
LOB types store lob locators, which point to large objects
stored in an external file, in-line (inside the row) or out-of-line
(outside the row).
BLOB, CLOB, and NCLOB data is stored in the database, in
or outside the row.
BFILE data is stored in operating system files outside the
database.
•PL/SQL operates on LOBs through the locators.
-For example, when you select a BLOB column value, only
a locator is returned.
•LOB locator includes a transaction ID.
•LOB locator’s change from one transaction to another.
BFILE- to store large binary objects residing on operating
system files outside the database.
•BFILE variable stores a file locator, which points to a large
binary file on the server.
•The locator includes a directory alias, which specifies a full
path name
•BFILEs are read-only.
Boolean Type
BOOLEAN- stores logical values TRUE, FALSE, and NULL
•You cannot insert the values TRUE and FALSE into a
database column.
•Also, you cannot select or fetch column values into a
BOOLEAN variable.
Composite Data Types
1 SMITH 1 5000
2 JONES 2 2345
3 NANCY 3 12
4 TIM 4 3456
VARCHAR2 NUMBER
BINARY_INTEGER BINARY_INTEGER
User-Defined Subtypes
PL/SQL predefines several subtypes in package STANDARD.
For example, PL/SQL predefines the subtypes CHARACTER
and INTEGER as follows:
SUBTYPE CHARACTER IS CHAR;
SUBTYPE INTEGER IS NUMBER(38,0);
Defining Subtypes
SUBTYPE subtype_name IS base_type[(constraint)] [NOT
NULL];
Some examples follow:
SUBTYPE BirthDate IS DATE NOT NULL;
*Examples to be covered:
Scope of an object
PL/SQL Control Structures
IF-THEN Statement IF-THEN-ELSIF Statement
IF condition THEN
sequence_of_statements; IF condition1 THEN
END IF; sequence_of_statements1
ELSIF condition2 THEN
IF-THEN-ELSE Statement
sequence_of_statements2
IF condition THEN ELSE
sequence_of_statements1; sequence_of_statements3
ELSE END IF;
sequence_of_statements2;
END IF;
Boolean type Example
DECLARE
v_flag boolean:=false;
n1 number:=300;
n2 number:=200;
BEGIN
v_flag:=n1>n2;
if v_flag then
dbms_output.put_line('true');
else
dbms_output.put_line('false');
end if;
END;
DECLARE
grade CHAR:=&grade;
BEGIN
CASE grade
WHEN ’A’ THEN dbms_output.put_line(’Excellent’);
WHEN ’B’ THEN dbms_output.put_line(’Very Good’);
WHEN ’C’ THEN dbms_output.put_line(’Good’);
WHEN ’D’ THEN dbms_output.put_line(’Fair’);
ELSE dbms_output.put_line(’No such grade’);
END CASE;
END;
Searched CASE Statement
[<<label_name>>]
CASE
WHEN search_condition1 THEN statements1;
...
WHEN search_conditionN THEN statementsN;
[ELSE sequence_of_statementsN+1;]
END CASE [label_name];
DECLARE
grade CHAR:=&grade;
BEGIN
CASE
WHEN grade=’A’ THEN dbms_output.put_line(’Excellent’);
WHEN grade=’B’ THEN dbms_output.put_line(’Very
Good’);
WHEN grade=’C’ THEN dbms_output.put_line(’Good’);
WHEN grade=’D’ THEN dbms_output.put_line(’Fair’);
ELSE dbms_output.put_line(’No such grade’);
END CASE;
Iterative Control: LOOP and EXIT Statements
There are three forms of LOOP statements: LOOP, WHILE-
LOOP, and FOR-LOOP.
LOOP
LOOP
sequence_of_statements;
END LOOP;
Example:
DECLARE DECLARE
BEGIN BEGIN
Exception Exception
is raised is raised
EXCEPTION EXCEPTION
Exception Exception
is trapped END; END; is not
trapped
Exception
propagates to calling
environment
Predefined Exception Handler
Predefined Exception raised when…
*Examples to be given for
no_data_found,too_many_rows,value_error
OTHERS EXCEPTION HANDLER
Can be used as a generic exception handler.
SQLCODE & SQLERRM Functions
SQLCODE returns the number of the Oracle error for
internal exceptions. You can pass an error number to
SQLERRM, which then returns the message associated with
the error number.
USER-DEFINED EXCEPTIONS
PL/SQL lets you define exceptions of your own.
User-defined exceptions must be declared and must be
raised explicitly by RAISE statements.
How PL/SQL Exceptions Propagate
Procedure RAISE_APPLICATION_ERROR
The procedure RAISE_APPLICATION_ERROR lets you
issue user-defined ORAerror messages from stored
subprograms. That way, you can report errors to your
application and avoid returning unhandled exceptions.
raise_application_error(error_number, message[, {TRUE
| FALSE}]);
error_number is a negative integer in the range
-20000 .. -20999
message is a character string up to 2048 bytes long.
If TRUE, the error is placed on the stack of previous
errors.
If FALSE (the default), the error replaces all previous
errors.
RAISE_APPLICATION_ERROR is part of package
DBMS_STANDARD, and as with package STANDARD, you
do not need to qualify references to it.
An application can call raise_application_error only from
an executing stored subprogram (or method).
When called, raise_application_error ends the
subprogram and returns a user-defined error number and
message to the application.
The error number and message can be trapped like any
Oracle error.
*will be discussed in procedures and triggers topic
Nonpredefined Error
PRAGMA EXCEPTION_INIT
Apart from predefined exception, we can extend the list of exceptions
associated with an Oracle error within our PL/SQL code with the use
of PRAGMA EXCEPTION_INIT keyword.
EXCEPTION PRAGMA is used to associate a named exception with a
particular Oracle error.
This enable us to trap the error specifically, rather than via an
OTHERS handle.
Only one user defined exception can be associated with one Oracle
error with each occurrence of PRAGMA EXCEPTION_INIT.
Yes
DECLARE OPEN FETCH EMPTY? CLOSE
Ex:
cursor emp_cur is
select ename,sal,hiredate,deptno from emp where
deptno=20;
OPENing the Cursor
Opening the cursor executes the query and identifies the
result set, which consists of all rows that meet the query
search criteria.
For cursors declared using the FOR UPDATE clause, the
OPEN statement also locks those rows.
OPEN cursor_name;
Ex:OPEN emp_cur;
OPEN c1(emplname, 3000);
OPEN c1(‘SMITH’, 1500);
OPEN c1(emplname, esal);
Fetching with a Cursor
The FETCH statement retrieves the rows in the result set
one at a time. Each fetch retrieves the current row and
then advances the cursor to the next row in the result
set.
FETCH cursor_name INTO var1,var2,.. or record_list;
Ex:
FETCH c1 INTO my_empno, my_ename, my_deptno;
LOOP
FETCH c1 INTO my_record;
EXIT WHEN c1%NOTFOUND;
-- process data record
END LOOP;
Closing a Cursor
The CLOSE statement disables the cursor, and the result
set becomes undefined.
Once a cursor is closed, you can reopen it. Any other
operation on a closed cursor raises the predefined
exception INVALID_CURSOR.
CLOSE cursor_name;
Ex:
CLOSE emp_cur;
CURSOR attributes
Cursor attributes return information about the execution
of a multi-row query.
%FOUND Attribute: Has a Row Been Fetched?- equates to
TRUE if the last fetch returned a row, or FALSE if the last
fetch failed to return a row.
%ISOPEN Attribute: Is the Cursor Open? - equates to TRUE
if explicit cursor is open; otherwise, %ISOPEN equates to
FALSE. In case of implicit cursors always it equates to
FALSE.
%NOTFOUND Attribute: Has a Fetch Failed? - yields FALSE if
the last fetch returned a row, or TRUE if the last fetch
failed to return a row.
%ROWCOUNT Attribute: How Many Rows Fetched So Far?
yields the number of rows fetched so far. The number is
incremented if the last fetch returned a row.
Examples to be discussed:
Extensibility: that is, they let you tailor the PL/SQL language
to suit your needs.
Modularity: that is, they let you break a program down into
manageable, well-defined modules.
reusability and maintainability: Once validated, a subprogram
can be used with confidence in any number of applications. If
its definition changes, only the subprogram is affected. This
simplifies maintenance.
Abstraction: To use subprograms, you must know what they
do, not how they work.
PL/SQL Procedures
Syntax:
procedure …
BEGIN
EXCEPTION
END;
A simple PL/SQL procedure
To increase the salary of employee
CREATE OR REPLACE PROCEDURE raise_salary (emp_id
INTEGER, increase REAL) is
BEGIN
UPDATE emp SET sal = sal + increase
WHERE empno = emp_id;
commit;
END raise_salary;
Calling a procedure
SQL> EXECUTE RAISE_SALARY(7369,100);
SQL> begin
2 raise_salary(7369,100);
3 end;
4 /
CREATE PROCEDURE calc_bonus (emp_id IN emp.empno
%TYPE, bonus OUT REAL) IS
BEGIN
SELECT sal * 3 INTO bonus FROM emp WHERE
empno = emp_id;
END;
Subprograms must be
declared at the end of a
declarative section after all
other program items.
DECLARE
empid INTEGER:=&EMPNO;
bon NUMBER;
PROCEDURE calc_bonus (emp_id in INTEGER, bonus out
REAL) IS
hire_date date;
BEGIN
SELECT sal * 3,hiredate INTO bonus,hire_date
FROM emp WHERE empno = emp_id;
IF months_between(sysdate,hire_date) > 60 THEN
bonus := bonus + 500;
END IF;
END;
BEGIN
calc_bonus(empid,bon);
dbms_output.put_line('Bonus='||bon);
END;
Default Values for Subprogram Parameters
create_dept;
create_dept(’MARKETING’);
create_dept(’MARKETING’, ’NEW YORK’);
you cannot skip a formal parameter by leaving out its
actual parameter.
create_dept(‘NEW YORK’); -- incorrect
You cannot solve the problem by leaving a placeholder for
the actual parameter.
create_dept(, ’NEW YORK’); -- not allowed
In such cases, you must use named notation, as follows:
create_dept(new_loc => ’NEW YORK’);
Dropping Procedures
Dropping Functions
DROP FUNCTION function_name
Comparing Procedures
and Functions
Procedures Functions
Execute as a PL/SQL Invoke as part of an
statement expression
Do not contain RETURN Must contain a RETURN
clause in the header clause in the header
Can return none, one, Must return a single value
or many values
Can contain a RETURN Must contain at least one
statement RETURN statement
Overview of Packages
Packages:
•Group logically related PL/SQL types, items,
and subprograms
•Consist of two parts:
–Specification
–Body
•Cannot be invoked, parameterized, or nested
•Allow the Oracle server to read multiple
objects into memory at once
Components of a Package
Public variable
Package
specification Procedure A
Public procedure
declaration
Private variable
Procedure B Private procedure
Package definition
body
Procedure A Public procedure
definition
Local variable
Package Body
Package for handling employees
DECLARE
emp_rec emp%ROWTYPE;
BEGIN
OPEN emp_stuff.c1;
LOOP
FETCH emp_stuff.c1 INTO emp_rec;
EXIT WHEN emp_stuff.c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(emp_rec.ename||','||
emp_rec.job||','||emp_rec.sal);
END LOOP;
CLOSE emp_stuff.c1;
END;
Overloading
Package Specification
declare
addr1 address_type;
begin
addr1:=address_type(20,'JAYANAGAR','DELHI',787889);
dbms_output.put_line(addr1.getresno||,||addr1.street||,||
addr1.city||,||addr1.phone);
end;
Adding an attribute to an existing object type
alter type address_type add attribute(state varchar2(20))
cascade;
When a new row is inserted the existing data will be NULL
for that column attribute.
Adding an method to an object type
ALTER TYPE ADDRESS_TYPE ADD MEMBER
FUNCTION GETSTATE RETURN VARCHAR2 CASCADE
Dropping attribute from an object type
ALTER TYPE ADDRESS_TYPE DROP ATTRIBUTE
STATE CASCADE
OBJECT TABLES
... ...
BINARY_INTEGER Scalar
Example :
DECLARE
TYPE IntDataTyp IS TABLE OF integer
INDEX BY BINARY_INTEGER;
inttab IntDataTyp;
BEGIN
inttab(1):=10;
inttab(12):=20;
inttab(25):=30;
dbms_output.put_line(inttab(1)||','||inttab(12)||','||inttab(25));
END;
Analyze following program
DECLARE
TYPE name_table IS TABLE OF VARCHAR2(100)
INDEX BY BINARY_INTEGER;
old_names name_table;
new_names name_table;
BEGIN
old_names(1) := 'Smith';
old_names(2) := 'Harry';
new_names(111) := 'Hari';
new_names(342) := 'Bindu';
new_names(500) := 'Simi';
old_names := new_names;
DBMS_OUTPUT.PUT_LINE (old_names (1));
END;
Note : No DML (except delete) or transactions can be
implemented on PL/SQL tables
Built-in Functions and Procedures for PL/SQL Tables
Operator Description
COUNT Returns the number of elements currently contained in the PL/SQL table.
DELETE Deletes one or more elements from the PL/SQL table.
EXISTS Returns FALSE if a reference to an element at the specified index would
raise the NO_DATA_FOUND exception.
FIRST Returns the smallest index of the PL/SQL table for which an element is
defined.
LAST Returns the greatest index of the PL/SQL table for which an element is
defined.
NEXT Returns the smallest index of the PL/SQL table containing an element
which is greater than the specified index.
PRIOR Returns the greatest index of the PL/SQL table containing an element
which is less than the specified index.
Deleting rows in PL/SQL tables
Example:
DECLARE
TYPE dept_table_type IS TABLE OF dept%ROWTYPE
INDEX BY BINARY_INTEGER;
dept_table dept_table_type;
-- Each element of dept_table is a record
to refer each field
dept_table(index).field_name must be used
Example
DECLARE
TYPE EmpTabTyp IS TABLE OF emp%ROWTYPE
INDEX BY BINARY_INTEGER;
emp_tab EmpTabTyp;
BEGIN
SELECT * INTO emp_tab(7566) FROM emp
WHERE empno = 7566;
dbms_output.put_line(emp_tab(7566).ename);
END;
Example using CURSOR FOR LOOP
SET SERVEROUTPUT ON
DECLARE
TYPE emp_tabtype IS TABLE OF EMP%ROWTYPE INDEX BY
BINARY_INTEGER;
EMPREC emp_tabtype;
BEGIN
Arrays are dense and have a fixed upper bound, but nested
tables are initially dense but become sparse and are unbounded
In arrays you cannot delete elements
In nested table you can delete elements using the built-in
procedure DELETE. That might leave gaps in the index, but
the built-in function NEXT lets you iterate over any series of
subscripts.
Understanding Varrays
Items of type VARRAY are called varrays.
They allow you to associate a single identifier with an entire
collection. This association lets you manipulate the collection
as a whole and reference individual elements easily.
To reference an element, you use standard subscripting syntax
DECLARE
TYPE NumList IS VARRAY(3) OF VARCHAR2(12);
nums NumList := NumList(10,20,30);
BEGIN
for i in 1..3 loop
DBMS_OUTPUT.PUT_LINE(nums(i));
end loop;
nums(1):='A';
nums(2):=60;
nums(3):='welcome';
for i in 1..3 loop
DBMS_OUTPUT.PUT_LINE(nums(i));
end loop;
END;
CREATE TYPE TOOL_TY AS OBJECT (TOOLNAME
VARCHAR2(25));
LOOP
MY_TOOLS(I+1):=MY_TOOLS(I);
END LOOP;
MY_TOOLS(POSITION):=NEW_TOOL; -- add new
project
UPDATE BORROWER SET TOOLS=MY_TOOLS
WHERE NAME=BNAME;
END;
INSERT
TABLE1
INSTEAD OF
Trigger
UPDATE
MY_VIEW TABLE2
Creating an INSTEAD OF Trigger
Syntax:
CREATE [OR REPLACE] TRIGGER trigger_name
INSTEAD OF
event1 [OR event2 OR event3]
ON view_name
[REFERENCING OLD AS old | NEW AS new]
[FOR EACH ROW]
trigger_body
INSTEAD OF Trigger Example
CREATE OR REPLACE VIEW EMPDEPTVIEW
AS
SELECT EMPNO,ENAME,JOB,SAL,E.DEPTNO,DNAME,LOC
FROM EMP E,DEPT D WHERE E.DEPTNO=D.DEPTNO;