PL-SQL Notes
PL-SQL Notes
PL-SQL Notes
Introduction to PL/SQL
Markup languages
Define how to add information into a document that indicates its logical
components or that provides layout instructions. Examples:
HTML, XML.
Structured Query Language is a language based on set theory, so it is all about
manipulating sets of data. SQL consists of a relatively small number of main
commands such as SELECT, INSERT, CREATE, and GRANT; in fact, each
statement accomplishes what might take hundreds of lines of procedural code to
accomplish. That's one reason SQL-based databases are so widely used.
Learning Oracle PL/SQL
PL/SQL, Oracle's programming language for stored procedures, delivers a world
of possibilities for your database programs. PL/SQL supplements the standard
relational database language, SQL, with a wide range of procedural features,
including loops, IF-THEN statements, advanced data structures, and rich
transactional control--all closely integrated with the Oracle database server.
PL/SQL is a procedural structured Query Language, is an extension to SQL
where we can write programs using all the SQL statements and procedural
statements.
Various procedural statements we can use in PL/SQL are
Assignment statements
Conditional statements
Loops
Transactional processing statements
Nested IF
IF <CONDITION1> THEN
ST1;
ST2;
ELSIF <CONDITION2> THEN
ST3;
ST4;
ELSIF <CONDITION3> THEN
ST5;
ELSE
ST6;
END IF;
In addition to these IF statements, we can also use SQL functions DECODE ()
and CASE.
1.
REVERSE
Without this keyword, the loop counter increases by one with every trip through
the loop, from the lower to the upper bound. With REVERSE, though, the loop
will decrease by one instead, going from the upper to the lower bound.
FOR n IN REVERSE 1..3
LOOP
END LOOP;
Also, the low and high values in the FOR loop range do not have to be literals, as
you can see in the next example:
FOR month_num IN 1 .. TO_NUMBER(TO_CHAR(SYSDATE, MM))
LOOP
Statements;
END LOOP;
As youre working with loops, its important to know that PL/SQL declares the
loop counter variable for you automatically, and there can be problems if it has
the same name as a variable youve declared in the usual place (the programs
declaration section). The scope (the only part of the code in which it can be
referenced) of the loop counter is between the LOOP and END LOOP keywords.
FOR Loops
Use a FOR loop to shortcut the test for the number of iterations
Do not declare the counter; it is declared implicitly
Lower_bound .. upper_bound is required
Reference the counter within the loop only; it is undefined outside the loop.
Do not reference the counter as the target of an assignment.
Conditional Loops
The simple loop is the, well, simplest loop structure. It has the following syntax:
LOOP
EXIT WHEN <CONDITION>;
Statements
END LOOP;
We can use this exit condition any where within the loop.
While Loop
While <Condition>
LOOP
Statements;
End Loop;
Transactional Processing Statements
We can use COOMIT and ROLLBACK as transactional processing statements.
Once the transaction is over then you decide whether you save the data or not to
save the data.
Note: - PL/SQL supports 4GL (object oriented programming language) features.
Every language uses some structure in writing programs. PL/SQL also uses two
different types of block structures in writing programs.
1. Unnamed PL/SQL block structure
2. Named PL/SQL block structure
The BEGIN and END keywords are mandatory and enclose the body of
actions to be performed. This section is referred to as the EXECUTABLE
SECTION (mandatory) where we write actual logic of the program.
Summary
Section
Description
Declarative Contains all variables, constants,
cursors, and user-defined exceptions
that are referenced in the executable
and declarative sections
Executable Contains
SQL
statements
in
manipulate data in the database and
PL/SQL statements to manipulate
data in the block
Exception Specifies the sections to perform
when errors and abnormal conditions
arise in the executable section
Inclusion
Optional
Mandatory
Optional
Scope of Variables
The scope of a variable is the portion of PL/SQL code in which that variable can
be referenced (i.e., its value read or modified). Most of the variables you define
will have as their scope the block in which they were defined. Consider the
following block:
DECLARE
book_title VARCHAR2 (100);
BEGIN
book_title := 'Learning Oracle PL/SQL';
END;
/
The variable book_title can be referenced within this block of code, but
nowhere else. So if I happen to write another separate block of code, any attempt
to read or change the value of book_titlewill result in a compilation error:
SQL> BEGIN
2 IF book_title LIKE '%PL/SQL%'
3 THEN
4 buy_it;
5 END IF;
6 END;
Types of Variables
PL/SQL variables:
All PL/SQL variables have a data type, which specifies a storage format,
constants, and valid range of values. Pl/SQL supports four data type
categories--
Scalar
Composite
Reference
LOB(large objects)
Non-PL/SQL variables:
Declaration section
A variable in PL/SQL can be declared in two different ways
1) Declaring variable by giving its data type and size
Syntax :
Identifier [CONSTANT] datatype [NOT NULL] [ := | DEFAULT expr];
Example
V_joindate DATE;
V_empno
Number(3) NOT NULL := 1001;
V_location VARCHAR2(10)
:= sec-bad;
C_comm.
CONSTANT NUMBER: = 1400;
Note: 1. = Used as comparison operator and
:= as assignment operator.
Data type
LONG RAW
NUMBER(precision,
scale)
BINARY_INTEGER
PLS_INTEGER
BOOLEAN
DATE
Description
Base type for fixed-length character data up to
32,767 bytes. If you do not specify a maximum
length, the default length is set to 1.
Base type for variable-length character data up o
32,767 bytes. There is no default size for
VARCHAR2 variables and constants.
Base type for variable-length character data up to
32,760 bytes. Use the LONG data type to store
variable-length character strings. You can insert any
LONG value into a LONG database column because
the maximum width of a LONG column is 2 ** 31
bytes. However, you cannot retrieve a value longer
than 32760 bytes from a LONG column into a LONG
variable.
Base type for binary data and byte strings up to
32,760 bytes.
Number having precision p and scale s. the precision
p can range from 1 to 38.
Base type for integers between 2,147,483,647 and
2,147,483,647
BASE type for signed integers between
%TYPE attribute that uses a database column defined as NOT NULL, you
can assign the NULL value to the variable.
Composite Data Types
A scalar type has no internal components. A composite type has internal
components that can be manipulated individually. Composite data types ( Also
known as collections) are of TABLE,RECORD, NESTED
<variable> <Tablename>%rowtype;
rec emp%rowtype;
Use of variables
Variables can be used for:
Temporary storage of data Data can be temporarily stored in one or more
variables for use when validating data input and for processing later in the
data flow process.
Manipulation of stored values Variables can be used for calculation and
other data manipulations without accessing the database.
Reusability After they declared, they can be used repeatedly in an
application simply by referencing them in other statements, including other
statements, including other declaratie statements.
Ease of maintenance When we declare variables using %TYPE and
%ROWTYPE, if any underlying definition changes, the variable definition
changes accordingly at run time. This provides data independence,
reduces maintenance costs.
Program
Write a program to maintain students information with
Rollno, Student_name, sub1,sub2, Total,average
Where sub1,sub2 are the marks in different subjects.
Solution
Step 1
Step 2
DECLARE
Stu
STUDENT%rowtype;
BEGIN
-- generate rollno automatically
SELECT nvl(max(rollno),0) + 1 into stu.rollno from student;
-- input name and marks in two subjects
stu.sname := &name;
stu.sub1 := &marks1;
stu.sub2 := &marks2;
Stu.total
:= stu.sub1 + stu.sub2;
Stu.average:= stu.total/2;
INSERT INTO STUDENT VALUES stu;
COMMIT;
END;
/
To run PL/SQL program
From SQL*Plus Environment
SQL> start student
Or
SQL> @student
From iSQL*Plus Environment
Use Execute button
Bind Variables
A bind variable is a variable that you declare in a host environment. Bind
variables can be used to pass run-time values, either number or character, into or
out of one or more PL/SQL programs.
The PL/SQL program use bind variables as they would use any other variable.
You can reference variables declared in the host or calling environment in
PL/SQL statements, unless the statement is in a procedure, function, or package.
Creating Bind Variables
To declare a bind variable In the iSQL*Plus environment, use the command
VARIABLE.
For example, we can declare a variable of type number and VARCHAR2 as
follows:
VARIABLE vsal NUMBER
VARIABLE getmsg as VARCHAR2 (30)
Both SQL and iSQL*Plus environment can reference the bind variable, and
iSQL*Plus can display its value through PRINT command
Using Bind Variables
To reference a bind variable in PL/SQL, you must prefix its name with a colon ( :)
Example
SQL>VARIABLE g_salary number
BEGIN
SELECT sal INTO :g_salary FROM EMP WHERE empno = 7521;
END;
/
SQL> PRINT g_salary
Note The DEFINE command specifies a user variable and assigns it a CHAR
value. Even though you enter the number 50000, iSQL*Plus assigns a CHAR
value to p_annual_sal consisting of the characters, 5,0,0,0 and 0.
Programming Guidelines
Make code maintenance easier by:
Code Conventions
The following table provides guidelines for writing code in uppercase or
lowercase to help you distinguish keywords from named objects.
Category
SQL statements
PL/SQL keywords
Data types
Identifiers and parameters
Database
tables
and
Case Convention
Uppercase
Uppercase
Uppercase
Lowercase
Lowercase
Examples
SELECT, INSERT
DECLARE,BEGIN,IF
VARCHAR2, BOOLEAN
V_sal_emp_cursor, g_sal
Emp, empno
columns
Summary
A Pl/SQL block is a basic, unnamed unit of a Pl/SQL program. It
consists of a set of SQL or PL/SQL statements and it performs a
single logical function. The declarative part is the first part of a
PL/SQL block and is used for declaring objects such as
variables, constants, cursors and exceptions. The executable
part is the mandatory part of a PL/SQL block, and contains SQL
and PL/SQL statements for querying and manipulating data. The
exception-handling part is embedded inside the executable part
of a block and is placed at the end of the executable part.
An anonymous PL/SQL block is the basic, unnamed unit of a
PL/SQL program. Procedures and functions can be compiled
separately and stored permanently in an Oracle database, ready
to be executed.
2.1 Introduction
In PL/SQL, errors and warnings are called as exceptions. Whenever a predefined
error occurs in the program, PL/SQL raises an exception. For example, if you try
to divide a number by zero then PL/SQL raises an exception called
ZERO_DIVIDE
and if SELECT can not find a record then PL/SQL raises
exception No_DATA_FOUND.
PL/SQL has a collection of predefined exceptions. Each exception has a name.
These exceptions are automatically raised by PL/SQL whenever the
corresponding error occurs.
In addition to predefined exceptions, user can also create his own exceptions to
deal with errors in the application.
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.
PL/SQL allows developers to raise and handle errors (exceptions) in a very
flexible and powerful way. Each PL/SQL block can have its own exception
section, in which exceptions can be trapped and handled (resolved
or passed on to the enclosing block).
When an exception occurs (is raised) in a PL/SQL block, its execution section
immediately terminates. Control is passed to the exception section.
Every exception in PL/SQL has an error number and error message; some
exceptions also have names.
Where error_number is a literal value (variable references are not allowed). This
number can be an Oracle error, such as -1855, or an error in the user-definable
-20000 to -20999 range.
Handling Exceptions
Trap the Exceptions
DECLARE
DECLARE
BEGIN
BEGIN
Exception
Is raised
EXCEPTION
Exception
Is trapped
EXCEPTION
END;
Exception
is raised
Exception
is not
trapped
END;
Exception propagates
To calling
Environment.
Trapping an Exception
If the exception is raised in the executable section of the block, processing
branches to the corresponding exception handler in the exception section of the
block. If PL/SQL successfully handles the exception, then the exception does not
propagates to the enclosing block or environment. The PL/SQL block terminates
successfully.
Propagating an Exception
If the exception is raised in the executable section of the block and there is no
corresponding exception handler, the PL/SQL block terminates with failure and
the exception is propagated to the calling environment.
Exception Types
}
}
}
No predefined Oracle Server }
Implicitly
raised
User-defined
Explicitly raised
You can program for exceptions to avoid disruption at run time. There are three
types of exceptions.
Exception
Predefined Oracle Server
error
No predefined Oracle
Server error
User-defined error
Description
One of approximately 20
errors that occur most
often in PL/SQL code
Any other standard
Oracle Server error
A condition that the
developer determines is
abnormal
Trapping Exceptions
Syntax
EXCEPTION
WHEN exception1 [ OR exception2 ] THEN
Statement1;
Statement2;
WHEN exception3 [ OR exception4 ] THEN
Statement3;
Statement4;
WHEN OTHERS THEN
Statement5;
Statement6;
The following PL/SQL block attempts to select information from the employee
and includes an exception handler for the case in which no data is found:
DECLARE
vempno NUMBER;
BEGIN
SELECT empno INTO vempno FROM EMP WHERE ename = 'RAM';
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO emp (empno, ename, job, deptno)
VALUES
(101,'RAM', 'EXECUTIVE', 10);
END;
In other words, if I am not already an employee in the company, the SELECT
statement fails and control is transferred to the exception section (which starts
with the keyword EXCEPTION). PL/SQL matches up the exception raised with
the exception in the WHEN clause (NO_DATA_FOUND is a named, internal
EXCEPTION
WHEN OTHERS THEN
...
Use the WHEN OTHERS clause in the exception handler as a catch all to trap
any exceptions that are not handled by specific WHEN clauses in the exception
section. If present, this clause must be the last exception handler in the exception
section.
The OTHERS handler traps all exceptions not already trapped. Some Oracle
tools have their own predefined exceptions that you can raise to cause events in
the application. The OTHERS handler also traps these exceptions.
For a complete list of predefined exceptions, see PL/SQL Users Guide and
Reference Error Handling
Note : PL/SQL declares predefined exceptions in the STANDARD package.
It is good idea to always handle the NO_DATA_FOUND
TOO_MANY_ROWS exceptions, which are the most common.
and
Declare
Associate
Declarative Section
Name the exception
Reference
Exception-handling
section
Handle the raised
exception
declare
deptno_in number;
still_have_employees EXCEPTION;
PRAGMA EXCEPTION_INIT(still_have_employees, -2292);
BEGIN
deptno_in := &deptno;
DELETE FROM d1
WHERE deptno = deptno_in;
EXCEPTION
WHEN still_have_employees
THEN
DBMS_OUTPUT.PUT_LINE
('Please delete employees in dept first');
ROLLBACK;
-- RAISE; /* Re-raise the current exception. */
END;
You trap a nonpredefined Oracle server error by declaring it first, or by using the
OTHERS handler. The declared exception is raised implicitly. In PL/SQL, the
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.
Note: PRAGMA (also called pseudoinstructions) is the keyword that signifies that
the statement is a compiler directive, which is not processed when the
PL/SQL block is executed. Rather, it directs the Pl/SQL compiler to
interpret all occurrences of the exception name within the block as the
associated Oracle server error number.
Declare
Declarative
section
Name the
Exception
Raise
Executable
Section
Reference
Exception-handling
Section
Handle the
raised
Exception.
Example:
DEFINE p_department_desc = Accounts
DEFINE p_department_number = 50
DECLARE
E_invalid_department EXCEPTION;
BEGIN
UPDATE dept
SET
dname = &p_department_desc
WHERE
deptno = &p_department_number;
IF SQL%NOTFOUND THEN
RAISE e_invalid_department;
END IF;
COMMIT;
EXCEPTION
WHEN e_invalid_department THEN
DBMS_OUTPUT.PUT_LINE(No such department id);
END;
Program 1
Write a program to maintain students information with
Rollno, Student_name, sub1,sub2, Total,average
Where sub1,sub2 are the marks in different subjects.
Solution
Step 1
Step 2
DECLARE
Stu
STUDENT%rowtype;
Negative
EXCEPTION;
BEGIN
-- generate rollno automatically
SELECT nvl(max(rollno),0) + 1 into stu.rollno from student;
-- input name and marks in two subjects
stu.sname := &name;
stu.sub1 := &marks1;
stu.sub2 := &marks2;
IF stu.sub1 < 0 or stu.sub2 < 0 then
RAISE negative;
END IF;
Stu.total
:= stu.sub1 + stu.sub2;
Stu.average:= stu.total/2;
INSERT INTO STUDENT VALUES stu;
COMMIT;
EXCEPTION
WHEN negative THEN
DBMS_OUTPUT.PUT_LINE( VE MARKS);
END;
/
Program 2
Write a program to get the salary of an employee
DECLARE
Vempno emp.empno%TYPE;
Vsal
emp.sal%TYPE;
BEGIN
Vempno := &empno;
SELECT sal into vsal from emp where empno = Vempno;
DBMS_OUTPUT.PUT_LINE(SALARY = || Vsal);
EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.PUT_LINE(Employee not found);
END;
/
a)Check what happened when we input a 5 digit number
b)Check what happens when we input employee number in single
quotes
c)Check what happens when we input alpha-numeric information
d)Check what happens when there is a duplicate empno
To handle all the above errors, we can modify the above program as
DECLARE
Vempno emp.empno%TYPE;
Vsal
emp.sal%TYPE;
BEGIN
Vempno := &empno;
SELECT sal into vsal from emp where empno = Vempno;
DBMS_OUTPUT.PUT_LINE(SALARY = || Vsal);
EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.PUT_LINE(Employee not found);
WHEN others then
DBMS_OUTPUT.PUT_LINE(SQLCODE || SQLCODE);
END;
/
Note :- SQLCODE and SQLERRM are called as Error Trapping functions.
SQLCODE displays error number (ORA-00001)
SQLERRM displays SQL error message
Exercise
1) Write a program to maintain employee details with
Empno, Ename, basic, da, hra, gross, pf, net
a)
b)
c)
d)
e)
f)
g)
Summary
In this lesion, you should have learned that:
Exception types:
- Predefined Oracle server error
- Nonpredefined Oracle server error
- User-defined error
Exception trapping
Exception handling
- Trap the exception within the PL/SQL block.
- Propagate the exception
LOOPS
1) Write a program to print the numbers in the format
1 2
4 5
7 8
3
6
9
1) Solution
begin
dbms_output.new_line;
for i in 1 .. 8
loop
for j in 1 .. 8
loop
dbms_output.put(j||' ');
end loop;
dbms_output.new_line;
end loop;
end;
3.0 Cursors
What is a Cursor?
Oracle uses work area to execute SQL commands and store processing
information. PL/SQL allows you to access this area through a name using a
cursor.
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.
When you execute a SQL statement from PL/SQL, the Oracle RDBMS
assigns a private work area for that statement. This work area contains
information about the SQL statement and the set of data returned or affected by
that statement.
The PL/SQL cursor is a mechanism by which you can name that work
area and manipulate the information within it. In its simplest form, you can think
of a cursor as a pointer into a table in the database.
Cursors are of two types in PL/SQL
Implicit cursor
Explicit cursor
Implicit cursor
PL/SQL declares a cursor implicitly for all SQL data manipulation statements,
including queries that return only one row. However, for queries that return more
than one row, you must declare an explicit cursor or use a cursor FOR loop. The
name of the implicit cursor is SQL. You can directly use the cursor without any
declaration.
Explicit Cursor
The set of rows returned by a query can consist of zero, one or multiple rows,
depending on how many rows meet your search criteria. When a query returns
multiple rows, you can explicitly declare a cursor to process the rows. The set of
rows returned by a multiple-row query is called the active set. It is
manipulated just like a file in programming languages.
Can process beyond the first row returned by the query, row by row.
Keep track of which row is currently being processed.
Allow the programmer to manually control them in the PL/SQL block.
Note: The fetch for an implicit cursor is an array fetch, and the existence of a
second row still raises the TOO_MANY_ROWS exception. Furthermore,
you can use explicit cursors to perform multiple fetches and to re-execute
parsed queries in the work area.
Let us understand the cursor, with C File. To make any changes in the file first we
have to open it (FOPEN () method). Once it is opened, it is placed in the memory
and a file pointer identifies this memory area (FP). To read a particular line of
information, we use a method (FREAD ()). The read information is stored into a
variable. The variable size is equal to the size of the information that you are
reading. To read each and every line from the file, we have to use a loop.
This loop is performed until it identifies EOF. Then we have to close the file
(FCLOSE () method), to free the memory space.
Assume that the file is there in the common share folder(in the server). Reading
each line from the server takes more time as well as we have to interact with the
server repeatedly, which increases the network traffic and reduces the efficiency.
Similarly, assume that your server is a Oracle server and the file is a database.
Every time we have to interact with server to get one row from the database. For
getting multiple records, each time we have to interact with database, which
reduces the efficiency. To over come this situation, we are defining a cursor,
through which we can get the required information into the memory and that
memory area is identified with cursor name (Like a file pointer).
In the place of fopen () method we are using OPEN () method. It places all the
required data into the memory.
We are using FREAD () method for reading each line of information from the file.
In the similar way we use FETCH method to get each record from memory.
After fetching one record, it should be placed into a variable. So, we have to
create a variable whose size is equal to the size of the information that we are
fetching.
Then we have to use a loop to read each and every record until nothing is there
to fetch.
Then close the cursor using CLOSE () method.
In more technical terms, a cursor is the name for a structure in memory, called a
private SQL area, which the server allocates at runtime for each SQL statement.
This memory area contains, among other things, a parsed version of the original
SQL statement.
If the host program uses any variables in the SQL statement, the cursor also
contains the memory addresses of these variables.
When you put SELECT statements into your PL/SQL, there are two ways to deal
with the data. You can use the SELECT INTO, as seen in the previous section, in
which case you are using an implicit cursor ("implicit" because you don't refer to it
specifically in your code; Oracle manages implicit cursors automatically). The
second way gives you more direct control over the creation, naming, and use of
cursors associated with your SELECTs. These cursors are called explicit cursors.
Cursor <cursorname> is
Select <column(s)> from <tablename> where
<Condition>;
Example
Cursor emp_cur is
Select empno, ename, job, sal from EMP where empno >= 7521;
Note:
Syntax
FETCH cursor_name INTO variable1, variable2,
For each column in the cursor there should be a corresponding variable in
FETCH statement.
FETCH statement is to be repeatedly executed to fetch all the rows of the cursor.
Example
CLOSE emp_cur;
Program
Write a program to test the cursor
SET SERVEROUTPUT ON -- SQL*plus Environment command
DECLARE
Cursor emp_cur is
Select empno, ename, job, sal from EMP where empno >= 7521;
Emp_rec emp_cur%rowtype;
BEGIN
/* open the cursor */
Open emp_cur;
/* fetch a record from cursor */
FETCH emp_cur into emp_rec;
DBMS_OUTPUT.PUT_LINE(emp_rec.empno || emp_rec.ename|| emp_rec.sal);
Analysis
This program reads and prints only one record from cursor
Program
To read each and every record from the cursor
SET SERVEROUTPUT ON
DECLARE
Cursor emp_cur is
Select empno, ename, job, sal from EMP where empno >= 7521;
Emp_rec emp_cur%rowtype;
BEGIN
/* open the cursor */
Open emp_cur;
/* fetch all the records of the cursor one by one */
LOOP
FETCH emp_cur into emp_rec;
/*
Exit loop if reached end of cursor
NOTFOUND is the cursor attribute
*/
exit when emp_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE (emp_rec.empno || emp_rec.ename|| emp_rec.sal);
END LOOP;
-- closing the cursor
CLOSE emp_cur;
END;
/
Passing parameters
Program
SET SERVEROUTPUT ON
DECLARE
Cursor emp_cur(v_empno number) is -- formal parameter
Select empno, ename, job, sal from EMP where empno >= v_empno;
Emp_rec emp_cur%rowtype;
V_eno emp.empno%type;
BEGIN
/* input the employee number */
v_eno := &empno;
/* open the cursor */
Open emp_cur(v_eno); -- Actual argument
/* fetch all the records of the cursor one by one */
LOOP
FETCH emp_cur into emp_rec;
/*
Exit loop if reached end of cursor
NOTFOUND is the cursor attribute
*/
exit when emp_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE (emp_rec.empno || emp_rec.ename|| emp_rec.sal);
END LOOP;
-- closing the cursor
CLOSE emp_cur;
END;
/
Cursor Attributes
Cursor attributes allow to get information regarding cursor. For example, you can
get the number of rows fetched so far from a cursor using ROWCOUNT
Use the following syntax to access cursor attributes
Cursor_name%Attribute
The following is the list of available cursor attributes:
Attribute
Data type
Significance
FOUND
BOOLEAN
NOTFOUND
BOOLEAN
ROWCOUNT
BOOLEAN
Recommended time
to use
After opening and
fetching from the
cursor but before
closing it (will be
NULL before first
fetch)
Same as above
Same as above
(except it will be zero
before the first fetch)
In addition to those cursor attributes, there are some less-commonly used cursor
attributes that you might see from time to time. They include:
ISOPEN Returns TRUE or FALSE depending on whether cursor_name is open.
Program
SET SERVEROUTPUT ON
DECLARE
Cursor emp_cur is
Select empno, ename, job, sal from EMP where empno >= 7521;
Emp_rec emp_cur%rowtype;
BEGIN
If not emp_cur%ISOPEN then
Open emp_cur;
End if;
LOOP
FETCH emp_cur into emp_rec;
If emp_cur%FOUND then
DBMS_OUTPUT.put_line(No of rows effected || emp_cur%ROWCOUNT);
Else
DBMS_OUTPT.put_line(END Of file );
END IF;
exit when emp_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE (emp_rec.empno || emp_rec.ename|| emp_rec.sal);
END LOOP;
CLOSE emp_cur;
END;
Cursor attributes can be used with both implicit and explicit cursors.
For example, the following shows how to use cursor attribute with implicit cursor:
Begin
Update EMP set sal = 1200 where ename like %E%;
/* If more than 5 rows are effected then rollback updation */
if SQL%ROWCOUNT > 5 then
Rollback;
else
commit;
end if;
End;
/
Note: 1) Except ISOPEN, all other attributes are implicit cursor attributes
2) When %ROWCOUNT is used with implicit cursor, it returns number of
rows effected by UPDATE, INSERT and DELETE commands. And when
used with explicit cursors, it returns the number of rows fetched so far
from the cursor.
Opening cursor
Closing cursor
Syntax
FOR rowtype_variable IN cursor_name
LOOP
Statements;
END LOOP;
Example
SET SERVEROUTPUT ON
declare
cursor c1 is
select empno,ename from emp;
begin
for c in c1
loop
dbms_output.put_line(c.empno || c.ename);
end loop;
end;
/
But C is available only inside the cursor for loop. It contains the same
columns as the cursor. In order to access a column of the current row of the
cursor, in the cursor for loop, use the format:
Rowtype_variable.columnname
Statements in the cursor for loop are executed once for each row of the
cursor. And for each row of the cursor, row is copied into
rowtype_variable.
Loop is terminated once end of cursor is reached. And cursor is closed.
Note : If parameters are to be passed to cursor, give the values after the
name of the cursor.
declare
cursor c1 (n number) is
Select empno, ename from EMP where empno >= n;
begin
for c in c1(7521)
loop
dbms_output.put_line (c.empno || c.ename);
end loop;
end;
Note: FOR UPDATE must be given if you want to use CURRENT OF clause
to refer to current row in the cursor.
Exercise
Write a program to Modify a particular entry in the passbook and update the
corresponding balances.( Handle suitable exceptions).
PASSBOOK
SNO
1
2
3
4
5
6
TRNDATE TRNTYPE
SYSDATE
D
SYSDATE
W
SYSDATE
W
SYSDATE
D
SYSDATE
W
SYSDATE
D
AMOUNT
30000
10000
2000
5000
3000
8000
BALANCE
30000
20000
18000
23000
20000
28000
In the above table, if we modify the amount in one particular transaction, Write a
program to modify the corresponding balances.
Handle suitable exceptions, to accept only a positive amount and in no case,
balance should become negative.
Summary
A cursor is always used by PL/SQL to execute single-row queries and
DML command. But in order to use multi-row query, you have to use
an explicit cursor. An explicit cursor contains a row-set, which is
retrieved by multi-row query.
Specially designed cursor FOR loop for cursors make cursor handling
very easy and automatic. FOR UPDATE clause is used to override
default locking and CURRENT OF is used to refer to current record in
the cursor.
Subprograms
Subprograms are named PL/SQL blocks that can accept parameters and be
invoked from a calling environment.
PL/SQL has two types of subprograms, procedures and functions.
What Is a Procedure?
A procedure is a type of subprogram that performs an action.
A procedure can be stored in the database, as a schema object, for repeated
execution.
Definition of a Procedure
A procedure is a named PL/SQL block that can accept parameters (sometimes
referred to as arguments), and be invoked. Generally speaking, you use a
procedure to perform an action. A procedure has a header, a declaration section,
an executable section, and an optional exception-handling section.
A procedure can be compiled and stored in the database as a schema object.
Procedures promote reusability and maintainability. When validated, they can be
used in any number of applications. If the requirements change, only the
procedure needs to be updated.
Creating Procedures
Objectives
After completing this lesson, you should be able to do the
following:
Objectives
After completing this lesson, you should be able to
do the following:
Describe PL/SQL blocks and subprograms
Describe the uses of procedures
Create procedures
Differentiate between formal and actual parameters
List the features of different parameter modes
Create procedures with parameters
Invoke a procedure
Handle exceptions in procedures
Remove a procedure
Lesson Aim
In this lesson, you learn the difference between anonymous PL/SQL blocks and
subprograms. You also learn to create, execute, and remove procedures.
Overview of Subprograms
A subprogram:
Is a named PL/SQL block that can accept parameters
and be invoked from a calling environment?
Is of two types:
A procedure that performs an action
A function that computes a value
Is based on standard PL/SQL block structure
Provides modularity, reusability, extensibility,
and maintainability.
Provides easy maintenance, improved data security
and integrity, improved performance, and improved
code clarity
A subprogram is based on standard PL/SQL structure that contains a declarative
section, an executable section, and an optional exception-handling section.
A subprogram can be compiled and stored in the database. It provides
modularity, extensibility, reusability, and maintainability.
Modularization is the process of breaking up large blocks of code into smaller
groups of code called modules. After code is modularized, the modules can be
reused by the same program or shared by other programs. It is easier to maintain
and debug code of smaller modules than a single large program. Also, the
modules can be easily extended for customization by incorporating more
functionality, if required, without affecting the remaining modules of the program.
Subprograms provide easy maintenance because the code is located in one
place and hence any modifications required to the subprogram can be performed
in this single location. Subprograms provide improved data integrity and security.
The data objects are accessed through the subprogram and a user can invoke
the subprogram only if appropriate access privilege is granted to the user.
Improved performance
After a subprogram is compiled, the parsed code is available in the shared
SQL area of the server and subsequent calls to the subprogram use this
parsed code. This avoids reparsing for multiple users.
Avoids PL/SQL parsing at run time by parsing at compile time
Subprogram Body
EXCEPTION (optional)
Exception Section
END;
Subprogram Specification
The header is relevant for named blocks only and determines the way that the
program unit is called or invoked.
The header determines:
The PL/SQL subprogram type, that is, either a procedure or a function
The name of the subprogram
The parameter list, if one exists
The RETURN clause, which applies only to functions
The IS or AS keyword is mandatory.
Subprogram Body
The declaration section of the block between IS|AS and BEGIN. The keyword
DECLARE that is used to indicate the start of the declaration section in
anonymous blocks is not used here.
The executable section between the BEGIN and END keywords is mandatory,
enclosing the body of actions to be performed. There must be at least one
statement existing in this section. There should be at least one NULL;
statement, which is considered an executable statement.
The exception section between EXCEPTION and END is optional. This section
traps predefined error conditions. In this section, you define actions to take if
the specified error condition arises.
PL/SQL block starts with either BEGIN or the declaration of local variables
and ends with either END or END procedure_name.
Syntax Definitions
You create new procedures with the CREATE PROCEDURE statement, which
may declare a list of parameters and must define the actions to be performed by
the standard PL/SQL block. The CREATE clause enables you to create standalone procedures, which are stored in an Oracle database.
PL/SQL blocks start with either BEGIN or the declaration of local variables and
end with either END or END procedure_name. You cannot reference host or bind
variables in the PL/SQL block of a stored procedure.
The REPLACE option indicates that if the procedure exists, it will be dropped
and replaced with the new version created by the statement.
You can not restrict the size of the data type in the parameters.
Parameter
Procedure_Name
Parameter
Mode
Data type
PL/SQL block
Description
Name of the procedure
Name of PL/SQL variable whose value is passed to or
populated by the calling environment, or both, depending on
the mode being used
Type of argument
IN (default)
OUT
IN OUT
Data type of argument can be any SQL/ PLSQL data type.
Can be of %TYPE, %ROWTYPE, or any scalar or
composite data type. You can not restrict the size of the
data type in the parameters.
Procedural body that defines the action performed by the
procedure.
Example:
raise_sal(v_id, 2000)
IN
Default Mode
Value is passed into
subprogram
OUT
Must be specified
Returned to Calling
Environment
Uninitialized variable
IN OUT
Must be specified
Passed into
subprogram; returned
to calling environment.
Initialized variable
Must be a variable
Must be a variable
Cannot be assigned a
default value
Cannot be assigned a
default value
IN Parameters: Example
CREATE OR REPLACE PROCEDURE raise_salary
(p_id IN emp.empno%TYPE)
IS
Vsal emp.sal%type;
BEGIN
Select sal into vsal from emp WHERE empno = p_id;
Dbms_output.put_line(vsal);
END raise_salary;
/
IN Parameters: Example
The example shows a procedure with one IN parameter. Running this statement
in iSQL*Plus creates the RAISE_SALARY procedure. When invoked,
RAISE_SALARY accepts the parameter for the employee ID and gets the Salary
of that employee.
To invoke a procedure in iSQL*Plus, use the EXECUTE command.
EXECUTE raise_salary (176)
To invoke a procedure from another procedure, use a direct call. At the location
of calling the new procedure, enter the procedure name and actual parameters.
raise_salary (176);
IN parameters are passed as constants from the calling environment into the
procedure. Attempts to change the value of an IN parameter result in an error.
Do not specify a size for a host variable of data type NUMBER when using the
VARIABLE command. A host variable of data type CHAR or VARCHAR2 defaults
to a length of one, unless a value is supplied in parentheses.
IN OUT Parameters
Example
Create a procedure with an IN OUT parameter to accept a character string
containing 10 digits and return a phone number formatted as (800) 633-0575.
Calling environment FORMAT_PHONE procedure
8006330575 (800)633-0575 p_phone_no
CREATE OR REPLACE PROCEDURE format_phone
(p_phone_no IN OUT VARCHAR2)
IS
BEGIN
p_phone_no := ( || SUBSTR(p_phone_no,1,3) ||
) || SUBSTR(p_phone_no,4,3) ||
- || SUBSTR(p_phone_no,7);
END format_phone;
/
Using IN OUT Parameters
With an IN OUT parameter, you can pass values into a procedure and return a
value to the calling environment. The value that is returned is the original, an
unchanged value, or a new value set within the procedure.
An IN OUT parameter acts as an initialized variable.
Run the statement to create the FORMAT_PHONE procedure.
Viewing IN OUT Parameters
VARIABLE g_phone_no VARCHAR2(15)
BEGIN
:g_phone_no := 8006330575;
END;
/
PRINT g_phone_no
EXECUTE format_phone (:g_phone_no)
PRINT g_phone_no
Exercise
1.
2.
3.
4.
5.
6.
7.
Creating Functions
Objectives
Example
CREATE OR REPLACE FUNCTION get_sal
(p_id emp.empno%TYPE)
RETURN NUMBER
IS
v_salary emp.sal%TYPE ;
BEGIN
SELECT sal INTO v_salary FROM emp WHERE empno = p_id;
RETURN v_salary;
END get_sal;
/
Executing Functions
Invoke a function as part of a PL/SQL expression.
Create a variable to hold the returned value.
Execute the function. The variable will be
populated by the value returned through a RETURN statement.
Example
VARIABLE g_salary NUMBER
EXECUTE :g_salary := get_sal(117)
PRINT g_salary
Exercise
1.
2.
3.
4.
PACKAGES
What is A Package?
Packages are containers of related procedures, functions and variables.
When we create different procedures and functions, they are stored as
independent objects. To group these objects together, we are creating packages.
Each package contains the following parts:
Package specification
Package body
Package Specification
Contains all declarations for variable, cursor, procedures and functions that are to
be made public. All public objects of package are visible outside the package.
Syntax
CREATE OR REPLACE PACKAGE package_name
IS
/* declare public objects of package */
END;
Package Body
Defines all the objects of the package. Objects declared in the specification are
called as public objects and the objects directly defined in the body without
declaring in the specification, are called as PRIVATE members.
Syntax
Local variables
Program
CREATE OR REPLACE PACKAGE SAMPLEPAK
IS
PROCEDURE PROC1( N NUMBER, N1 OUT NUMBER);
FUNCTION FUN1(N NUMBER) RETURN NUMBER;
END;
/
CREATE OR REPLACE PACKAGE BODY SAMPLEPAK
IS
PROCEDURE PROC1(N NUMBER, N1 OUT NUMBER)
IS
BEGIN
N1 := N * 5;
END PROC1;
FUNCTION FUN1(N NUMBER) RETURN NUMBER
IS
N1 NUMBER;
BEGIN
N1 := N * 2;
RETURN N1;
END FUN1;
END SAMPLEPAK;
/
Execution
VARIABLE N NUMBER
EXECUTE SAMPLEPAK.PROC1(5,:N)
PRINT N
EXECUTE :N := SAMPLEPAK.FUN1(4)
PRINT N
Execution
VARIABLE N NUMBER
EXECUTE SAMPLEPAK.PROC1(5,:N)
PRINT N
EXECUTE :N := SAMPLEPAK.FUN1(4)
PRINT N
Note :- A private member can not be accessed by referring package object. They
are called only through public members of the package object.
Program
CREATE OR REPLACE PACKAGE POLYPACK
IS
PROCEDURE PROC1( N NUMBER, N1 OUT NUMBER);
PROCEDURE PROC1 (X VARCHAR2,Y VARCHAR2,Z OUT VARCHAR2);
END;
/
CREATE OR REPLACE PACKAGE BODY POLYPACK
IS
PROCEDURE PROC1(N NUMBER, N1 OUT NUMBER)
IS
BEGIN
N1 := N * 5;
END PROC1;
PROCEDURE PROC1(X VARCHAR2,Y VARCHAR2, Z OUT VARCHAR2)
IS
BEGIN
Z := CONCAT(X,Y);
END PROC1;
END POLYPACK;
/
Execution
VARIABLE N NUMBER
VARIABLE ST VARCHAR2(100)
EXECUTE POLYPACK.PROC1(5,:N)
PRINT N
Objectives
After completing this lesion, you should be able to
do the following:
Describe different types of triggers
Describe database triggers and their use
Create Database triggers
Describe database trigger firing rules
Remove database triggers
Trigger - Levels
These Triggers are written at three different levels
Schema
TABLE
ROW
Types of Triggers
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
Can be either
Application trigger : Fires whenever an event
occurs with a particular application.
Database trigger: Fires whenever a data event
(such as DML) or system event (such as logon
or shutdown) occurs on a schema or database.
Types of Triggers
Row Triggers : A row trigger is fired each time the table is affected by triggering
statement. For example, if an UPDATE statement updates multiple rows of a
table, a row trigger is fired once for each row affected by the UPDATE statement.
If a triggering statement affects no rows, a row trigger is not executed at all.
A Row trigger is fired once for each row affected by the command. These triggers
are used to check for the validity of the data in the triggering statements and
rows affected.
triggers are called INSTEAD-OF triggers because, unlike other types of triggers,
Oracle fires the trigger instead of executing the triggering statement.
A trigger could also restrict DML operations to occur only at certain times
during weekdays.
Modify table data when DML statements are issued against views
END;
END;
Testing secure_emp
INSERT INTO EMP (empno, ename) VALUES (101,ravi);
ERROR at line 1
ORA-20001 You may insert into EMP table only during business hours
ORA-06512 at PLSQL SECURE_emp, LINE 4
Ora-04088 error during execution of trigger PLSQL SECURE_EMP
Note : The row might be inserted if you are in a different time zone from the
database server. The trigger fires even if your system clock is within these
business hours.
Data Operation
INSERT
UPDATE
DELETE
Old Value
Null
Value before update
Value before delete
New Value
Inserted value
Value after update
NULL
The OLD and NEW qualifiers are available only in ROW triggers
Prefix these qualifiers a colon ( : ) in every SQL and PL/SQL statement
There is no colon ( : ) prefix if the qualifiers are referenced in the WHEN
restricting condition
Exercise
1) Write a trigger to access the table in a specified time
2) Write a trigger to accept only valid updations (Example, fire the trigger if
the employee salary is modified with lesser value than his original salary)
3) Write a trigger to accept unique values in to a particular column of a table,
when we are placing a new record.
4) Write a trigger to update stock automatically when customer makes a
transaction
Itemmaster
Itemno
itemname stock
Itemtran
Transaction_no
ROSEDAWSON*315
EXPECTO*315
J@NUARY:-)h0ME315