Post on 04-Jan-2016
Overview
· What is PL/SQL· Advantages of PL/SQL· Basic Structure of a PL/SQL Block· Anonymous Block· Types of Block· Declaring a Variable· Constant· Variable Initialization· Select Statement· Execution Control · Cursor· If Statement· Basic Loop· For Loop· While Loop· Exception Handling· Procedure· Function
What is PL/SQL
Increase the expressiveness of SQL, Process query results in a tuple-oriented way, Optimize combined SQL statements, Develop modular database application
programs, Reuse program code, and Reduce the cost for maintaining and changing
applications.
Advantages of PL/SQL
Can include error handling and control
structures
Can be stored and used by various application programs or users
Allows for tighter security by granting privileges for executing stored procedures rather than granting privileges directly on database object
Basic Structure of a PL/SQL Block· Has three sections:
Declarative sectionExecutable sectionException-handling section
· Syntax:[DECLARE]BEGIN… SQL & other executable statements[EXCEPTION]END;
Structure of PL-SQL block [<Block header>] [declare
<Constants><Variables><Cursors><User defined exceptions>]
begin<PL/SQL statements/ executable commands>[exception<Exception handling>]
end;
Declarative Section Identified by the DECLARE keyword Used to define variables and constants referenced in the
block Variable:
o Reserve a temporary storage area in memoryo Manipulated without accessing a physical storage medium
Constant:o Its assigned value can’t be changed during execution
Forward execution:o Variable and constants must be declared before they can
be referenced
Executable Section
Identified by the BEGIN keyword
o Mandatory
o Can consist of several SQL and/or PL/SQL statements
Used to access & manipulate data within the block
Exception-handling Section
Identified by the EXCEPTION keyword Used to display messages or identify other actions
to be taken when an error occurs Addresses errors that occur during a statement’s
execution Examples: No rows returned or divide by zero
errors
Types of Blocks
· Anonymous block
· Procedure
· Function
Anonymous Block
Not stored since it cannot be referenced by
a name Usually embedded in an application
program, stored in a script file, or manually entered when needed
To perform one-time processing activities
Declaring a Variable· Reserves a temporary storage area in the computer’s memory· Every variable must have:
A nameA data type
Form is <variable> <data type>
· Variables can be initialized· Variable name can consist of up to 30 characters, numbers,
or special symbols· Variable name must begin with a character · You can use naming conventions, for example v_name to
represent a variable, and c_name to represent a constant.
Constants
·Variables that have a value that does not
change during the execution of the block
· Optional CONSTANT keyword can be
used to designate a constant in the block’s
declarative section
Variable Initialization Use DEFAULT keyword or (:=) assignment
operator Variable must be initialized if it is assigned a
NOT NULL constraint Non-numeric data types must be enclosed in
single quotation marks
Variable Initialization Examples
ExampleDeclare
pi constant NUMBER(9,7) := 3.1415927; radius INTEGER(5); area NUMBER(14,2);
begin radius := 3; area := pi*power(radius,2);
insert into AREAS values (radius, area);end;/
• The end; line signals the end of the PL/SQL block;• Depending on the tool you use, you may need to add a slash
(/) to execute the PL/SQL block.
%TYPE & %ROWTYPE%TYPE
Takes the data type from the table
Form is
<variable> <table>.<column>%TYPE
%TYPE & %ROWTYPE %ROWTYPE
Creates a record with fields for each column of the specified
tableDECLARE
row_variable table %ROWTYPE;
BEGIN
SELECT column name1, column name2, …………
INTO row_variable
FROM table nameWHERE column name = variable name;
The variables are then accessed as: row_variable.column name where column name is the name of a column in the table.
Allows programs to adapt as the database changes
Examplecreate table AREAS(
radius number(7,2),
area number(14,2));
create table RADIUS_VALS(
radius number(7,2));
Example (%TYPE)Declare
pi constant NUMBER(9,7) := 3.1415927; radi areas.radius%type; a areas.area%type ;
begin radi := 4; a := pi*power(radi,2);
insert into AREAS values (radi, a);end;/
PL/SQL procedure successfully completed.
Example (%ROWTYPE )Declare
pi constant NUMBER(9,7) := 3.1415927; a areas%rowtype ;
begin a.radius := 6; a.area := pi*power(a.radius,2);
insert into AREAS values (a.radius, a.area);end;/
SELECT Statement
The SELECT statement may be used in a block ofcode but the following example will return an error:
BEGINSELECT Cust_idFROM Customer;
END;
Correct form is:select <column(s)> into <matching list of variables> from <table(s)>
SELECT Statement
Requires use of INTO clause to identify variableassigned to each data element Syntax:
SELECT columnname [, columnname, …]INTO variablename [, variablename, …]FROM tablenameWHERE condition;
SELECT Statement Example
DECLARE
S_Cust_id VARCHAR2(12);
S_Cust_name VARCHAR2(12);
S_Cust_dob DATE;
BEGIN
Select Cust_id, Cust_name, Cust_dob
Into S_Cust_id, S_Cust_name, S_Cust_dob
From Customer
Where Cust_id = 'C00000000005';
DBMS_OUTPUT.PUT_LINE('CustomerName:'||
S_Cust_name || 'Customer Date of Birth: ' || S_Cust_dob);
END;
/
Terminal ResponseSET SERVEROUTPUT ON;
DBMS_OUTPUT.PUT_LINE();
Form of argument ('Salary is: ' || salary)
Example: DBMS_OUTPUT.PUT_LINE('Name:‘|| fname);
Problem of previous Select It is important to ensure that the select statement
retrieves at most one tuple! Otherwise it is not possible to assign the attribute values
to the specified list of variables and a runtime error occurs.
If the select statement retrieves more than one tuple, a cursor must be used instead.
Furthermore, the data types of the specified variables must match those of the retrieved attribute values.
For most data types, PL/SQL performs an automatic type conversion (e.g., from integer to real).
Cursors
When a query returns multiple rows, defining
a cursor allows us to» process beyond the first row returned
» keep track of which row is currently being processed
Cursors are defined and manipulated using» DECLARE
» OPEN
» FETCH
» CLOSE
Declaring Cursors
Syntax· Cursor name - similar to a pointer variable· There is no INTO clause· Example
CURSOR <cursor name> IS <select-expression>;
CURSOR emp_cursor ISSELECT employee_id, employee_nameFROM employeeWHERE employee_name LIKE 'E%';
Cursors
Opening a Cursor
Opens a cursor (which must be closed) Gets the query result from the database The rows returned become the cursor's current active set
Sets the cursor to position before the first row. This becomes the current row.
NOTE - You must use the same cursor name if you want data from that cursor.
OPEN <cursor name>;
OPEN emp_cursor;
Fetching A Row
SyntaxMoves the cursor to the next row in the current active set
Assigns values to the host variables
FETCH <cursor name>
INTO <host variables>;
FETCH emp_cursor
INTO e_id, e_name;
Closing the Cursor
Closes the cursor (which must be open) There is no longer an active set Reopening the same cursor will reset it to
point to the beginning of the returned table
CLOSE <cursor name>;
CLOSE emp_cursor;
Fetching A Row
CURSOR ExampleDECLARE
CURSOR emp_cursor ISSELECT employee_id, employee_nameFROM employeeWHERE employee_name LIKE 'E%';emp_val emp_cursor%ROWTYPE;
BEGINOPEN emp_cursor;FETCH emp_cursor INTO emp_val;DBMS_OUTPUT.PUT_LINE(emp_val.employee_id);CLOSE emp_cursor;
END;/
Examplecreate table AREAS(
radius number(7,2),
area number(14,2));
create table RADIUS_VALS(
radius number(7,2));
ExampleDeclare
Pi constant NUMBER(9,7) := 3.1415927; area NUMBER(14,2); cursor rad_cursor is select * from
RADIUS_VALS; rad_val rad_cursor%ROWTYPE;
begin open rad_cursor; fetch rad_cursor into rad_val; area := pi*power(rad_val.radius,2); insert into AREAS values (rad_val.radius, area); close rad_cursor;
end;/
Explanation When the rad_cursor cursor is opened, the query
declared for that cursor is executed and the records to be returned are identified.
Next, records are fetched from the cursor. In the Declarations section, the rad_val variable is
declared to anchor its datatypes to the rad _cursor cursor.
When you fetch a record from the cursor into the rad_val variable, you can still address each column value selected via the cursor’s query.
When the cursor’s data is no longer needed, you can close the cursor.
ExampleYou can even base %TYPE definitions on
cursors.cursor rad_cursor is
select * from RADIUS_VALS;
rad_val rad_cursor%ROWTYPE;
rad_val_radius rad_val.Radius%TYPE;
In the example, the rad_val variable inherits the datatypes of the result set of the rad_cursor cursor.
The rad_val_radius variable inherits the datatype of the Radius column within the rad_val variable
Cursor Properties
Cursors have four attributes that can be used
In program:
–%FOUND, %NOTFOUND : a record can/cannot be fetched from the cursor
–%ISOPEN : the cursor has been opened
–%ROWCOUNT : the number of rows fetched from the cursor so far
Execution Control Decision: IF statement
executes statements based on a condition
Loops: Basic loop
Executes statements until condition in EXIT clause is TRUE
FOR loop
Uses counter
WHILE loop
Executes statements until condition is FALSE
IF Statement Syntax:
IF <condition 1> THEN
<command 1>
ELSIF <condition 2> THEN
<command 2>
ELSE
<command 3>
END IF;
Flow Chart of IF-THEN-ELSE
IF Statement
Basic Loop
Syntax:
LOOP
Statements;
EXIT [WHEN condition];
END LOOP;
Flow chart of Loop
Basic Loop
FOR Loop
Syntax:
FOR counter IN [reverse] lower_limit .. upper_limit
LOOP
sequence of statements;
END LOOP;
For Loop The loop counter is declared implicitly. The scope of the loop counter is only the
for loop. It overrides the scope of any variable
having the same name outside the loop. Inside the for loop, counter can be
referenced like a constant. counter may appear in expressions, but
one cannot assign a value to counter.
For Loop
Using the keyword reverse causes the iteration to proceed downwards from the higher bound to the lower bound.
A loop can be named. Naming a loop is useful whenever loops are nested and inner loops are completed unconditionally using the
exit <label name>; statement
Flow Chart of For Loop
FOR Loop
WHILE Loop
Syntax:
WHILE condition LOOP
Statements;
END LOOP;
Flow Chart of While Loop
WHILE Loop
Simple Loopsdeclare
pi constant NUMBER(9,7) := 3.1415927;
radius INTEGER(5);
area NUMBER(14,2);
begin
radius := 3;
Loop
area := pi*power(radius,2);
insert into AREAS values (radius, area);
radius := radius+1;
exit when area >100;
end loop;
end;
For Loopsdeclare
pi constant NUMBER(9,7) := 3.1415927;
radius INTEGER(5);
area NUMBER(14,2);
begin
/* Specify the criteria for the number of loop executions. */
for radius in 1..7 loop
area := pi*power(radius,2);
insert into AREAS values (radius, area);
/* Signal the end of the loop. */
end loop;
end;
/
For Loopsdeclare
pi constant NUMBER(9,7) := 3.1415927;
radius INTEGER(5);
area NUMBER(14,2);
begin
for radius in reverse 7..1 loop
area := pi*power(radius,2);
insert into AREAS values (radius, area);
end loop;
end;
/
Simple While Loopdeclare
pi constant NUMBER(9,7) := 3.1415927;
radius INTEGER(5);
area NUMBER(14,2);
begin
radius := 3;
while area<100
loop
area := pi*power(radius,2);
DBMS_OUTPUT.PUT_LINE(concat('Radius is:',radius));
DBMS_OUTPUT.PUT_LINE(concat('Areas is:', area));
radius := radius+1;
end loop;
end;
/
Nested Loops
Any type of loop can be nested inside
another loop Execution of the inner loop must
becompleted before control is returned to the outer loop
Nested Loops
Continue
You can use the continue statement within loops to exit the current iteration of the loop and transfer control to the next iteration.
For example, if you iterate through a set of counter values, you can skip specific values without exiting the loop entirely.
The two forms of the continue statement are continue and continue when.
The when portion provides the condition to be evaluated.
If the condition is true, the current iteration of the loop will complete and control will pass to the next iteration.
Continuedeclare
pi constant NUMBER(9,7) := 3.1415927;
radius INTEGER(5);
area NUMBER(14,2);
begin
radius := 1;
loop
if radius < 5 then
continue;
end if;
area := pi*power(radius,2);
insert into AREAS values (radius, area);
radius := radius+1;
exit when area >100;
end loop;
end;
Continue whendeclare
pi constant NUMBER(9,7) := 3.1415927;
radius INTEGER(5);
area NUMBER(14,2);
begin
radius := 1;
loop
continue when radius < 5;
area := pi*power(radius,2);
insert into AREAS values (radius, area);
radius := radius+1;
exit when area >100;
end loop;
end;
Case You can use case statements to control the branching logic
within your PL/SQL blocks. For example, you can use case statements to assign values
conditionally or to transform values prior to inserting them. case CategoryName
when ‘SCIFI' then ‘Science Fiction' when 'ADV' then 'Adventure' when ‘ANIM' then 'Animation '
else CASE_NOT_FOUND end
The keyword case begins the clause. The when clauses are evaluated sequentially. The else keyword within the case clause works similarly to
the else keyword within an if - then clause.
Simple Cursor Loops
You can use the attributes of a cursor—such as whether or not any rows are left to be fetched—as the exit criteria for a loop.
In the following examples, a cursor is executed until no more rows are returned by the query.
Before a cursor can be used, it must be opened using the open statement
The associated select statement then is processed and the cursor references the first selected tuple.
Selected tuples then can be processed one tuple at a time using the fetch command
Simple Cursor Loops The fetch command assigns the selected attribute values of the
current tuple to the list of variables. After the fetch command, the cursor advances to the next tuple
in the result set. Note that the variables in the list must have the same data
types as the selected values. After all tuples have been processed, the close command is
used to disable the cursor. Each loop can be completed unconditionally using the exit
clause:
exit [<block label>] [when <condition>]
Simple Cursor Loops Using exit without a block label causes the completion of the
loop that contains the exit statement The condition refers to a cursor. To determine the status of the
cursor, the cursor’s attributes are checked. Cursors have four attributes you can use in your program:
%FOUND- A record can be fetched from the cursor. %NOTFOUND- No more records can be fetched from the cursor. %ISOPEN - The cursor has been opened. %ROWCOUNT - The number of rows fetched from the cursor so far.
The %FOUND, %NOTFOUND, and %ISOPEN cursor attributes are Booleans; they are set to either TRUE or FALSE.
You can evaluate their settings without explicitly matching them to values of TRUE or FALSE.
Simple Cursor Loops DECLARE
CURSOR emp_cursor IS
SELECT employee_id, employee_name, sal FROM employee
WHERE employee_name LIKE 'E%';
emp_val emp_cursor%ROWTYPE;
emp_sal emp_cursor.sal%TYPE
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO emp_val;
EXIT WHEN emp_cursor%NOTFOUND;
emp_sal := emp_val.sal;
DBMS_OUTPUT.PUT_LINE(emp_val.employee_id);
END LOOP;
CLOSE emp_cursor;
END;
/
Simple Cursor LoopDeclare
pi constant NUMBER(9,7) := 3.1415927;
area NUMBER(14,2);
cursor rad_cursor is select * from RADIUS_VALS;
rad_val rad_cursor%ROWTYPE;
begin
open rad_cursor;
loop
fetch rad_cursor into rad_val;
exit when rad_cursor%NOTFOUND;
area := pi*power(rad_val.radius,2);
DBMS_OUTPUT.PUT_LINE(concat('Radius is:',rad_val.radius));
DBMS_OUTPUT.PUT_LINE(concat('Areas is:', area));
end loop;
close rad_cursor;
End;
Simple Cursor Loops In the example above, %NOTFOUND is a
predicate that evaluates to false if the most recent fetch command has read a tuple.
The value of <cursor name>%NOTFOUND is null before the first tuple is fetched.
The predicate evaluates to true if the most recent fetch failed to return a tuple, and false otherwise.
%FOUND is the logical opposite of %NOTFOUND.
Cursor FOR Loops • A Cursor FOR loop uses the results of a query
to dynamically determine the number of times the loop is executed.
• In a Cursor FOR loop, the opening, fetching, and closing of cursors is performed implicitly;
• You do not need to explicitly specify these actions.
• Cursor for loops can be used to simplify the usage of a cursor
Cursor FOR LoopsDECLARE
CURSOR emp_cursor IS
SELECT employee_id, employee_name, sal
FROM employee
WHERE employee_name LIKE 'E%';
BEGIN
for emp_val in emp_cursor
LOOP
emp_sal := emp_val.sal;
DBMS_OUTPUT.PUT_LINE(emp_val.employee_id);
END LOOP;
END;
/
Fetches the current row to emp_val
Cursor FOR Loops • In a Cursor FOR Loop, there is no open or fetch
command. • A record suitable to store a tuple fetched by the cursor
is implicitly declared. • Note that emp_val is not explicitly declared in the block.• Furthermore, this loop implicitly performs a fetch at
each iteration as well as an open before the loop is entered and a close after the loop is left.
• If at an iteration no tuple has been fetched, the loop is automatically terminated without an exit.
Cursor FOR Loops • The command for emp_val in emp_cursor implicitly
opens the emp_cursor cursor and fetches a value into the emp_val variable.
• When no more records are in the cursor, the loop is exited and the cursor is closed.
• In a Cursor FOR loop, there is no need for a close command. • It is even possible to specify a query instead of <cursor
name> in a for loop:- for sal_rec in (select SAL + COMM total from EMP) loop
- . . . ;- end loop;
Cursor FOR Loops • Except data definition language commands such as
create table, all types of SQL statements: delete, insert, update, and commit can be used in PL/SQL blocks
• Note that in PL/SQL only select statements of the type select <column(s)> into are allowed, i.e., selected attribute values can only be assigned to variables (unless the select statement is used in a subquery).
• The usage of select statements as in SQL leads to a syntax error.
Cursor For Loopdeclare
pi constant NUMBER(9,7) := 3.1415927;
area NUMBER(14,2);
cursor rad_cursor is
select * from RADIUS_VALS;
begin
/* If a record can be fetched from the cursor, then fetch it into the rad_val variable. If no rows can be fetched, then skip the loop. */
for rad_val in rad_cursor
loop
area := pi*power(rad_val.radius,2);
DBMS_OUTPUT.PUT_LINE(concat('Radius is:',rad_val.radius));
DBMS_OUTPUT.PUT_LINE(concat('Areas is:', area));
end loop;
end;
/
Cursor Update If some tuples selected by the cursor will be modified in
the PL/SQL block, the clause for update [(<column(s)>)] has to be added at the end of the cursor declaration.
In this case selected tuples are locked and cannot be accessed by other users until a commit has been issued.
If update or delete statements are used in combination with a cursor, these commands can be restricted to currently fetched tuple.
In these cases the clause where current of<cursor name> is added as shown in the following example.
Cursor Update (Error!) All employees having ’KING’ as their manager get a 5% salary increase. Note that the record emp_rec is implicitly defined. //check below
Declare
manager EMP.MGR%TYPE;
cursor emp_cur (mgr no number) is
select SAL from EMP
where MGR = mgr no
for update of SAL;
Begin
for emp_rec in emp cur(manager) loop
select EMPNO into manager from EMP where ENAME = ’KING’;
update EMP set SAL = emp_rec.sal * 1.05
where current of emp_cur;
end loop;
commit;
end;
Procedure
• Sophisticated business rules and application logic can be stored as procedures within Oracle
• You may group procedures and other PL/SQL commands into packages.
You may experience performance gains when using procedures for two reasons:
The processing of complex business rules may be performed within the database—and therefore by the server.
Because the procedural code is stored within the database and is fairly static, you may also benefit from the reuse of the same queries within the database
Procedure · Also called “Stored Procedures”· Named block· Can process several variables· Returns no values
· Interacts with application program using IN, OUT, or INOUT parameters
Valid parameters include all data types. However, for char, varchar2, and number no length
and scale, respectively, can be specified. For example, the parameter number (6) results in a
compile error and must be replaced by number
Procedure Basic Syntax CREATE [OR REPLACE] PROCEDURE name
[( argument [IN|OUT|IN OUT] datatype
[{, argument [IN|OUT|IN OUT] datatype }] )]
AS
/* declaration section */
BEGIN
/* executable section - required*/
EXCEPTION
/* error handling statements */
END;
/
Some Details Parameter direction: The optional clauses IN, OUT,
and IN OUT specify the way in which the parameter is used. The default mode is IN» IN (default) : means that the parameter can be referenced inside the procedure body, but it cannot be changed» OUT: means that a value can be assigned to the parameter in the body, but the parameter’s value cannot be referenced. The OUT qualifier signifies that the procedure passes a value back to the caller through this argument» IN OUT: allows both assigning values to the parameter and referencing the parameter.
Some Details IN OUT: A value must be specified for this argument
when the procedure is called, and the procedure will return a value to the caller via this argument
Executing procedures» EXECUTE <name>(<parameters>)» EXECUTE <name>;
A procedure can be deleted using the command
drop procedure <procedure name> drop function <function name>
Procedure ExampleCreate Procedure Insert_Customer(customerid IN varchar2)
As
BEGIN
insert into customer
values(customerid,Null, Null, Null, Null);
END;
/
Execute Insert_Customer(‘c_67’);
Function
· Named block that is stored on the Oracle
server
· Accepts zero or more input parameters
· Returns one value
Function Basic SyntaxCREATE [OR REPLACE] FUNCTION name
[( argument datatype
[{, argument datatype}] )]
RETURN datatype
AS
/* declaration section */
BEGIN
/* executable section - required*/
EXCEPTION
/* error handling statements */
END;
/
Function ExampleCREATE OR REPLACE FUNCTION getBDate (customerid VARCHAR2)RETURN DATEAS
v_bdate customer.cust_dob%TYPE;BEGIN
SELECT cust_dob INTO v_bdateFROM customerWHERE cust_id = customerid;RETURN v_bdate;
END;/
select getBDate('C00000000005')) from dual;
Function Example
CREATE OR REPLACE
PROCEDURE show_date(c_id VARCHAR2)
AS
BEGIN
DBMS_OUTPUT.PUT_LINE(getBDate(c_id));
END;
/
Execute show_date('C00000000005');
Exception Handling
A PL/SQL block may contain statements that specify Exception handling routines.
Each error or warning during the execution of a PL/SQL block raises an exception.
One can distinguish between two types of exceptions:
· system defined exceptions
· user defined exceptions
System Defined Exceptions
System defined exceptions are always automatically raised
whenever corresponding errors or warnings occur.
User Defined Exceptions
User defined exceptions, in contrast, must be raised explicitly
in a sequence of statements using raise <exception name>.
After the keyword exception at the end of a block, user defined
exception handling routines are implemented.
An implementation has the pattern
when <exception name> then <sequence of statements>;
Exception Handlingdeclare pi constant NUMBER(9,7) := 3.1415927; radius INTEGER(5); area NUMBER(14,2); some_variable NUMBER(14,2);begin radius := 3; loop some_variable := 1/(radius-4); area := pi*power(radius,2); insert into AREAS values (radius,
area); radius := radius+1; exit when area >100; end loop; end;
User Defined Exceptions • Because the calculation for some_variable involves division, you may
encounter a situation in which the calculation attempts to divide by zero—an error condition
• The second time through the loop, the radius variable has a value of 4—and the calculation for some_variable encounters an error:
• ERROR at line 1:• ORA-01476: divisor is equal to zero• ORA-06512: at line 9
• Because an error was encountered, the first row inserted into AREAS is rolled back, and the PL/SQL block terminates.
• You can modify the processing of the error condition by adding an Exception Handling section to the PL/SQL block, as shown next
Exception Handlingdeclare pi constant NUMBER(9,7) := 3.1415927; radius INTEGER(5); area NUMBER(14,2); some_variable NUMBER(14,2);begin radius := 3; loop some_variable := 1/(radius-4); area := pi*power(radius,2); insert into AREAS values (radius, area); radius := radius+1; exit when area >100; end loop; exception when ZERO_DIVIDE
then insert into AREAS values (0,0); end;
Exception Handlingdeclare
emp_sal NUMBER(10,3);
Emp_no VARCHAR2(12);
too_high_sal exception;
begin
select EMPLOYEE_ID, SALARY into emp_no, emp_sal
from EMPLOYEE where EMPLOYEE_NAME = ’E_Y’;
if emp_sal * 1.05 > 2000 then raise too_high_sal;
end if;
exception
when NO_DATA_FOUND
then DBMS_OUTPUT.PUT_LINE(‘No data found’);
when too_high_sal then DBMS_OUTPUT.PUT_LINE(‘High Salary’);
end;
/
Exception Handling• When the PL/SQL block encounters an error, it scans the
Exception Handling section for the defined exceptions.
• After the keyword when a list of exception names, connected with or can be specified.
• In addition to the system-defined exceptions and user defined exceptions, you can use the when others clause to address all exceptions not defined within your Exception Handling section.
• This introduces the default exception handling routine, for example, a rollback.
Exception HandlingIt is also possible to use procedure raise_application_error.
This procedure has two parameters
<error number> and <message text>.
<error number> is a negative integer defined by the user and must range between -20000 and -20999.
<error message> is a string with a length up to 2048 characters.
If the procedure raise application error called from a PL/SQL block, processing the PL/SQL block terminates and all database modifications are undone, that is, an implicit rollback is performed in addition to displaying the error message.
Exception Handlingdeclare
emp_sal NUMBER(10,3);
Emp_no VARCHAR2(12);
begin
select EMPLOYEE_ID, SALARY into emp_no, emp_sal
from EMPLOYEE where EMPLOYEE_NAME = ’E_Y’;
if emp_sal * 1.05 > 2000
then raise_application_error(-20010, ’Salary is too high for ’ || to_char(Emp no) );
end if;
end;
/
Exception Handling• The concatenation operator “||” can be used to concatenate
single strings to one string. • In order to display numeric variables, these variables must
be converted to strings using the function to_char. • Once an exception is encountered, you cannot return to your
normal flow of command processing within the Executable Commands section.
• If you need to maintain control within the Executable Commands section, you should use if conditions to test for possible exceptions before they are encountered by the program, or create a nested block with its own local exception handling.
Compilation Errors
Loading a procedure or function may cause compilation errors.
SHOW ERRORS; gives the errors
To get rid of procedures or functions:
DROP PROCEDURE <name>;
DROP FUNCTION <name>;
Debugging PL/SQL
• The SQL*Plus show errors command displays all the errors associated with the most recently created procedural object.
• This command checks the USER_ERRORS data dictionary view for the errors associated with the most recent compilation attempt for that object.
• Show errors displays the line and column number for
each error, as well as the text of the error message. • To view errors associated with previously created
procedural objects, you may query USER_ERRORS directly
Debugging PL/SQL• If any errors were encountered during the creation of
the OVERDUE_CHARGES function , the lines in the code that resulted in the error conditions would be returned by the query.
select Line, /*Line number of the error. */Position, /*Column number of the error.*/Text /*Text of the error message.*/from USER_ERRORS where Name = 'OVERDUE_CHARGES' and Type = 'FUNCTION'order by Sequence;
• Valid values for the Type column are VIEW, PROCEDURE, PACKAGE, FUNCTION, and PACKAGE BODY
Debugging PL/SQL
• In addition to the debugging information provided by the show errors command, you may use the DBMS_OUTPUT package,
• It is automatically installed when you create an Oracle database
PUT Puts multiple outputs on the same linePUT_LINE Puts each output on a separate lineNEW_LINE Used with PUT; signals the end of the current output
line
• To track the variable’s value, you may use a command similar to the one shown
DBMS_OUTPUT.PUT_LINE ('Owed:'||Owed_Amount);
Viewing Source Code of Procedure
The source code for existing procedures, functions, packages, and package bodies can be queried from the following data dictionary views:
○ USER_SOURCE For procedural objects owned by the user○ ALL_SOURCE For procedural objects owned by the user or
to which the user has been granted access○ DBA_SOURCE For all procedural objects in the database
Select information from the USER_SOURCE view via a query
select Text
from USER_SOURCE
where Name = 'NEW_BOOK'
and Type = 'PROCEDURE'
order by Line;
Output of above query is:TEXT-----------------------------------------------------------------procedure NEW_BOOK (aTitle IN VARCHAR2, aPublisher IN VARCHAR2, aCategoryName IN VARCHAR2)asbegin insert into BOOKSHELF (Title, Publisher, CategoryName, Rating) values (aTitle, aPublisher, aCategoryName, NULL); delete from BOOK_ORDER where Title = aTitle;end;○ the USER_SOURCE view contains one record for each line of the
NEW_BOOK procedure so should be ordered by with Line.
Compiling PL/SQL• Oracle compiles procedural objects when they are created. • Procedural objects may become invalid if the database
objects they reference change. • The next time the procedural objects are executed, they
will be recompiled by the database. • You can avoid this run-time compiling—and the
performance degradation it may cause—by explicitly recompiling the procedures, functions, and packages.
• To recompile a procedure, use the alter procedure command, as shown in the following listing.
• The compile clause is the only valid option for this command.
• Alter function/procedure OVERDUE_CHARGES compile;
Packages It is essential for a good programming style that logically
related blocks, procedures, and functions are combined into modules
Each module then provides an interface which allows users and designers to utilize the implemented functionality.
PL/SQL supports the concept of modularization by which modules and other constructs can be organized into packages.
A package consists of a package specification and a package body.
The package specification defines the interface that is visible for application programmers, and the package body implements the package specification
Packages When creating packages, the package
specification and the package body are created separately.
Thus, there are two commands to use: create package for the package specification, and create package body for the package body.
Both of these commands require that you have the CREATE PROCEDURE system privilege.
If the package is to be created in a schema other than your own, then you must have the CREATE ANY PROCEDURE system privilege
Packages Here is the syntax for creating package specifications:
create [or replace] package [ user. ] package[authid {definer | current_user} ]{is | as} package specification ;
A package specification consists of the list of functions, procedures, variables, constants, cursors, and exceptions that will be available to users of the package.
A package body contains the blocks and specifications for all of the public objects listed in the package specification.
The package body may include objects that are not listed in the package specification; such objects are said to be private and are not available to users of the package.
Private objects may only be called by other objects within the same package body.
Packages A procedure or function implemented in a package can
be called from other procedures and functions using the statement <package name>.<procedure name>[(<list of parameters>)].
Additional functions, procedures, exceptions, variables, cursors, and constants may be defined within the package body,
but they will not be available to the public unless they have been declared within the package specification (via the create package command).
execute BOOK_INVENTORY.NEW_BOOK('ONCE REMOVED');
Packages If a user has been granted the EXECUTE
privilege on a package, then that user can access any of the public objects that are declared in the package specification.
Packages are groups of procedures, functions, variables, and SQL statements grouped together into a single unit.
To execute a procedure within a package, you must first list the package name, and then list the procedure name, as shown previously Execute BOOK_INVENTORY.NEW_BOOK('ONCE REMOVED');
Packages Packages allow multiple procedures to use the same
variables and cursors. Procedures within packages may be either available to
the public (as is the NEW_BOOK procedure in the prior example) or private, in which case they are only accessible via commands from within the package (such as calls from other procedures).
Packages may also include commands that are to be executed each time the package is called, regardless of the procedure or function called within the package.
Thus, packages not only group procedures but also give you the ability to execute commands that are not procedure specific.
Packages Oracle offers several predefined packages and
procedures that can be used by database users and application developers.
A set of very useful procedures is implemented in the package DBMS_OUTPUT.
Procedure DBMS_OUTPUT.ENABLE DBMS_OUTPUT.DISABLE DBMS_OUTPUT.PUT(<string>) DBMS_OUTPUT.PUT LINE(<string>) DBMS_OUTPUT.NEW
THANK YOU