0% found this document useful (0 votes)
149 views160 pages

Oracle 9i Database Server: PL/SQL

PL/SQL is Oracle's procedural extension language for SQL that allows developers to perform procedural logic and handle errors. Key benefits of PL/SQL include improved performance by reducing network traffic through executing SQL statements in blocks, modularized program development through blocks and subprograms, and improved security, integrity and performance through stored procedures and functions. PL/SQL supports various data types including scalars, composites, references and LOBs which allow storing large objects.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
Download as ppt, pdf, or txt
0% found this document useful (0 votes)
149 views160 pages

Oracle 9i Database Server: PL/SQL

PL/SQL is Oracle's procedural extension language for SQL that allows developers to perform procedural logic and handle errors. Key benefits of PL/SQL include improved performance by reducing network traffic through executing SQL statements in blocks, modularized program development through blocks and subprograms, and improved security, integrity and performance through stored procedures and functions. PL/SQL supports various data types including scalars, composites, references and LOBs which allow storing large objects.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1/ 160

Oracle 9i Database Server

PL/SQL
Procedural Language/Structured Query
Language

•PL/SQL is the procedural extension to SQL


with design features of programming
languages.
•Data manipulation and query statements of
SQL are included within procedural units of
code.
PL/SQL Environment

PL/SQL engine
PL/SQL Procedural
PL/SQL PL/SQL statement
block block SQL
executor

SQL statement 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

Anonymous Procedure Function


[DECLARE] PROCEDURE name FUNCTION name
IS RETURN datatype
IS
BEGIN BEGIN BEGIN
--statements --statements --statements
RETURN value;
[EXCEPTION] [EXCEPTION] [EXCEPTION]

END; END; END;


Variables
Variables are used to store values/data, for
reusability, ease of maintenance using type
attributes.
Types of Variables
•PL/SQL variables:
–Scalar
–Composite
–Reference
–LOB (large objects)

•Non-PL/SQL variables: Bind and host variables


Types of Variables
•Scalar data types hold a single value (correspond to
column types in Oracle server tables). PL/SQL also
supports Boolean variables.
•Composite data types, such as records, allow groups
of fields to be defined.
•Reference data types hold values, called pointers, that
designate other program items.
•LOB data types hold values, called locators, that
specify the location of large objects (such as graphic
images) that are stored out of line.
•Non-PL/SQL variables include host language variables
declared in precompiler programs, screen fields in Forms
applications, and SQL*Plus/iSQL*Plus host variables.
Types of Variables
Atlanta 25-JAN-01
TRUE 256120.08
“Four score and seven years ago
our fathers brought forth upon
this continent, a new nation,
conceived in LIBERTY, and dedicated
to the proposition that all men
are created equal.”
Declaring PL/SQL Variables

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;

The names of the variables must not be longer than 30


characters.
Adopt a naming convention for PL/SQL identifiers:
for example, v_variablename
Different Datatypes
BINARY_INTEGER to store signed integers(-2**31 .. 2**31)
BINARY_INTEGER Subtypes
A base type is the datatype from which a subtype is derived.
A subtype associates a base type with a constraint and so
defines a subset of values.
BINARY_INTEGER subtypes:
NATURAL, POSITIVE - integer must be positive value.
NATURALN, POSITIVEN - prevent the assigning of nulls to
an integer variable.
SIGNTYPE - allows only -1, 0, and 1, which is useful in
NUMBER to store fixed-point or floating-point numbers
Range is 1E-130 .. 10E125
NUMBER Subtypes
DEC, DECIMAL, NUMERIC - fixed-point numbers with a
maximum precision of 38 decimal digits

DOUBLE PRECISION, FLOAT - floating-point numbers with a


maximum precision of 126 binary digits, which is roughly equivalent
to 38 decimal digits.

INTEGER, INT, SMALLINT - integers with a maximum precision


of 38 decimal digits.

REAL - floating-point numbers with a maximum precision of 63


binary digits (approx : 18 decimal digits)
CHAR - to store fixed-length character data. Maximum size is
32767 bytes.
Syntax:
CHAR[(maximum_size [CHAR | BYTE] )]
CHAR Subtypes -
LONG - to store variable-length character strings. The LONG
datatype is like the VARCHAR2 datatype, except that the
maximum size of a LONG value is 32760 bytes.
LONG RAW - to store binary data or byte strings. The
maximum size of a LONG RAW value is 32760 bytes.
ROWID and UROWID
Internally, every database table has a ROWID pseudocolumn,
which stores binary values called rowids.
Each rowid represents the storage address of a row.
A physical rowid identifies a row in an ordinary table.
A logical rowid identifies a row in an index-organized table.
ROWID stores physical rowids.
UROWID (universal rowid) datatype can store physical,
logical, or foreign (non-Oracle) rowids.
Physical Rowids Physical rowids provide fast access. As long
as the row exists, its physical rowid does not change.
VARCHAR2- to store variable-length character data.
Maximum size is 32767 bytes.
Syntax :
VARCHAR2(maximum_size [CHAR | BYTE])
VARCHAR2 Subtypes –
STRING,VARCHAR subtypes for compatibility with
ANSI/ISO and IBM types.
National Character Types
ASCII and EBCDIC character sets are adequate to represent
the Roman alphabet.
But some Asian languages, such as Japanese, contain
thousands of characters which require two or three bytes to
represent each character
Oracle provides globalization support with this type.
NCHAR- to store fixed-length national character data.
NVARCHAR2- to store variable-length Unicode character
data.
LOB Data Type Variables
Book
(CLOB)

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

TRUE 23-DEC-98 ATLANTA

PL/SQL table structure PL/SQL table structure

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;

SUBTYPE Counter IS NATURAL;

TYPE NameList IS TABLE OF VARCHAR2(10);

SUBTYPE DutyRoster IS NameList;

TYPE TimeRec IS RECORD (minutes INTEGER, hours


INTEGER);

SUBTYPE FinishTime IS TimeRec;

SUBTYPE ID_Num IS emp.empno%TYPE;


Initializing Variables
V_COUNT NUMBER NOT NULL:=0
V_SALARY NUMBER(7,2);
V_ANN_SAL NUMBER(9,2):=monthly_sal *12;
tax := price * tax_rate;
bonus := current_salary * 0.10;
amount := TO_NUMBER(SUBSTR('750 dollars', 1, 3));
married BOOLEAN:=FALSE;
today date:=SYSDATE;
credit_limit CONSTANT NUMBER(9,2) := 5000.00;
DBMS_OUTPUT Package

Package DBMS_OUTPUT enables you to display output from


PL/SQL blocks and subprograms.
The procedure put_line outputs information to a buffer in the
SGA. You display the information by setting
SERVEROUTPUT ON in SQL*Plus.
SQL> SET SERVEROUTPUT ON
SQL> BEGIN
2 DBMS_OUTPUT.PUT_LINE(‘Hello World');
3 END;
4 /
Hello World

PL/SQL procedure successfully completed.


SQL>DECLARE
2 X integer;
3 BEGIN
4 X:=5000;
5 DBMS_OUTPUT.PUT_LINE('The value of X='||X);
6 END;
7 /
The value of X=5000

*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;

*Income tax example to be discussed


CASE Statement
[<<label_name>>]
CASE selector
WHEN expression1 THEN sequence_of_statements1;
...
WHEN expressionN THEN sequence_of_statementsN;
[ELSE sequence_of_statementsN+1;]
END CASE [label_name];

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;

use an EXIT / EXIT WHEN statement to complete the loop.


WHILE-LOOP
WHILE condition LOOP
sequence_of_statements
END LOOP;
FOR-LOOP

FOR counter IN [REVERSE] lower_bound..higher_bound


LOOP
sequence_of_statements
END LOOP;
NULL Statement
The NULL statement does nothing other than pass control to
the next statement.
Interacting with the Oracle Server

SELECT .. INTO .. Statement


-retrieves data from one or more database tables, then assigns
the selected values to variables

*To be explained with example


SQL *PLUS BIND VARIABLES

These are host variables that may be used to pass runtime


values into or out of PL/SQL block.
Bind variables are declared in SQL *PLUS

VARIABLE variable_name [NUMBER | CHAR | CHAR(N) |


VARCHAR2(N)]
Ex: VARIABLE emplname VARCHAR2(12)

*To be explained with example with PRINT command


Declaring Variables based on database columns
DECLARE
empname EMP.ENAME%TYPE;
….
%TYPE attribute enables you to define a variable based on a
table column datatype
% is attribute indicator.
PL/SQL Record Variables
A record is a group of related data items stored in fields, each
with its own name and datatype.
These items are logically related but dissimilar in type.
A record containing a field for each item lets you treat the data
as a logical unit.
To create records, you define a RECORD type, then declare
records of that type.
PL/SQL Record Structure

Field1 (data type) Field2 (data type) Field3 (data type)

Example:

Field1 (data type) Field2 (data type) Field3 (data type)


dept_id number(2) dept_name varchar2(14) dept_loc varchar2(13)
10 ACCOUNTING NEW YORK
Syntax
TYPE type_name IS RECORD
(field_declaration[, field_declaration]…);
identifier type_name;

field_name {field_type | variable%TYPE


| table.column%TYPE | table%ROWTYPE}
[[NOT NULL] {:= | DEFAULT} expr]

Note : RECORD types cannot be CREATEd and stored in the


database.
You can use %TYPE and %ROWTYPE to specify field types.
In the following example, you define a RECORD type named
DeptRec:
TYPE DeptRectype IS RECORD (
dept_id dept.deptno%TYPE, dept_name VARCHAR2(14),
dept_loc VARCHAR2(13));
Declaring a record variable
dept_rec deptrectype;

To access individual fields


dept_rec.dept_id;
dept_rec.dept_name;
*example on recordtype

Record variables based on tables


It means that each field in the record has the same name and
datatype as the columns in the specified table.
%ROWTYPE attribute is used to facilitate the declaration of a
record based on a table.
emprec EMP%ROWTYPE;
* example on rowtype
* Retired employees example.
PL/SQL Error Handling
In PL/SQL, a warning or error condition is called an
exception.
An exception is an identifier in PL/SQL that is raised during
the execution of a block that terminates its main body of
actions. A block always terminates when PL/SQL raises an
exception, but can you specify an exception handler to
perform final actions.
Examples of internally defined exceptions include no data
found, fetching multiple rows, value error, division by zero,
out of memory and many more.
For example, if the error ORA-01403 occurs when no
rows are retrieved from the database in a SELECT
statement, then PL/SQL raises the exception
NO_DATA_FOUND.
Handling Exceptions
Trap the exception Propagate the exception

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.

This statement is a compiler directive that allows the developer to


declare the Oracle-numbered error to be associated with a named
exception in the block.
CURSOR’s
Whenever you issue a SQL statement, the Oracle
server opens an area of memory in which the command
is parsed and executed. This area is called a cursor.
PL/SQL cursors provide a way for your program to
select multiple rows of data from the database and
then to process each row individually.
PL/SQL uses two types of cursors: implicit and explicit.

PL/SQL declares a cursor implicitly for all SQL DML


statements, including select queries that return only
one row.

However, for queries that return more than one row,


you must declare an explicit cursor.
Controlling Explicit Cursors
No

Yes
DECLARE OPEN FETCH EMPTY? CLOSE

• Create a • Identify • Load the • Test for • Release


named the active current existing the active
SQL area set row into rows set
variables • Return to
FETCH if
rows are
found
Declaring a Cursor
When you declare a cursor, you name it and associate it
with a specific query

CURSOR cursor_name [(parameter[, parameter]...)]


[RETURN return_type] IS select_statement;

where return_type must represent a record or a row in a


database table.

At this stage, the query is parsed (cols, tables etc., are


validated) but it is not executed.

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:

1. To fetch empno,ename,job,sal,deptno from emp using


record type variable using cursor%ROWTYPE
2. To fetch top five employee details.
3. To fetch nth row from a table
CURSOR FOR loop:
PL/SQL provides a special kind of FOR loop to process the
rows returned in an explicit CURSOR.
In a CURSOR FOR loop, a declared CURSOR is OPENed,
FETCHed from and CLOSEed automatically when all of the
rows have be processed.
Each iteration of the loop fetches a row from the active set into
a record, which is implicitly declared for use within the loop.
The loop is terminated automatically at the end of the iteration
when the last row was FETCHed.
Cursor Variables
Cursor variables are like C pointers, which hold the
memory location (address) of some item instead of the
item itself.

In PL/SQL, a pointer has datatype REF X, where REF


is short for REFERENCE and X stands for a class of
objects.

Therefore, a cursor variable has datatype REF CURSOR.

Uses of Cursor Variables


Mainly, you use cursor variables to pass query result sets
between PL/SQL stored subprograms and various clients.
Defining REF CURSOR Types
To create cursor variables, you take two steps.
First, you define a REF CURSOR type, then declare cursor
variables of that type.
You can define REF CURSOR types in any PL/SQL block,
subprogram, or package
TYPE ref_type_name IS REF CURSOR [RETURN
return_type];
where ref_type_name is a type specifier used in
subsequent declarations of cursor variables and
return_type must represent a record or a row in a
database table.
Then declare variable of ref_type_name
Example : 2
SQL> variable g_ref refcursor 
DECLARE
TYPE emp_cur_t is REF CURSOR return emp
%rowtype;
v_cur emp_cur_t;
emp_rec emp%rowtype;
BEGIN
OPEN v_cur for select * from emp;
FOR idx in 1..6 LOOP
FETCH v_cur into emp_rec;
DBMS_OUTPUT.PUT_LINE(emp_rec.ename);
END LOOP;
:g_ref := v_cur;
END;
/
SQL> print g_ref
PL/SQL Subprograms

Subprograms are named PL/SQL blocks that can take


parameters and be invoked.
PL/SQL has two types of subprograms called procedures and
functions.
Procedures are used to perform an action
Functions are used to compute a value.
subprograms have a declarative part, an executable part, and
an optional exception-handling part.
The declarative part contains declarations of types, cursors,
constants, variables, exceptions, and nested subprograms.
Advantages of Subprograms

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:

[CREATE [OR REPLACE]]


PROCEDURE procedure_name[(parameter[,
parameter]...)]
{IS | AS}
[local declarations]
BEGIN
executable statements
[EXCEPTION
exception handlers]
END [procedure_name];

First 2 lines are procedure specification and rest is


procedure body
•declarative part is placed between the IS and BEGIN
•keyword DECLARE is not used.
•Procedures that take no parameters are written without
parentheses.
•You cannot constrain the datatype of a parameter.
PROCEDURE reconcile (acct_id CHAR(5)) IS ... illegal
However, you can use the following workaround to size-
constrain parameter types indirectly:
DECLARE
SUBTYPE Char5 IS CHAR(5);
PROCEDURE reconcile (acct_id Char5) IS ...
where parameter stands for the following syntax:
parameter_name [IN | OUT | IN OUT ] datatype [{:= |
DEFAULT} expression]
Procedural Parameter Modes
Procedure
IN parameter
Calling
environment OUT parameter
IN OUT parameter

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;

Calling procedure from a PL/SQL block


DECLARE
empid emp.empno%TYPE:=&EMPNO;
bonus NUMBER;
BEGIN
calc_bonus(empid,bonus);
dbms_output.put_line('Bonus='||bonus);
END;
Example for inserting a row:

PROCEDURE create_dept (new_dname VARCHAR2,


new_loc VARCHAR2) IS
BEGIN
INSERT INTO dept VALUES (deptno_seq.NEXTVAL,
new_dname, new_loc);
END create_dept;
Examples
Inserting row into table. Handling exception.
Delete row from table. Handle exception if any.
Declaring PL/SQL
Subprograms

You can declare


subprograms in any PL/SQL
block, subprogram, or
package.

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

PROCEDURE create_dept (dno dept.deptno%type,


new_dname dept.dname%type DEFAULT ’TEMP’,
new_loc dept.loc%type VARCHAR2 DEFAULT ’TEMP’) IS
BEGIN
INSERT INTO dept
VALUES (dno, new_dname, new_loc);
Commit;
END;

If an actual parameter is not passed, the default value of


its corresponding formal parameter is used.

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

DROP PROCEDURE procedure_name;


PL/SQL Functions

Functions and procedures are structured alike, except


that functions have a RETURN clause.
[CREATE [OR REPLACE ] ]
FUNCTION function_name [ ( parameter [ , parameter ]...
) ] RETURN datatype
{IS | AS}
[ local declarations ]
BEGIN
executable statements;
RETURN Statement;
[ EXCEPTION
exception handlers ]
END [ function_name ];
RETURN Statement
RETURN statement must contain an expression, which is
evaluated when the RETURN statement is executed.
In a function, there must be at least one execution path
that leads to a RETURN statement. Otherwise, you get a
function returned without value error at run time.
Examples :
A function which returns string in sentence case after
accepting a string

CREATE OR REPLACE FUNCTION SENTCASE(STR


VARCHAR2)
RETURN VARCHAR2
IS
S VARCHAR2(80);
BEGIN
S:=UPPER(SUBSTR(STR,1,1))||
LOWER(SUBSTR(STR,2));
RETURN S;
END;
Calling a function
SELECT SENT_CASE('HOW are YOU now') FROM
DUAL;
Examples:
Function to get day of the week.
Function to calculate your age in years and months
Function to retrieve emprecord with max salary.

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

Note : A package specification can exist without a package


body, but a package body cannot exist without a package
specification.
Packages usually have two parts, a specification and a body,
although sometimes the body is unnecessary.

The specification is the interface to your applications; it


declares the types, variables, constants, exceptions, cursors,
and subprograms available for use.

The body fully defines cursors and subprograms, and so


implements the spec.
Package Specification

Package Body
Package for handling employees

CREATE OR REPLACE PACKAGE emp_actions AS


PROCEDURE hire_employee (
empno NUMBER,
ename VARCHAR2,
job VARCHAR2,
mgr NUMBER,
sal NUMBER,
comm NUMBER,
deptno NUMBER);
PROCEDURE fire_employee (emp_id NUMBER);
PROCEDURE raise_salary (emp_id INTEGER, increase
NUMBER);
END emp_actions;
Package body
CREATE OR REPLACE PACKAGE BODY emp_actions AS
PROCEDURE hire_employee (
empno NUMBER,
ename VARCHAR2,
job VARCHAR2,
mgr NUMBER,
sal NUMBER,
comm NUMBER,
deptno NUMBER) IS
BEGIN
INSERT INTO emp VALUES (empno, ename, job, mgr,
SYSDATE, sal, comm, deptno);
END hire_employee;
(cont’d)
Package body cont’d…
PROCEDURE fire_employee (emp_id NUMBER) IS
BEGIN
DELETE FROM emp WHERE empno = emp_id;
END fire_employee;

PROCEDURE raise_salary (emp_id INTEGER, increase


NUMBER) IS
BEGIN
UPDATE emp SET sal = sal + increase WHERE empno =
emp_id;
END raise_salary;
END emp_actions;
Executing Packages
-EXECUTE EMP_ACTIONS.FIRE_EMPLOYEE(7566);
-EXECUTE EMP_ACTIONS.HIRE_EMPLOYEE
(1000,'RAJESH','MANAGER',7566,3000,500,10);
-EXECUTE EMP_ACTIONS.RAISE_SALARY(7369,100);
Using cursors in a package
CREATE PACKAGE emp_stuff AS
CURSOR c1 RETURN emp%ROWTYPE;
END emp_stuff;

CREATE PACKAGE BODY emp_stuff AS


CURSOR c1 RETURN emp%ROWTYPE IS
SELECT * FROM emp WHERE sal > 2500;
END emp_stuff;
(cont’d …..)
Using cursor in a PL/SQL block

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

•Enables you to use the same name for different


subprograms inside a PL/SQL block, a subprogram, or a
package

•Requires the formal parameters of the subprograms to


differ in number, order, or data type family

•Enables you to build more flexibility because a user or


application is not restricted by the specific data type or
number of formal parameters
Example :

Package Specification

CREATE OR REPLACE PACKAGE over_pack


IS
PROCEDURE add_dept
(p_deptno IN dept.deptno%TYPE,
p_name IN dept.dname%TYPE DEFAULT 'unknown',
p_loc IN dept.loc%TYPE DEFAULT 'unknown');
PROCEDURE add_dept
(p_name IN dept.dname%TYPE DEFAULT 'unknown',
p_loc IN dept.loc%TYPE DEFAULT 'unknown');
END over_pack;
/
Package Body
CREATE OR REPLACE PACKAGE BODY over_pack IS
PROCEDURE add_dept
(p_deptno IN dept.deptno%TYPE,
p_name IN dept.dname%TYPE DEFAULT 'unknown',
p_loc IN dept.loc%TYPE DEFAULT 'unknown')
IS
BEGIN
INSERT INTO dept VALUES (p_deptno, p_name, p_loc);
END add_dept;
PROCEDURE add_dept
(p_name IN dept.dname%TYPE DEFAULT 'unknown',
p_loc IN dept.loc%TYPE DEFAULT 'unknown')
IS
BEGIN
INSERT INTO dept VALUES (dept_seq.NEXTVAL, p_name,
p_loc);
END add_dept;
END over_pack;
/
OBJECTS
What Is an Object Type?
An object type is a user-defined composite datatype that
encapsulates a data structure along with the functions and
procedures needed to manipulate the data.
The variables that form the data structure are called
attributes.
The functions and procedures that characterize the behavior of
the object type are called methods.
Object type is the closest thing to a class.
Object Type and Objects (Instances) of that Type
Why Use Object Types?

Object types reduce complexity by breaking down a large


system into logical entities.
This lets you create software components that are modular,
maintainable, and reusable.
It also allows different teams of programmers to develop
software components concurrently.
Object types minimize side effects by allowing access to data
only through approved operations.
*USER_OBJECTS-procedures,functions,types etc
*USER_TYPES-object_types
*USER_SOURCE-code for objects
*USER_TYPE_ATTRS-objects attributes
*USER_TYPE_METHODS-objects methods
Structure of an Object Type

The specification is the interface to your applications; it


declares a data structure (set of attributes) along with the
operations (methods) needed to manipulate the data.
The body fully defines the methods, and so implements the
spec.
Defining Object Types
You cannot define object types in a PL/SQL block,
subprogram, or package. You can define them interactively in
SQL*Plus
CREATE [OR REPLACE] TYPE type_name {IS | AS}
OBJECT
(
attribute_name datatype[, attribute_name datatype]...
[MEMBER subprogram_spec ,..]
)

CREATE [OR REPLACE] TYPE BODY type_name {IS |


AS}
{MEMBER | STATIC} {subprogram_body | call_spec};…
END;
Simple Example without body

CREATE or REPLACE TYPE address_type AS OBJECT


(
RESNO NUMBER(4),
STREET VARCHAR2(12),
CITY VARCHAR2(12),
PHONE VARCHAR2(20)
);

CREATE TABLE EMPADDRESS(


ENAME VARCHAR2(12),
ADDRESS address_type);

INSERT INTO EMPADDRESS VALUES('SMITH',


address_type(112,'M G ROAD','BLORE','1234567'));

SELECT ENAME,E.ADDRESS.PHONE FROM EMPADDRESS E;


observe
E.address.phone
Note that the access of the datatype’s attribute requires the use
of a table alias. A table alias, also known as a correlation
variable, allows oracle to resolve any ambiguity regarding the
name of the object being selected.
Format for column name is
Correlation.column.attribute
Previous example with spec and body

CREATE or REPLACE type address_type AS OBJECT(


resno NUMBER(5),
street VARCHAR2(10),
city VARCHAR2(12),
phone VARCHAR2(20),
MEMBER FUNCTION getresno RETURN NUMBER,
MEMBER FUNCTION getstreet RETURN VARCHAR2,
MEMBER FUNCTION getcity RETURN VARCHAR2,
MEMBER FUNCTION getphone RETURN VARCHAR2
);
CREATE OR REPLACE TYPE BODY address_type AS
MEMBER FUNCTION getresno RETURN NUMBER is
BEGIN
RETURN resno;
END;
MEMBER FUNCTION getstreet RETURN VARCHAR2 is
BEGIN
RETURN street;
END;
MEMBER FUNCTION getcity RETURN VARCHAR2 is
BEGIN
RETURN city;
END;
MEMBER FUNCTION getphone RETURN VARCHAR2 is
BEGIN
RETURN phone;
END;
END;
DECLARE
ADDR1 ADDRESS_TYPE;
BEGIN
SELECT ADDRESS INTO ADDR1 FROM
EMPADDRESS WHERE ENAME='SMITH';
DBMS_OUTPUT.PUT_LINE(ADDR1.PHONE);
END;

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

A table in which each row represents an object

-CREATE TABLE address OF address_type;

-INSERT INTO address VALUES


(address_type(10 ,‘MNagar',‘Blore',‘Kar','23445'));

-SELECT * FROM ADDRESS;

-update address set street=‘MExtn' where resno=10;

-delete address where resno=10;


Example for practice

CREATE TYPE ADDRESS_TY AS OBJECT


(STREET VARCHAR2(20),
CITY VARCHAR2(20),
STATE CHAR(2),
ZIP NUMBER);

CREATE TYPE PERSON_TY AS OBJECT


(NAME VARCHAR2(20),
ADDRESS ADDRESS_TY);

CREATE TABLE CUSTOMER


(CUSTOMER_ID NUMBER,
PERSON PERSON_TY);
INSERT INTO CUSTOMER VALUES(1,
PERSON_TY('NEIL MULLANE',
ADDRESS_TY('57 MT PLEASANT ST', 'FINN', 'NH',
11111)));

INSERT INTO CUSTOMER VALUES(2,


PERSON_TY('SEYMOUR HESTER',
ADDRESS_TY('1 STEPAHEAD RD', 'BRIANT', 'NH',
11111)));

SELECT CUSTOMER_ID,C.PERSON.NAME FROM


CUSTOMER C;

SELECT C.PERSON.ADDRESS.STREET FROM


CUSTOMER C;
COLLECTION
A collection is an ordered group of elements, all of the
same type.
It is a general concept that encompasses lists, arrays,
and other familiar datatypes.
Each element has a unique subscript that determines
its position in the collection
Types of Collections
PL/SQL tables: to hold arbitrary no of elements. Indexing is
by binary_integer.

Nested tables hold an arbitrary number of elements. They use


sequential numbers as subscripts.

Varrays (variable-size arrays) hold a fixed number of


elements (although you can change the number of elements at
runtime). They use sequential numbers as subscripts.
INDEX BY Tables
Objects of the TABLE type are called INDEX BY tables.
They are modeled as database tables (but not the same
as).
INDEX BY tables use a primary key to provide you with
array-like access to rows.
A INDEX BY table:
•Is similar to an array
•Must contain two components:
–A primary key of data type BINARY_INTEGER
that indexes the INDEX BY table
–A column of a scalar or record data type, which
stores the INDEX BY table elements
•Can increase dynamically because it is
unconstrained
Creating an INDEX BY Table
Syntax:
TYPE type_name IS TABLE OF
{column_type | variable%TYPE
| table.column%TYPE} [NOT NULL]
| table.%ROWTYPE
[INDEX BY BINARY_INTEGER];
identifier type_name;
Declare an INDEX BY table to store names.
Example:
...
TYPE ename_table_type IS TABLE OF
emp.ename%TYPE
INDEX BY BINARY_INTEGER;
ename_table ename_table_type;
...
INDEX BY Table Structure

Unique identifier Column


... ...
1 JONES
2 SMITH
3 KING

... ...

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

To delete specific row


<table_name>.delete(<index_number>)

To delete all the rows


<table_name>.delete

To delete range of rows


<tablename>.DELETE (start_index_in IN INTEGER,
end_index_in IN INTEGER);
DECLARE
TYPE stringtabtype IS TABLE OF varchar2(15)
INDEX BY BINARY_INTEGER;
playerslist stringtabtype;
BEGIN
playerslist(99):='Sachin';
playerslist(10):='Dravid';
playerslist(5):='Shewag';
playerslist(12):='Ganguly';
playerslist(25):='Yuvraj';
playerslist(15):='Harbajan';
playerslist(19):='Kumble';
dbms_output.put_line('Total Players :'||playerslist.count);
FOR i IN playerslist.first..playerslist.last LOOP
if playerslist.exists(i) then
dbms_output.put_line(i||'.'||playerslist(i));
end if;
END LOOP;
playerslist.delete(12,19);--deleting range of elements
FOR i IN playerslist.first..playerslist.last LOOP
if playerslist.exists(i) then
dbms_output.put_line('Indexes - Prior :'||playerslist.prior(i)||' Next :'||
playerslist.next(i));
dbms_output.put_line(i||'.'||playerslist(i));
end if;
END LOOP;
END;
INDEX BY Table of Records
•Define a TABLE variable with a permitted PL/SQL data type.
•Declare a PL/SQL variable to hold department information.

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

for rec in (select * from emp) loop


EMPREC(rec.empno):=rec;
END LOOP;

for i in EMPREC.FIRST..EMPREC.LAST LOOP


if EMPREC.exists(i) then
dbms_output.put_line(i||','||EMPREC(i).ENAME);
end if;
end loop;
END;
Nested Tables

•nested tables can be considered one-column database tables.


•oracle stores the rows of a nested table in no particular order.
•when you retrieve the nested table into a PL/SQL variable,
the rows are given consecutive subscripts starting at 1. That
gives you array-like access to individual rows.
NESTED ARRAY vs ARRAY

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

A varray has a maximum size


Defining Collection Types
You can define TABLE and VARRAY types in the declarative
part of any PL/SQL block, subprogram, or package.
Nested Tables
TYPE type_name IS TABLE OF element_type [NOT NULL]
type_name is a type specifier used later to declare collections.
element_type is any PL/SQL datatype
Varrays
TYPE type_name IS {VARRAY | VARYING ARRAY}
( size_limit) OF element_type [NOT NULL]
type_name and element_type are the same as for nested tables
size_limit is a positive integer
Example:
DECLARE
TYPE NumList IS TABLE 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 PHONE_TYPE AS OBJECT(
PHONE_LOC VARCHAR2(10),
PHONE_NO NUMBER(12));

-CREATE TYPE PHONE_TAB AS TABLE OF


PHONE_TYPE;

-CREATE TABLE EMP_PHONE(


ENAME VARCHAR2(12),
PHONE_DETAILS PHONE_TAB)
NESTED TABLE PHONE_DETAILS STORE AS
PHONE_EXTABLE;
The NESTED TABLE clause is required whenever a database
table has a nested table column. The clause identifies the
nested table and names a system-generated store table, in
which Oracle stores the nested table data.
Inserting rows

-INSERT INTO EMP_PHONE VALUES('SMITH',


PHONE_TAB(PHONE_TYPE('HOME',12345),
PHONE_TYPE('OFF',56789)))

-INSERT INTO EMP_PHONE VALUES('JONES',


PHONE_TAB(PHONE_TYPE('CELL',23456),PHONE_TYP
E('OFF',98765),PHONE_TYPE('OFF',99999)))
-SELECT * FROM EMP_PHONE;
-SELECT PHONE_LOC,PHONE_NO FROM THE(SELECT
PHONE_DETAILS FROM EMP_PHONE WHERE
ENAME='SMITH');
Performing DML actions on nested table
-INSERT INTO THE(SELECT PHONE_DETAILS FROM
EMP_PHONE WHERE ENAME='SMITH')
VALUES('CELL',777777);
-INSERT INTO TABLE(SELECT PHONE_DETAILS
FROM EMP_PHONE WHERE ENAME='SMITH')
VALUES('CELL',99999)
-UPDATE THE(SELECT PHONE_DETAILS FROM
EMP_PHONE WHERE ENAME='SMITH') SET
PHONE_NO=11111 WHERE PHONE_LOC='HOME';
-DELETE THE(SELECT PHONE_DETAILS FROM
EMP_PHONE WHERE ENAME='SMITH') WHERE
PHONE_LOC='OFF';
VARRAYS

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));

CREATE OR REPLACE TYPE TOOLS_VA AS


VARRAY(5) OF TOOL_TY;

CREATE TABLE BORROWER


(NAME VARCHAR2(25),
TOOLS TOOLS_VA);

INSERT INTO BORROWER VALUES ('JED HOPKINS',


TOOLS_VA(TOOL_TY('HAMMER‘),
TOOL_TY('SLEDGE‘), TOOL_TY('AX‘)));

SELECT * FROM BORROWER;


SELECT * FROM THE(SELECT TOOLS FROM
BORROWER WHERE NAME='JED HOPKINS')

SELECT B.NAME,N.* FROM BORROWER


B,TABLE(B.TOOLS) N;
UPDATE BORROWER SET
TOOLS=TOOLS_VA(TOOL_TY(‘PLIER'),TOOL_TY(‘SCR
EW DRIVER'))
Using cursor method
DECLARE
CURSOR BORROWER_CURSOR IS SELECT * FROM
BORROWER;
BEGIN
FOR BORROWER_REC IN BORROWER_CURSOR
LOOP
DBMS_OUTPUT.PUT_LINE('Contact Name: '||
borrower_rec.name);
for i in 1..borrower_rec.tools.count
loop
dbms_output.put_line(borrower_rec.tools(i));
end loop;
end loop;
end;
Currently, you cannot reference the individual elements of a
varray in an INSERT, UPDATE, or DELETE statement. You
must retrieve the entire varray, use PL/SQL procedural
statements to add, delete, or update its elements, and then store
the changed varray back in the database table.
Procedure for adding row into varray
CREATE OR REPLACE PROCEDURE ADD_TOOLS(
BNAME IN VARCHAR2,
NEW_TOOL IN TOOL_TY,
POSITION IN NUMBER)AS
MY_TOOLS TOOLS_VA;
BEGIN
SELECT TOOLS INTO MY_TOOLS FROM BORROWER
WHERE NAME=BNAME FOR UPDATE OF TOOLS;
MY_TOOLS.EXTEND; -- make room for new
project
/* Move varray elements forward. */
FOR I IN REVERSE POSITION..MY_TOOLS.LAST-1

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;

EXECUTE ADD_TOOLS('JED HOPKINS',


Procedure for updating VARRAY
CREATE or replace PROCEDURE update_tools(
bname IN varchar2,
oldtoolname IN varchar2,
newtool IN VARCHAR2) AS
my_tools tools_va;
BEGIN
SELECT tools INTO my_tools FROM borrower WHERE name = bname
FOR
UPDATE OF tools;
/* Find toos, update it, then exit loop immediately. */
FOR i IN my_tools.FIRST..my_tools.LAST LOOP
IF my_tools(i).toolname = oldtoolname THEN
my_tools(i).toolname:= newtool;
EXIT;
END IF;
END LOOP;
UPDATE borrower SET tools = my_tools WHERE name = bname;
END;
-EXECUTE UPDATE_PROJECT('JED HOPKINS','SLEDGE','GI ROD');
TRIGGER
A trigger:
•Is a PL/SQL block or a PL/SQL procedure
associated with a table, view, schema, or the
database
•Executes implicitly whenever a particular
event takes place
USES OF TRIGGERS

Triggers may be used to


-supplement declarative referential integrity.
-enforce complex business rules.
-audit change to data.
-monitor database related actions.
Creating DML Triggers

A triggering statement contains:


•Trigger timing
–For table: BEFORE, AFTER
–For view: INSTEAD OF
•Triggering event: INSERT/UPDATE/DELETE
•Table name: On table, view
•Trigger type: Row or statement
•WHEN clause: Restricting condition
•Trigger body: PL/SQL block
DML Trigger Components

Trigger timing: When should the trigger fire?

•BEFORE: Execute the trigger body before the


triggering DML event on a table.

•AFTER: Execute the trigger body after the


triggering DML event on a table.

•INSTEAD OF: Execute the trigger body instead


of the triggering statement. This is used for
views that are not otherwise modifiable.
DML Trigger Components

Triggering user event: Which DML statement


causes the trigger to execute?
You can use any of the following:
•INSERT
•UPDATE
•DELETE
DML Trigger Components

Trigger type: Should the trigger body execute


for each row the statement affects or only
once?
•Statement: The trigger body executes once for
the triggering event. This is the default. A
statement trigger fires once, even if no rows
are affected at all.
•Row: The trigger body executes once for each
row affected by the triggering event. A row
trigger is not executed if the triggering event
affects no rows.
DML Trigger Components

Trigger body: What action should the trigger


perform?
The trigger body is a PL/SQL block or a call to a
procedure.
Syntax for Creating
DML Statement Triggers
Syntax:

CREATE [OR REPLACE] TRIGGER trigger_name


timing
event1 [OR event2 OR event3]
ON table_name
trigger_body

Note: Trigger names must be unique with


respect to other triggers in the same schema.
Example:
CREATE OR REPLACE TRIGGER secure_emp
BEFORE INSERT or UPDATE or DELETE ON emp
BEGIN
IF (TO_CHAR(SYSDATE,'DY') IN ('SAT','SUN')) OR
(TO_CHAR(SYSDATE,'HH24:MI')
NOT BETWEEN '08:00' AND '18:00')
THEN RAISE_APPLICATION_ERROR (-20500,
'DML allowed only during business hours.');
END IF;
END;
/
Using Conditional Predicates
CREATE OR REPLACE TRIGGER secure_emp
BEFORE INSERT OR UPDATE OR DELETE ON emp
BEGIN
IF (TO_CHAR (SYSDATE,'DY') IN ('SAT','SUN')) OR
(TO_CHAR (SYSDATE, 'HH24') NOT BETWEEN '08' AND '18')
THEN
IF DELETING THEN
RAISE_APPLICATION_ERROR (-20502,'You may delete from
EMP table only during business hours.');
ELSIF INSERTING THEN
RAISE_APPLICATION_ERROR (-20500,'You may insert into
EMP table only during business hours.');
ELSIF UPDATING THEN
RAISE_APPLICATION_ERROR (-20504,'You may update
EMP table only during normal hours.');
END IF;
END IF;
END;
Creating a DML Row Trigger

CREATE [OR REPLACE] TRIGGER trigger_name


timing
event1 [OR event2 OR event3]
ON table_name
[REFERENCING OLD AS old | NEW AS new]
FOR EACH ROW
[WHEN (condition)]
trigger_body
Using OLD and NEW Qualifiers

Within a ROW trigger, reference the value of a column


before and after the data change by prefixing it with the
OLD and NEW qualifier.
•The OLD and NEW qualifiers are available only in ROW
triggers.
•Prefix these qualifiers with a colon (:) in every SQL and
PL/SQL statement.
•There is no colon (:) prefix if the qualifiers are
referenced in the WHEN restricting condition.
Note: Row triggers can decrease the performance if you do
a lot of updates on larger tables.
Fires when DML is performed on EMP table

CREATE OR REPLACE TRIGGER Print_salary_changes


BEFORE INSERT OR UPDATE ON Emp
FOR EACH ROW
WHEN (new.Empno > 0)
DECLARE
sal_diff number;
BEGIN
sal_diff := :new.sal - :old.sal;
dbms_output.put_line('Old salary: ' || :old.sal);
dbms_output.put_line(' New salary: ' || :new.sal);
dbms_output.put_line(' Difference ' || sal_diff);
END;
INSTEAD OF Triggers
Application
INSERT INTO my_view
. . .;

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;

CREATE OR REPLACE TRIGGER INSTEADTRIG


INSTEAD OF INSERT ON EMPDEPTVIEW
FOR EACH ROW
DECLARE
dnos NUMBER(2);
BEGIN
IF INSERTING THEN
SELECT COUNT(*) INTO dnos FROM DEPT WHERE DEPTNO=:NEW.DEPTNO;
IF dnos=0 THEN
INSERT INTO DEPT VALUES(:NEW.DEPTNO,:NEW.DNAME,:NEW.LOC);
INSERT INTO EMP(EMPNO,ENAME,JOB,SAL,DEPTNO)
VALUES(:NEW.EMPNO,:NEW.ENAME,:NEW.JOB,:NEW.SAL,:NEW.DEPTNO);
ELSE
INSERT INTO EMP(EMPNO,ENAME,JOB,SAL,DEPTNO)
VALUES(:NEW.EMPNO,:NEW.ENAME,:NEW.JOB,:NEW.SAL,:NEW.DEPTNO);
END IF;
END IF;
EXCEPTION
WHEN others THEN
dbms_output.put_line('Exception occurred.');
END;
Altering triggers

ALTER TRIGGER trigger_name ENABLE|DISABLE;


ALTER TABLE table_name ENABLE|DISABLE all
triggers;
Dropping triggers:
DROP TRIGGER trigger_name;
The following data dictionary views reveal
information about triggers:
- USER_TRIGGERS

You might also like