7/27/2019 Adv Plsql1
1/140
Advanced Oracle PLSQL
programming
Advantech 1 Krishnamurthy
7/27/2019 Adv Plsql1
2/140
Anonymous Procedure Function
[DECLARE]
BEGIN
--statements
[EXCEPTION]
END;
PROCEDURE name
IS
BEGIN
--statements
[EXCEPTION]
END;
FUNCTION name
RETURN datatype
IS
BEGIN
--statementsRETURN value;
[EXCEPTION]
END;
PL/SQL Block Structure
Advantech 2 Krishnamurthy
7/27/2019 Adv Plsql1
3/140
Naming Conventions Advantages of proper naming
conventions: Easier to read
Understandable
Gives information about the functionality
Easier to debug
Ensures consistency
Advantech 3 Krishnamurthy
7/27/2019 Adv Plsql1
4/140
Do not use reserved keywords as identifiers:
To list reserved keywords use data dictionary view v$reserved_words
- select keyword from v$reserved_words;
Label blocks You can give a name to a block so that you canaccess corresponding blocks variables in sub-blocks
Loop Labels - You can give a name to a loop by using a label
FOR year_number IN 1800..1995
LOOPFOR month_number IN 1 .. 12LOOP
IF year_loop.year_number = 1900 THEN ... END IF;
END LOOP month_loop;END LOOP year_loop;
Advantech 4 Krishnamurthy
7/27/2019 Adv Plsql1
5/140
Procedures A procedure is:
A named PL/SQL block that performs a
sequence of actions and optionally returns avalue or values
Stored in the database as a schema object
Used to promote reusability andmaintainability
[CREATE [OR REPLACE]] PROCEDURE [schema.]name[(parameter[,parameter...] ) ]
[AUTHID DEFINER | CURRENT_USER] IS[declarations][PRAGMA AUTONOMOUS_TRANSACTION]BEGIN executable statements
[ EXCEPTION exception handlers]END [name];
Note : Importance of OR REPLACE to be explained
Advantech 5 Krishnamurthy
7/27/2019 Adv Plsql1
6/140
Procedural Parameter Modes
Callingenvironment
Procedure
procedure
BEGIN
EXCEPTION
END;
IN parameter
OUT parameter
IN OUT parameter
Advantech 6 Krishnamurthy
7/27/2019 Adv Plsql1
7/140
Any assignments made toparameters are rolledback when an exceptionis raised in the program*
Any assignments madeto parameters are rolledback when an exceptionis raised in the program*
In parametercannot bemodified in theprogram*
Actual parameter must bea variable
Actual parameter mustbe a variable
Actual parametercan be constant,expression,variable etc.,
Cannot have defaultvalue
Cannot have defaultvalue
Can have defaultvalue
Sub-program takes
in/gives out value
Sub-program gives out
value
Sub-program
takes value
Pass by valuePass by valuePass by reference
IN OUTOUTIN
Parameter modes
*example discussed in next slideAdvantech 7 Krishnamurthy
7/27/2019 Adv Plsql1
8/140
IN parameter-variable vsal number
-exec :vsal:=1000-create or replace procedure ex(psal IN number)isbegin
psal:=500; -- illegal
update . . .end;
/OUT / IN OUT parameter
-variable vsal number-create or replace procedure ex(psal OUT number)isbegin
psal:=500; -- rolled back
select sal into psal from emp where empno=9999; -- raises excep.end;
/-exec ex(:vsal)
-print vsal(null)Advantech 8 Krishnamurthy
7/27/2019 Adv Plsql1
9/140
The NOCOPY Parameter Mode Hint
NOCOPY is a hint to the compiler about how you would like the
PL/SQL engine to work with the data structure being passed in as anOUT or IN OUT parameter.
Parameter mode Passed by value or reference? (default)
IN By reference
OUT By value
IN OUT By value
We can infer from these definitions and rules that when a large datastructure (such as a collection, a record, or an instance of an objecttype) is passed as an OUT or IN OUT parameter, that structure will
be passed by value, and your application could experienceperformance and memory degradation as a result of all this copying.The NOCOPY hint is a way for you to attempt to avoid this.
The syntax of this feature is as follows:parameter_name OUT NOCOPY or IN OUT NOCOPY datatypeAdvantech 9 Krishnamurthy
7/27/2019 Adv Plsql1
10/140
Matching Actual and Formal Parameters in PL/SQL
PL/SQL offers two ways to make the association between actual and
formal parameters:
Positional notation - Associate the actual parameter implicitly (byposition) with the formal parameter.
Named notation - Associate the actual parameter explicitly (byname) with the formal parameter.
It is more efficient to use this named notation method since it is self-
explanatory (what data to which parameter etc.,)
You can also include only the parameters you want or need in theparameter list.
Advantech 10 Krishnamurthy
7/27/2019 Adv Plsql1
11/140
AUTHID [DEFINER] | CURRENT_USER
CREATE OR REPLACE PROCEDURE remove_emp(p_empno IN emp.empno%type,p_ename OUT emp.ename%type)
AUTHID CURRENT_USERIS
BEGINDELETE EMP WHERE EMPNO=p_empnoRETURNING ename INTO p_ename;IF SQL%FOUND THEN
dbms_output.put_line(sql%rowcount||' row deleted.');COMMIT;ELSE
dbms_output.put_line('0 rows deleted.');END IF;
END;
Advantech 11 Krishnamurthy
7/27/2019 Adv Plsql1
12/140
PRAGMA AUTONOMOUS_TRANSACTION
These are independent transactions which performs commit/rollbackonly local DML changes and not main transaction. These are startedand ended by named subprograms
CREATE OR REPLACE PROCEDURE ADD_PLAYER(name VARCHAR2)
ISPRAGMA AUTONOMOUS_TRANSACTION;
BEGININSERT INTO CRICKET VALUES(NAME);
COMMIT; -- tcl command mandatory else throws runtime errorsEND;/INSERT INTO CRICKET VALUES('DRAVID');
EXEC ADD_PLAYER('SEHWAG'); -- COMMITTED
ROLLBACK; -- rolls back inserting of DRAVID record but SEHWAG isadded and committed
Advantech 12 Krishnamurthy
7/27/2019 Adv Plsql1
13/140
Functions A function is:
A named block that must return a value
Stored in the database as a schema object Called as part of an expression or used to
provide a parameter value[CREATE [OR REPLACE]] FUNCTION [schema.]name[( parameter [, parameter ...] ) ]
RETURN return_datatype[AUTHID DEFINER | CURRENT_USER][DETERMINISTIC] [PARALLEL ENABLE ...] [PIPELINED][RESULT_CACHE [RELIES ON table_name]]
IS [declaration statements]BEGIN executable statements[EXCEPTION exception handler statements]END [ name ];
Advantech 13 Krishnamurthy
7/27/2019 Adv Plsql1
14/140
Function: ExampleCREATE OR REPLACE FUNCTION get_maxsal_limit(
p_empno IN emp.empno%type)RETURN numberis
v_hisal salgrade.hisal%type;BEGIN
SELECT hisal INTO v_hisalFROM salgrade s,emp eWHERE sal between losal and hisaland e.empno=p_empno;RETURN v_hisal;
EXCEPTIONWHEN others THEN
RETURN null;END;
/
exec dbms_output.put_line(get_maxsal_limit(7566));
Advantech 14 Krishnamurthy
7/27/2019 Adv Plsql1
15/140
Ways to Execute Functions
Invoke as part of a PL/SQL expression Using a host variable to obtain the result:
Using a local variable to obtain the result:
Use as a parameter to another subprogram
Use in a SQL statement (subject to restrictions)
EXECUTE dbms_output.put_line(get_maxsal_limit(7566))
select empno,ename,sal,get_maxsal_limit(empno) from emp;
VARIABLE v_hisal NUMBER
EXECUTE :v_hisal := get_maxsal_limit(7566)
DECLARE v_hisal salgrade.hisal%type;
BEGINv_hisal := get_maxsal_limit(7566); ...
END;
Advantech 15 Krishnamurthy
7/27/2019 Adv Plsql1
16/140
Restrictions on Calling Functions
from SQL Expressions
User-defined functions that are callable from
SQL expressions must: Be stored in the database Accept only I Nparameters with valid SQL data types,
not PL/SQL-specific types
Return valid SQL data types, not PL/SQL-specific
types
When calling functions in SQL statements:
Parameters must be specified with positional notation
You must own the function or have the EXECUTE
privilege
Advantech 16 Krishnamurthy
7/27/2019 Adv Plsql1
17/140
Restrictions on Calling Functions
from SQL Expressions
Functions called from: A SELECT statement cannot contain DML statements
An UPDATE orDELETE statement on a tableT cannot query orcontain DML on the same tableT
SQL statements cannot end transactions (that is, cannotexecute COMMI T orROLLBACKoperations)
Note: Calls to subprograms that break these restrictions
are also not allowed in the function.
Advantech 17 Krishnamurthy
7/27/2019 Adv Plsql1
18/140
You cannot have DML in a function which are invoked usingselect statement
create or replace function del_emp(e number)return numberis
n number;
begindelete emp where empno=e;n:=sql%rowcount;return n;
end;/
SQL> select del_emp(7566) from dual;select del_emp(7566) from dual
*ERROR at line 1:ORA-14551: cannot perform a DML operation inside a query
Advantech 18 Krishnamurthy
7/27/2019 Adv Plsql1
19/140
PL/SQL Packages: Review
PL/SQL packages:
Group logically related components:
PL/SQL types
Variables, data structures, and exceptions
Subprograms: procedures and functions
Consist of two parts:
A specification A body
Enable the Oracle server to read multiple objects
into memory simultaneously
Advantech 19 Krishnamurthy
7/27/2019 Adv Plsql1
20/140
Components of a PL/SQL Package
Packagespecification
Packagebody
Procedure A declaration;
variable
Procedure A definition
BEGINEND;
Procedure B definition
variable
variable
Public
Private
Advantech 20 Krishnamurthy
7/27/2019 Adv Plsql1
21/140
Creating the Package Specification
Syntax:
The OR REPLACE option drops and re-creates the packagespecification.
Variables declared in the package specification are initializedto NULL by default.
All constructs declared in a package specification are visibleto users who are granted privileges on the package.
CREATE [OR REPLACE] PACKAGEpackage_name IS|AS
public type and variable declarations
subprogram specifications
END [package_name];
Advantech 21 Krishnamurthy
7/27/2019 Adv Plsql1
22/140
Creating the Package Body
Syntax:
The OR REPLACE option drops and re-creates the packagebody.
Identifiers defined in the package body are private and not
visible outside the package body.
All private constructs must be declared before they arereferenced.
Public constructs are visible to the package body.
CREATE [OR REPLACE] PACKAGE BODYpackage_name IS|AS
private type and variable declarationssubprogram bodies
[BEGIN initialization statements]
END [package_name];
Advantech 22 Krishnamurthy
7/27/2019 Adv Plsql1
23/140
CURSORsWhenever you issue a SQL statement, the Oracleserver opens an area of memory in which thecommand is parsed and executed. This area iscalled a cursor.
Types of cursor's1.IMPLICIT cursor
-automatically defined by oracle-INSERT/UPDATE/DELETE-SELECT INTO statement which returns single row-Name: SQL
2.EXPLICIT cursor-user defined cursors-SELECT statement which returns zero or more rows
-Name: user-defined cursor nameAdvantech 23 Krishnamurthy
7/27/2019 Adv Plsql1
24/140
CURSORs
Advantech 24 Krishnamurthy
7/27/2019 Adv Plsql1
25/140
Controlling Explicit CursorsControlling Explicit Cursors
Create anamed
SQL area
DECLAREDECLARE
Identifythe active
set
OPENOPEN
Load thecurrent
row into
variables
FETCHFETCH
Releasethe active
set
CLOSECLOSEYes
Test forexisting
rows
EMPTY?EMPTY?
Return toFETCH if
rows are
found
No
Advantech 25 Krishnamurthy
7/27/2019 Adv Plsql1
26/140
Declaring a Cursor
When you declare a cursor, you name it and associate itwith a specific query. When you declare a cursor oraclenames an area of memory in server and associates selectstatement with the cursor location.
At this stage, the query is PARSED
Parsing means
- checks for syntax (formation of SQL statement)
- checks for semantics (whether cols,tables,privileges etcexists)
CURSOR cursor_name [(parameter[, parameter]...)][RETURN return_type] IS select_statement;Ex:
cursor emp_cur isselect ename,sal,hiredate,deptno from emp wheredeptno=20;
Advantech 26 Krishnamurthy
7/27/2019 Adv Plsql1
27/140
OPENing the Cursor
Opening the cursor executes the query and identifies theresult set, which consists of all rows that meet the querysearch 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); parameterized cursors
OPEN c1(emplname, esal);
Advantech 27 Krishnamurthy
7/27/2019 Adv Plsql1
28/140
Fetching with a Cursor
The FETCH statement retrieves the rows in the result setone at a time. Each fetch retrieves the current row andthen advances the cursor to the next row in the resultset.
FETCH cursor_name INTO var1,var2,.. or record_list;
Ex:
FETCH c1 INTO my_empno, my_ename, my_deptno;
LOOPFETCH c1 INTO my_record;
EXIT WHEN c1%NOTFOUND;-- process data recordEND LOOP;
Advantech 28 Krishnamurthy
7/27/2019 Adv Plsql1
29/140
Closing a Cursor
The CLOSE statement disables the cursor, and the resultset becomes undefined.
Once a cursor is closed, you can reopen it. Any otheroperation on a closed cursor raises the predefined
exception INVALID_CURSOR.
CLOSE cursor_name;
Ex:
CLOSE emp_cur;
Advantech 29 Krishnamurthy
7/27/2019 Adv Plsql1
30/140
-returns number of rows processed%ROWCOUNT
-returns TRUE if cursor is
open
-always returns FALSE
since cursor is implicitly
closed
%ISOPEN
-complements %found attribute%NOTFOUND
-returns TRUE ifLASTFETCH is successful
-returns TRUE iflaststatement is successful
%FOUND
EXPLICIT cursorIMPLICIT cursorATTRIBUTE
CURSOR attributes
- returns status of the cursor
Advantech 30 Krishnamurthy
7/27/2019 Adv Plsql1
31/140
The FOR UPDATE Clause
Syntax:
Use explicit locking to deny access for theduration of a transaction.
Lock the rows before the update or delete.
SELECT ...
FROM ...
FOR UPDATE [OF column_reference][NOWAIT];
Advantech 31 Krishnamurthy
7/27/2019 Adv Plsql1
32/140
The FOR UPDATE Clause
DECLARE
CURSOR empcursor ISSELECT * FROM EMP WHERE sal > 1000 for update;
rec empcursor%rowtype;newsal emp.sal%type;
BEGINOPEN empcursor;LOOP
FETCH empcursor INTO rec;EXIT WHEN empcursor%NOTFOUND;
IF rec.sal >= 3000 THENnewsal:=rec.sal*1.5;
ELSEnewsal:=rec.sal*1.2;
END IF;UPDATE EMP SET SAL=newsal WHERE EMPNO=rec.empno;END LOOP;CLOSE empcursor;COMMIT;
END;Advantech 32 Krishnamurthy
Th "WHERE CURRENT OF" l
7/27/2019 Adv Plsql1
33/140
The "WHERE CURRENT OF" clause
The update statement within the loop uses the primarykey of the table, and is therefore a reasonably efficientindex lookup.
However, since we just fetched the row in question, whyshould we need to perform an index lookup? Shouldn't wealready know where the row is?
In fact, the second index lookup is unnecessary. PL/SQL(and the programmatic interfaces) can refer to thecurrent row selected by the cursor using the clause
"WHERE CURRENT OF cursor_name". Using this notation,PL/SQL can use the row address (ROWID) stored in thecursor structure to locate the row without an indexlookup.
Advantech 33 Krishnamurthy
WHERE CURRENT OF contd
7/27/2019 Adv Plsql1
34/140
WHERE CURRENT OF cont dDECLARE
CURSOR empcursor IS
SELECT * FROM EMP WHERE sal > 1000 for update;rec empcursor%rowtype;newsal emp.sal%type;
BEGINOPEN empcursor;
LOOPFETCH empcursor INTO rec;EXIT WHEN empcursor%NOTFOUND;IF rec.sal >= 3000 THEN
newsal:=rec.sal*1.5;
ELSEnewsal:=rec.sal*1.2;
END IF;UPDATE EMP SET SAL=newsal WHERE CURRENT OF empcursor;
END LOOP;
CLOSE empcursor;COMMIT;
END;
The WHERE CURRENT OF clause eliminates the I/Os involved with anindex lookup and does improve the performance of the updatestatement.
Advantech 34 Krishnamurthy
CURSOR FOR loop:
7/27/2019 Adv Plsql1
35/140
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, FETCHedfrom and CLOSEed automatically when all of the rows have beprocessed.
Each iteration of the loop fetches a row from the active set into arecord, 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.
FOR record_name IN cursor_name LOOP
statement1;
statement2;
. . .
END LOOP;
Advantech 35 Krishnamurthy
7/27/2019 Adv Plsql1
36/140
Handling Exceptions
An exception is an error in PL/SQL that is
raised during program execution.
An exception can be raised:
Implicitly by the Oracle server
Explicitly by the program
An exception can be handled:
By trapping it with a handler
By propagating it to the calling environment By trapping and propagating it
Advantech 36 Krishnamurthy
Predefined Exception raised when
7/27/2019 Adv Plsql1
37/140
Predefined Exception raised when
Advantech 37 Krishnamurthy
7/27/2019 Adv Plsql1
38/140
Advantech 38 Krishnamurthy
7/27/2019 Adv Plsql1
39/140
Advantech 39 Krishnamurthy
7/27/2019 Adv Plsql1
40/140
Advantech 40 Krishnamurthy
7/27/2019 Adv Plsql1
41/140
Handling Exceptions
Exceptionraised
Is theexception
trapped?
yes
Execute statementsin the EXCEPTION
section.
Terminate
gracefully.
no
Terminate
abruptly.
Propagate the
exception.
Advantech 41 Krishnamurthy
Predefined Exception Handler
7/27/2019 Adv Plsql1
42/140
Predefined Exception Handler
Advantech 42 Krishnamurthy
7/27/2019 Adv Plsql1
43/140
Advantech 43 Krishnamurthy
7/27/2019 Adv Plsql1
44/140
Exceptions: Example
DECLAREv_ename emp.ename%type;
BEGINSELECT ename INTO v_ename FROM EMP
WHERE DEPTNO=&DEPTNO;dbms_output.put_line('Name is :'||v_ename);
EXCEPTIONWHEN no_data_found THENdbms_output.put_line('No employee in this dept');
WHEN too_many_rows THENdbms_output.put_line('Multiple rows fetched. Use cursors');
END;/
Advantech 44 Krishnamurthy
Built-in Error Functions
7/27/2019 Adv Plsql1
45/140
SQLCODE - returns the error code of the most recently raised
exception in your block. If there is no error, SQLCODE returns 0.SQLCODE also returns 0 when you call it outside of an exceptionhandler.
Oracle maintains a stack of SQLCODE values.
Suppose, for example, that function FUNC raises the VALUE_ERRORexception (-6502). Within the exception section of FUNC, you call aprocedure PROC that raises DUP_VAL_ON_INDEX (-1). Within theexception section of PROC, SQLCODE returns -1. When control
propagates back up to the exception section of FUNC, however,SQLCODE will still return -6502. Run the sqlcode_test.sql file(available on the book's web site) to see a demonstration of thisbehavior.
Advantech 45 Krishnamurthy
SQLERRMf h h f
7/27/2019 Adv Plsql1
46/140
SQLERRM is a function that returns the error message for aparticular error code. If you do not pass an error code to
SQLERRM, it returns the error message associated with the valuereturned by SQLCODE.
If SQLCODE is 0, SQLERRM returns this string:
ORA-0000: normal, successful completion
If SQLCODE is 1 (the generic user-defined exception error code),SQLERRM returns this string: User-defined exception
Here is an example of calling SQLERRM to return the error messagefor a particular code:
BEGINDBMS_OUTPUT.put_line (SQLERRM(-1403)); or 100
END;SQL> /ORA-01403: no data found
Advantech 46 Krishnamurthy
DBMS_UTILITY.FORMAT_ERROR_STACKThi b ilt i f ti lik SQLERRM t th
7/27/2019 Adv Plsql1
47/140
This built-in function, like SQLERRM, returns the messageassociated with the current error (i.e., the value returned by
SQLCODE).
It differs from SQLERRM in two ways:
- Its length is not restricted; it will return the full errormessagestring.
- You cannot pass an error code number to this function
Note that even though the name of the function includes theword "stack" it doesn't return a stack of errors leading back tothe line on which the error was originally raised.
Advantech 47 Krishnamurthy
DBMS_UTILITY.FORMAT_ERROR_BACKTRACEThi f ti t f tt d t i th t di l t k f
7/27/2019 Adv Plsql1
48/140
This function returns a formatted string that displays a stack ofprograms and line numbers leading back to the line on which the
error was originally raised.
DBMS_UTILITY.FORMAT_CALL_STACK - returns a formattedstring showing the execution call stack inside your PL/SQL
application.
Advantech 48 Krishnamurthy
ExampleCREATE OR REPLACE PROCEDURE proc1 IS
7/27/2019 Adv Plsql1
49/140
CREATE OR REPLACE PROCEDURE proc1 ISBEGIN
DBMS_OUTPUT.put_line('running proc1');RAISE NO_DATA_FOUND;
END;/CREATE OR REPLACE PROCEDURE proc2 IS
BEGINDBMS_OUTPUT.put_line('calling proc1');proc1;
END;/
CREATE OR REPLACE PROCEDURE proc3 ISBEGIN
DBMS_OUTPUT.put_line('calling proc2');proc2;
EXCEPTION
WHEN OTHERS THENDBMS_OUTPUT.put_line('Error stack at top level:');DBMS_OUTPUT.put_line(DBMS_UTILITY.format_error_backtrace);
END;/
Advantech 49 Krishnamurthy
SQL> exec proc3;calling proc2
7/27/2019 Adv Plsql1
50/140
calling proc2calling proc1
running proc1Error stack at top level:ORA-06512: at "SCOTT.PROC1", line 4ORA-06512: at "SCOTT.PROC2", line 4
ORA-06512: at "SCOTT.PROC3", line 4
Advantech 50 Krishnamurthy
Example
7/27/2019 Adv Plsql1
51/140
begin
dbms_output.put_line('Outer Executable section');begin
dbms_output.put_line('Inner Executable section');raise too_many_rows;
exceptionwhen others thendbms_output.put_line('Inner Exception');dbms_output.put_line('Code:'||sqlcode||' Message:'||sqlerrm);dbms_output.put_line('Error:'||dbms_utility.format_error_stack);dbms_output.put_line('Backtrace:'||dbms_utility.format_error_backtrace);raise no_data_found;
end;exception
when others thendbms_output.put_line('Outer Exception');dbms_output.put_line('Code:'||sqlcode||' Message:'||sqlerrm);dbms_output.put_line('Error:'||dbms_utility.format_error_stack);
dbms_output.put_line('Backtrace:'||dbms_utility.format_error_backtrace);end;
Advantech 51 Krishnamurthy
Output:Outer Executable section
7/27/2019 Adv Plsql1
52/140
Outer Executable sectionInner Executable section
Inner ExceptionCode:-1422 Message:ORA-01422: exact fetch returns more than requestednumber of rowsError:ORA-01422: exact fetch returns more than requested number of rowsBacktrace:ORA-06512: at line 5 -- displays line no
Outer ExceptionCode:100 Message:ORA-01403: no data foundORA-01422: exact fetch returns more than requested number of rowsError:ORA-01403: no data found
ORA-01422: exact fetch returns more than requested number of rowsBacktrace:ORA-06512: at line 12 -- displays line no
Advantech 52 Krishnamurthy
7/27/2019 Adv Plsql1
53/140
Trapping User-Defined Exceptions
Declarativesection
Executablesection
Exception-handlingsection
Declare Raise Reference
Name the
exception
Explicit ly raise
the exception by
using the RAISEstatement
Handle the raised
exception
Note : Example to be discussed
Advantech 53 Krishnamurthy
DECLARE--declaring user defined exception name
7/27/2019 Adv Plsql1
54/140
g psalary_missing exception;
v_ename emp.ename%type;v_sal emp.sal%type;BEGIN
SELECT ename,sal INTO v_ename,v_sal FROM EMP WHEREEMPNO=&EMPNO;
IF v_sal IS NULL THEN--raising user defined exception explicitlyRAISE salary_missing;
ELSEdbms_output.put_line(v_ename||' earns salary of '||v_sal);
END IF;dbms_output.put_line('Rest of the executable code ......');
EXCEPTIONWHEN no_data_found THEN
dbms_output.put_line('No employee with this id.');
WHEN salary_missing THEN-- handling user exceptiondbms_output.put_line('Salary of '||v_ename||' is NULL !!!');
WHEN others THENdbms_output.put_line('Exception:'||SQLERRM);
END;Advantech 54 Krishnamurthy
Trapping Non-Predefined Oracle
7/27/2019 Adv Plsql1
55/140
Trapping Non Predefined Oracle
Server Errors
Declarative section
Declare
Name the
exceptionCode PRAGMA
EXCEPTION_INIT
EXCEPTION section
Handle the raised
exception
Associate Reference
Advantech 55 Krishnamurthy
PRAGMA EXCEPTION_INIT
7/27/2019 Adv Plsql1
56/140
DECLARE
child_rows_found exception;PRAGMA EXCEPTION_INIT(child_rows_found,-2292);
BEGINDELETE DEPT WHERE DEPTNO=10;
EXCEPTIONWHEN child_rows_found THENdbms_output.put_line('Cannot delete parent record.');
WHEN others THENdbms_output.put_line('Exception:'||SQLERRM);
END;
Advantech 56 Krishnamurthy
ExampleCREATE OR REPLACE PROCEDURE add_emp(
7/27/2019 Adv Plsql1
57/140
p_empno IN emp.empno%type,
p_deptno IN emp.deptno%type)ISBEGIN
INSERT INTO emp(empno,deptno)VALUES(p_empno,p_deptno);EXCEPTION
WHEN OTHERS THENDECLAREv_errcode PLS_inTEGER := SQLCODE;
BEGINIF v_errcode = -1 THEN
DBMS_OUTPUT.put_line('Employee already exists');RAISE;
ELSIF v_errcode = -2291 THENDBMS_OUTPUT.put_line('Invalid deptno');RAISE;
ELSERAISE;
END IF;END;
END add_emp;
Advantech 57 Krishnamurthy
The RAISE APPLICATION ERROR
7/27/2019 Adv Plsql1
58/140
The RAISE_APPLICATION_ERROR
Procedure
Syntax:
You can use this procedure to issue user-defined error
messages from stored subprograms.
You can report errors to your application and avoid
returning unhandled exceptions.
Arguments
- error_numbermust be in the range -2000 to -20999
- error_message must be text message of 2kb max
raise_application_error (error_number,
message[, {TRUE | FALSE}]);
Advantech 58 Krishnamurthy
Th
7/27/2019 Adv Plsql1
59/140
The RAISE_APPLICATION_ERROR
Procedure
Is used in two places:
Executable section
Exception section
Returns error conditions to the user in a
manner consistent with other Oracle server
errors
Advantech 59 Krishnamurthy
7/27/2019 Adv Plsql1
60/140
Dependencies
7/27/2019 Adv Plsql1
61/140
Dependencies
Table
View
Database trigger
Procedure
Function
Package body
Package specification
User-defined object
and collection types
Function
Package specification
Procedure
Sequence
Synonym
Table
View
User-defined object
and collection types
Referenced objectsDependent objects
Advantech 61 Krishnamurthy
Dependencies
7/27/2019 Adv Plsql1
62/140
Dependencies
View orprocedure
Direct
dependency
Referenced
Indirectdependency
Direct
dependency
Dependent
Table
Referenced
xxxxxxxxxxxxxxvvvvvvvvvvvvvv
xxxxxxxxxxxxxx
vvvvvvvvvvvvvv
xxxxxxxxxxxxxx
vvvvvvvvvvvvvv
xxxxxxxxxxxxxx
vvvvvvvvvvvvvv
xxxxxxxxxxxxxx
vvvvvvvvvvvvvv
Procedure
Dependent
Advantech 62 Krishnamurthy
Dependency Management
- Another important phase of PL/SQL compilation and execution is
7/27/2019 Adv Plsql1
63/140
- Another important phase of PL/SQL compilation and execution is
the checking of program dependencies.- A dependency (in PL/SQL) is a reference from a stored program tosome Oracle object outside the program.
- Server-based PL/SQL programs can have dependencies on tables,
views, types, procedures, functions, sequences, synonyms, orpackage specifications, but not on package bodies or type bodies.
Oracle's basic dependency objective for PL/SQL is
Do not allow a program to run if any of the objects on which itdepends have changed since it was compiled.
Note: most of dependency management happens automatically,from the tracking of dependencies to the recompilation required tokeep everything synchronized.
Advantech 63 Krishnamurthy
Dependencies in PL/SQL
A simple illustration:
7/27/2019 Adv Plsql1
64/140
A simple illustration:
I have a package epkg which contains procedures, functions, recordtypes, collections etc related to emp table. Description is as shown
Advantech 64 Krishnamurthy
To view data dictionary information regarding the same I would useuser_objects and user_dependencies
7/27/2019 Adv Plsql1
65/140
Oracle has used its DIANA to determine a list of other objects that
EPKG needs in order to compile successfully.
Advantech 65 Krishnamurthy
Dependency graph of EPKG package
7/27/2019 Adv Plsql1
66/140
standardPACKAGE
dbms_standardPACKAGE
dbms_outputPACKAGE
epkg BODY epkg SPEC
emp TABLE
Advantech 66 Krishnamurthy
Let us find out which objects depends on EMP table and when wemodify structure of EMP table you can observe the dependent objectsstatus
7/27/2019 Adv Plsql1
67/140
status
Advantech 67 Krishnamurthy
You can use deptree procedure to view the dependency tree.
Run following script in SYS schema
7/27/2019 Adv Plsql1
68/140
C:\app\Administrator\product\11.1.0\db_1\RDBMS\ADMIN\utldtree.sql
SQL> EXEC DEPTREE_FILL('TABLE', 'SCOTT', 'EMP');
SQL> SELECT * FROM IDEPTREE;
DEPENDENCIES-----------------------------------------------------------------------
PACKAGE SCOTT.EPKGCURSOR ."LOCK TABLE "EMP" IN ROW EXCLUSIVE MODE NOWAIT "
PACKAGE BODY SCOTT.EPKGPROCEDURE SCOTT.RAISE_SALARYPACKAGE BODY SCOTT.EPKG
TABLE SCOTT.EMP
Note : Using packages in your design can break the cycle of
dependencies and recompilations.
Advantech 68 Krishnamurthy
Healing InvalidsIn any event, no PL/SQL program marked as invalid will run until asuccessful recompilation restores its validity There are at least three
7/27/2019 Adv Plsql1
69/140
successful recompilation restores its validity. There are at least three
ways that can happen:
By hand - Using an explicit ALTER command to recompile thepackage
By script - Using a program that looks for invalid packages andissues the ALTER commands for you
Automatically - Relying on Oracle's built-in recompilation rules
Advantech 69 Krishnamurthy
Recompiling by handThe "by hand" method is simple, but it can be tedious.
7/27/2019 Adv Plsql1
70/140
ALTER PACKAGE epkg COMPILE BODY;ALTER PROCEDURE raise_salary COMPILE;
Recompiling by scriptVarious scripts exist that can help you reduce the tedium of theserecompilations. Note that these must be run while logged in to thedatabase as SYSDBA.
utlip.sql - Invalidates and recompiles all PL/SQL code and views
in the entire database.
utlrp.sql - Recompiles all of the invalid objects in serial and isappropriate for single-processor hardware.
utlrcmp.sql - Like utlrp.sql, recompiles all invalid objects, but inparallel
Advantech 70 Krishnamurthy
Automatic recompilation
Automatic recompilation, is simpler, but it isn't without drawbacks.
7/27/2019 Adv Plsql1
71/140
If you merely execute one of the programs implemented in the EPKGpackage body, Oracle will recompile it just prior to execution.
Production environments are likely to have strict policies on whenyou can and cannot recompile programs. That's because installing a
new version of a PL/SQL program can force a lot of recompilation andcan have disastrous side effects on programs currently running.
You will probably want to run a script similar to utlrp.sqlto find andrecompile all invalid objects. Your DBA should help you schedule an
upgrade procedure, which should include running a recompilationscript.
Aside from a potentially unscheduled drain on performance, thebiggest drawback to Oracle's automatic recompilation feature is that
it can interfere with packages that are currently running.
This happens because automatically recompiling a package that iscurrently running invalidates the package.
Advantech 71 Krishnamurthy
Automatic recompilation ..
Not only that, Oracle shares the program's bytecode among differentsessions so this in alidation affects not j st the session that
7/27/2019 Adv Plsql1
72/140
sessions, so this invalidation affects not just the session thattriggered the recompilation, but every Oracle session that hasinstantiated the package! Consequences of this devastation includethe following:
- Executions terminate with an ORA-04068 error
- All public and private package variables assume their defaultvalues; if you haven't supplied an explicit default value, it will revertto NULL. This effect applies to any package that the session hasinstantiated, not just the one that's getting recompiled. So, if youwere in the middle of any computations that assign values topackage variables, you will lose the contents of those variables.
- DBMS_OUTPUT stops working. Well, not really, but if you hadpreviously enabled it, Oracle will disable it. This occurs because itson/off switch is really a package variable, and resetting the packagestate causes this variable to revert to its default, which is off.
Advantech 72 Krishnamurthy
Remote Dependencies
Server-based PL/SQL immediately becomes invalid whenever there'sa change in a local object on which it depends However if it depends
7/27/2019 Adv Plsql1
73/140
a change in a local object on which it depends. However, if it dependson an object on a different computer and that object changes, Oracledoes not attempt to invalidate the calling PL/SQL program in realtime. Instead, Oracle defers the checking until runtime.
Here is a program that has a remote dependency on the procedurerecompute_prices which lives across the database linkfindat.ldn.world:
PROCEDURE synch_em_up (tax_site_in IN VARCHAR2,since_in IN DATE)
ISBEGIN
IF tax_site_in = 'LONDON' [email protected](cutoff_time => since_in);
END IF;.
Advantech 73 Krishnamurthy
If you recompile the remote procedure and some time later try to runsynch_em_up, you are likely to get an ORA-04062 error withaccompanying text such as timestamp (or signature) of package
7/27/2019 Adv Plsql1
74/140
"SCOTT.recompute_prices" has been changed.
If your call is still legal, Oracle will recompile synch_em_up, and if itsucceeds, its next invocation should run without error.
To understand Oracle's remote procedure call behavior, you need toknow that the PL/SQL compiler always stores two kinds ofinformation about each referenced remote procedure: its timestampand its signature:
timestamp - The most recent date and time (down to the second)when an object's specification was reconstructed, as given by theTIMESTAMP (date datatype) column in the USER_OBJECTS view.
For PL/SQL programs, this is not necessarily the same as the mostrecent compilation time because it's possible to recompile an objectwithout reconstructing its specification.
Advantech 74 Krishnamurthy
SignatureA footprint of the actual shape of the object's specification.
7/27/2019 Adv Plsql1
75/140
Signature information includes the object's name and theordering, datatype family, and mode of each parameter.
So when I compiled synch_em_up, Oracle retrieved both thetimestamp and the signature of the remote procedure called
recomputed_prices, and stored a representation of them with thebytecode of synch_em_up.
How do you suppose Oracle uses this information at runtime?
The model is simple: it uses either the timestamp or the signature,depending on the current value of the parameterREMOTE_DEPENDENCIES_MODE.
If that timestamp or signature information, which is stored in thelocal program's bytecode, doesn't match the actual value of theremote procedure at runtime, you get the ORA-04062 error.
Advantech 75 Krishnamurthy
Oracle's default remote dependency mode is the timestamp method,but this setting can sometimes cause unnecessary recompilations.
7/27/2019 Adv Plsql1
76/140
The DBA can change the system-wide setting via the databaseinitialization file or an ALTER SYSTEM command; an applicationdeveloper can set it for the current session using the followingcommand:
ALTER SESSION SET REMOTE_DEPENDENCIES_MODE = SIGNATURE;
Advantech 76 Krishnamurthy
Using Oracle-Supplied Packages
7/27/2019 Adv Plsql1
77/140
Oracle-supplied packages: Are provided with the Oracle server
Extend the functionality of the database
Enable access to certain SQL features that are normallyrestricted for PL/SQL
For example, the DBMS_OUTPUT package wasoriginally designed to debug PL/SQL programs.
Advantech 77 Krishnamurthy
Some of the Oracle-Supplied Packages
7/27/2019 Adv Plsql1
78/140
pp g
Here is an abbreviated list of some Oracle-
supplied packages:
DBMS_ALERT DBMS_LOCK
DBMS_SESSI ON
DBMS_OUTPUT HTP
UTL_FI LE
UTL_MAI L DBMS_SCHEDULER
Advantech 78 Krishnamurthy
DBMS_OUTPUT Package
7/27/2019 Adv Plsql1
79/140
The DBMS_OUTPUT package enables you to send
messages from stored subprograms and triggers.
PUT and PUT_LI NE place text in the buffer. GET_LI NE and GET_LI NES read the buffer.
Use SET SERVEROUTPUT ON to display messages inSQL*Plus. (The default is OFF.)
PUT_LINE
GET_LINE
PUTNEW_LINE
GET_LINES
SET SERVEROUT ON [SIZE n]
EXEC procBuffer
Output
Advantech 79 Krishnamurthy
UTL_FILE Package
7/27/2019 Adv Plsql1
80/140
The UTL_FI LE package extends PL/SQL programs to
read and write operating system text files.
It provides a restricted version of operating system stream fileI/O for text files.
It can access files in operating system directories defined by aCREATE DI RECTORY statement.
EXEC proc
O/S fileUTL_FILE
CREATE DIRECTORY
my_dir AS '/dir'
Advantech 80 Krishnamurthy
UTL_FILE package
7/27/2019 Adv Plsql1
81/140
DBA configuration
connect system/ as sysdba
CREATE OR REPLACE DIRECTORY FILE_DIR AS 'C:\TEMP_FILES';
GRANT READ,WRITE ON DIRECTORY FILE_DIR TO PUBLIC;
CONNECT scott/tiger
Advantech 81 Krishnamurthy
writing emp table data into filecreate or replace procedure write_emp(
path in varchar2,
7/27/2019 Adv Plsql1
82/140
filename in varchar2)is
output_file utl_file.file_type;cursor empcursor IS
SELECT empno,ename,sal FROM EMP;
beginoutput_file := utl_file.fopen (PATH,FILENAME, 'w');for erec in empcursor looputl_file.put_line(output_file,
erec.empno||','||erec.ename||','||erec.sal);end loop;utl_file.fclose(output_file);
exceptionwhen others thendbms_output.put_line(SQLERRM);
end;
exec write_emp('FILE_DIR','empdata.txt');
Advantech 82 Krishnamurthy
Reading contents of a filecreate or replace procedure read_file(
path in varchar2,filename in varchar2)
7/27/2019 Adv Plsql1
83/140
)is
input_file utl_file.file_type;input_buffer varchar2(4000);
begininput_file := utl_file.fopen (path,filename,'R');dbms_output.put_line('Output:');loop
utl_file.get_line (input_file, input_buffer);dbms_output.put_line(input_buffer);
end loop;utl_file.fclose(input_file);
exceptionwhen no_data_found then
null;when others then
dbms_output.put_line(SQLERRM);end;
/exec read_file('FILE_DIR','empdata.txt');
Advantech 83 Krishnamurthy
Advanced Cursor Concepts
Cursor Variables and REF CURSORs
7/27/2019 Adv Plsql1
84/140
A cursor variable is a variable that points to orreferences an underlying cursor.
Unlike an explicit cursor, which names the PL/SQL work
area for the result set, a cursor variable is a reference tothat work area.
Explicit and implicit cursors are staticin that they are
tied to specific queries.
The cursor variable can be opened for any query, evenfor different queries within a single program execution.
Advantech 84 Krishnamurthy
The most important benefit of the cursor variable is that it provides amechanism for passing results of queries (the rows returned by fetchesagainst a cursor) between different PL/SQL programs even between
7/27/2019 Adv Plsql1
85/140
client and server PL/SQL programs.
Advantech 85 Krishnamurthy
It is important to distinguish between declaring a cursor variable andcreating an actual cursor object the result set identified by the cursorSQL statement.
7/27/2019 Adv Plsql1
86/140
A constant is nothing more than a value, whereas a variable points to itsvalue. Similarly, a static cursor acts as a constant, whereas a cursorvariable references or points to a cursor object.
These distinctions are shown in figure. Notice that two different cursorvariables in different programs are both referring to the same cursorobject.
Advantech 86 Krishnamurthy
Cursor Variables REF CURSORCursor variables are like C pointers, which hold thememory location (address) of some item instead of the
lf
7/27/2019 Adv Plsql1
87/140
item itself.
A REF CURSOR is basically a data type.
A variable created based on such a data type is generallycalled a cursor variable.
A cursor variable can be associated with different queriesat run-time.
The primary advantage of using cursor variables is their
capability to pass result sets between sub programs (likestored procedures, functions, packages etc.).
Advantech 87 Krishnamurthy
Defining REF CURSOR Types
To create cursor variables, you take two steps.
Fi t d fi REF CURSOR t th d l
7/27/2019 Adv Plsql1
88/140
First, you define a REF CURSOR type, then declare cursorvariables of that type.
You can define REF CURSOR types in any PL/SQL block,
subprogram, or package
TYPE ref_type_name IS REF CURSOR [RETURNreturn_type];
where r e f _ t y p e _ n a m e is a type specifier used insubsequent declarations of cursor variables and
r e t u r n _ t y p e must represent a record or a row in a
database table.
Then declare variable ofref_type_name
Advantech 88 Krishnamurthy
SYS_REFCURSOR weak reference type
Oracle has pre-defined ref cursor type in standard package usingwhich you can declare a variable.
7/27/2019 Adv Plsql1
89/140
create or replace procedure emp_refcur(cur_var out sys_refcursor)isbegin
open cur_var for select * from emp;end;/SQL> variable e_curvar refcursor
SQL> exec emp_refcur(:e_curvar)
SQL> print e_curvar
Advantech 89 Krishnamurthy
Dynamic Queries With REF CURSOR's
Oracle supports dynamic queries via the OPEN FOR USINGstatement.
7/27/2019 Adv Plsql1
90/140
A string literal or string variable is supplied in the OPEN FOR USINGstatement to the SELECT command.
OPEN name FOR dynamic_string[ USING bind_arg [, bind_arg_2 ]...];
name is the identifier of a previously declared cursor variable.dynamic_string is a string literal or string variable containing aSELECT command.
bind_arg, bind_arg_2... are bind arguments that are used to passvariables to corresponding placeholders in the SELECT command
when the cursor variable is opened.
The placeholders are identifiers prefixed by a colon character.
Advantech 90 Krishnamurthy
Example
CREATE OR REPLACE PROCEDURE dept_query (p_deptno emp.deptno%TYPE, p_sal emp.sal%TYPE)
IS
7/27/2019 Adv Plsql1
91/140
IS emp_refcur SYS_REFCURSOR;v_empno emp.empno%TYPE;v_ename emp.ename%TYPE;p_query_string VARCHAR2(100);
BEGINp_query_string := 'SELECT empno, ename FROM emp WHERE ' ||
'deptno = :dno AND sal >= :esal';OPEN emp_refcur FOR p_query_string USING p_deptno, p_sal;
DBMS_OUTPUT.PUT_LINE('EMPNO ENAME');DBMS_OUTPUT.PUT_LINE('----- -------');LOOP
FETCH emp_refcur INTO v_empno, v_ename;EXIT WHEN emp_refcur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_empno || ' ' || v_ename);END LOOP;CLOSE emp_refcur;
END;
Advantech 91 Krishnamurthy
COLLECTION
A ll ti i d d f l t ll f th
7/27/2019 Adv Plsql1
92/140
A collection is an ordered group of elements, all of thesame type.
Each element has a unique subscript that determinesits position in the collection
Advantech 92 Krishnamurthy
Types of Collections
Associative Arrays : to hold arbitrary no of elements.I d i i b l i t bi i t h 2 iti
7/27/2019 Adv Plsql1
93/140
Indexing is by pls_integer, binary_integer, varchar2, positiveand natural
Nested tables hold an arbitrary number of elements. They usesequential numbers as subscripts.
Varrays (variable-size arrays) hold a fixed number ofelements (although you can change the number of elements atruntime). They use sequential numbers as subscripts.
Note:A nested table & varrays are of object type and therefore
needs to first be initialized with a constructor before being used.
Advantech 93 Krishnamurthy
7/27/2019 Adv Plsql1
94/140
Advantech 94 Krishnamurthy
Associative Arrays
Objects of the TABLE type are called INDEX BY tables.
They are modeled as database tables (but not the)
7/27/2019 Adv Plsql1
95/140
They are modeled as database tables (but not thesame as).
Associative arrays use a primary key to provide youwith array-like access to rows.
An Associative Array:
Is similar to an array in other languages
Must contain two components:
A primary key is data that indexes the INDEX BYtable
A column of a scalar or record data type, which
stores the INDEX BY table elements
Can increase dynamically because it isunconstrained
Advantech 95 Krishnamurthy
Creating an I NDEX BY Table
7/27/2019 Adv Plsql1
96/140
Syntax:TYPE type_name IS TABLE OF
{column_type | variable%TYPE
| table.column%TYPE} [NOT NULL]
| table.%ROWTYPE
[INDEX BY datatype];
identifier type_name;
...
TYPE ename_table_type IS TABLE OF emp.ename%TYPE
INDEX BY BINARY_INTEGER;ename_table ename_table_type;
...
Example:Declare an INDEX BY table to store names.
Advantech 96 Krishnamurthy
I NDEX BY Table Structure
7/27/2019 Adv Plsql1
97/140
Unique identifier Column
... ...1 JONES
2 SMITH
3 KING
... ...
BI NARY_I NTEGER Scalar
Advantech 97 Krishnamurthy
Example :
DECLARETYPE IntDataTyp IS TABLE OF integer
7/27/2019 Adv Plsql1
98/140
TYPE IntDataTyp IS TABLE OF integerINDEX BY BINARY_INTEGER;inttab IntDataTyp;
BEGINinttab(1):=10;inttab(12):=20;
inttab(25):=30;dbms_output.put_line(inttab(1)||','||inttab(12)||','||inttab(25));
END;
Advantech 98 Krishnamurthy
Note : No DML (except delete) or transactions can beimplemented on various collections
Built-in Functions and Procedures for collections
7/27/2019 Adv Plsql1
99/140
Built in Functions and Procedures for collections
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 wouldraise 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 isdefined.
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.Advantech 99 Krishnamurthy
EXTEND Extends the number of elements in collection.EXTEND;a collection. Cannot be used on (extends collection by asingle element) associative arrays or other collections
that have not been initialized.
7/27/2019 Adv Plsql1
100/140
that have not been initialized.collection.EXTEND(n);.(extends collection by nelements)collection.EXTEND(n,I); (extends collection by nelements by copying value in element indexed byI)
TRIM Removes elements from the endcollection.TRIM;.of a collection. removes a single element from end of
collectioncollection.TRIM(n);. removes n elements from end ofcollection
Advantech 100 Krishnamurthy
Deleting rows in collections
To delete specific row d l t ()
7/27/2019 Adv Plsql1
101/140
To delete specific row.delete()
To delete all the rows
.delete
To delete range of rows
.DELETE (start_index_in IN INTEGER,end_index_in IN INTEGER);
Advantech 101 Krishnamurthy
I NDEX BY Table of Records
7/27/2019 Adv Plsql1
102/140
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 fielddept_table(index).field_name must be used
Define a TABLE variable with a permitted PL/SQL data type.
Declare a PL/SQL variable to hold department information.
Example:Example:
Advantech 102 Krishnamurthy
Example using CURSOR FOR LOOP
SET SERVEROUTPUT ON
7/27/2019 Adv Plsql1
103/140
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;
Advantech 103 Krishnamurthy
Nested Tables
nested tables can be considered one-column database tables.
oracle stores the rows of a nested table in no particular order
7/27/2019 Adv Plsql1
104/140
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. Thatgives you array-like access to individual rows.
Advantech 104 Krishnamurthy
NESTED ARRAY vs ARRAY
7/27/2019 Adv Plsql1
105/140
Arrays are dense and have a fixed upper bound, but nestedtables 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-inprocedure DELETE. That might leave gaps in the index, butthe built-in function NEXT lets you iterate over any series of
subscri ts.Advantech 105 Krishnamurthy
Understanding Varrays
Items of type VARRAY are calledvarrays.
They allow you to associate a single identifier with an entire
7/27/2019 Adv Plsql1
106/140
They allow you to associate a single identifier with an entirecollection. This association lets you manipulate the collectionas a whole and reference individual elements easily.
To reference an element, you use standard subscripting syntax
A varray has a maximum size
Advantech 106 Krishnamurthy
Defining Collection Types
You can define TABLE and VARRAY types in the
declarative part of any PL/SQL block, subprogram, or
7/27/2019 Adv Plsql1
107/140
p y p gpackage.
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 andelement_type are the same as for nested tablessize_limit is a positive integer
Advantech 107 Krishnamurthy
Example:DECLARE
TYPE NumList IS TABLE OF VARCHAR2(12);
nums NumList := NumList(10,20,30);BEGIN
7/27/2019 Adv Plsql1
108/140
BEGINfor 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 loopDBMS_OUTPUT.PUT_LINE(nums(i));end loop;
END;
Advantech 108 Krishnamurthy
DECLARETYPE dname_nt_type IS TABLE OF dept.dname%type;dnames dname_nt_type:=dname_nt_type();
BEGINFOR rec IN (SELECT dname from dept) LOOP
7/27/2019 Adv Plsql1
109/140
FOR rec IN (SELECT dname from dept) LOOPdnames.EXTEND;dnames(dnames.LAST):=rec.dname;
END LOOP;FOR j IN dnames.FIRST..dnames.LAST LOOP
dbms_output.put_line(j||'-'||dnames(j));
END LOOP;END;/
Advantech 109 Krishnamurthy
Comparing Associative array, nested table & varray
7/27/2019 Adv Plsql1
110/140
Needs
initialization(except in bulk
collect)
Does not need
initialization
initialization
Bound by size
Can hold
arbitrary no of
elements
No of
elements
Alwaysstarts from
1
Can start
from any
indexnumber
Start
index
Cannot
contain gaps
Initially dense,
after deletion
becomes
sparse
Can contain
gaps
gaps
Cannot
create
schema leveltypes
INDEX BY
clause is
used
Associative
Array
Varray
Schema
level typescan be
created
No indexby clause
Nested
Tables
Schema
types
indexcollection
Advantech 110 Krishnamurthy
Performance GainsPerformance Gains
BULK COLLECT INTO clause (ie.,BULK FETCH INTO)
7/27/2019 Adv Plsql1
111/140
SQL
DATA
Context Switching
Performance Gains
with Bulk Bindingwith Bulk Binding
PL/SQL Engine SQL Engine
SQL Statement
ExecutorProcedural statement
Executor
Advantech 111 Krishnamurthy
The Oracle server has three execution engines: one eachfor PL/SQL, SQL, and Java.
- When running PL/SQL blocks and subprograms, thePL/SQL engine runs procedural statements but sends the
7/27/2019 Adv Plsql1
112/140
PL/SQL engine runs procedural statements but sends theSQL statements to the SQL engine, which parses andexecutes the SQL statement and, in some cases, returnsdata to the PL/SQL engine. During execution, every SQLstatement causes a context switch between the twoengines, which results in a performance penalty.
- Performance can be improved substantially byminimizing the number of context switches required torun a particular block or subprogram. When a SQL
statement runs inside a loop that uses collection elementsas bind variables, the large number of context switchesrequired by the block can cause poor performance.
Advantech 112 Krishnamurthy
7/27/2019 Adv Plsql1
113/140
Using FETCH cur_name BULK COLLECT INTOcollectionThis statement avoid context switching between PL/SQL
engine and SQL engine for fetching rows into colleciton
7/27/2019 Adv Plsql1
114/140
DECLARECURSOR empcursor is select * from emp;TYPE erectabtype IS TABLE OF emp%rowtype;etab erectabtype;
BEGIN
OPEN empcursor;FETCH empcursor BULK COLLECT INTO etab;CLOSE empcursor;FOR idx IN etab.first..etab.last LOOP
dbms_output.put_line(idx||','||etab(idx).ename);END LOOP;
END;
Advantech 114 Krishnamurthy
Using SELECT col_list BULK COLLECT INTOcollection
DECLAREdeptno tab dbms sql.number table; -- inbuilt type
7/27/2019 Adv Plsql1
115/140
p _ _ q _ ; ypename_tab dbms_sql.varchar2_table;
BEGIN
SELECT ename,deptno BULK COLLECT INTO ename_tab,deptno_tabFROM EMP WHERE SAL > 2000;FOR i IN 1..ename_tab.COUNT LOOP --or sql%rowcountdbms_output.put_line(ename_tab(i)||','||deptno_tab(i));
END LOOP;
END;/
Advantech 115 Krishnamurthy
RETURNING into arrays
DECLARE
TYPE emp_rec_type IS RECORD(empno EMP.EMPNO%TYPE,
% )
7/27/2019 Adv Plsql1
116/140
ename EMP.ENAME%TYPE);TYPE emp_tab_type IS TABLE OF emp_rec_typeINDEX BY binary_integer;emptab emp_tab_type;
BEGINUPDATE EMP SET SAL=SAL*1.15WHERE DEPTNO=30
RETURNING empno,ename BULK COLLECT INTO emptab;FOR i IN 1..emptab.LAST LOOPdbms_output.put_line(emptab(i).empno||','||emptab(i).ename);END LOOP;
END;
Advantech 116 Krishnamurthy
INSERT with RECORD BindCREATE TABLE retired_employeesAS SELECT * FROM EMP WHERE 1=0;
DECLAREv erec emp%rowtype;
7/27/2019 Adv Plsql1
117/140
v_erec emp%rowtype;BEGINSELECT * INTO v_erec FROM EMP WHERE EMPNO=7566;
INSERT INTO retired_employees VALUES v_erec;END;
Bulk INSERTing with a record.
DECLARETYPE emprectype IS TABLE OF emp%ROWTYPE;retirees emprectype;
BEGINSELECT * BULK COLLECT INTO retirees FROM EMP;FOR indx in retirees.first..retirees.last LOOP
INSERT INTO retired_employees VALUES retirees(indx);END LOOP;
END;
Advantech 117 Krishnamurthy
UPDATE SET ROW with RECORD Bind
Oracle gives you an easy and powerful way to update anentire row in a table from a record: the SET ROW clause.The ROW keyword is functionally equivalent to *.
7/27/2019 Adv Plsql1
118/140
DECLARE
v_erec emp%rowtype;BEGINSELECT * INTO v_erec FROM EMP WHERE EMPNO=7566;v_erec.sal:=v_erec.sal*1.5;v_erec.job:='SR CLERK';
UPDATE emp SET ROW = v_erec WHERE empno=v_erec.empno;END;
Advantech 118 Krishnamurthy
RETURNING into a record from a DELETE statement.
DECLAREv_erec emp%ROWTYPE;BEGIN
7/27/2019 Adv Plsql1
119/140
BEGINDELETE FROM emp WHERE empno = 7566
RETURNING empno, ename, job, mgr, hiredate, sal,comm, deptno INTO v_erec;
dbms_output.put_line('Deleted :'||v_erec.empno);END;
Advantech 119 Krishnamurthy
You can also RETURN less columnsEx - 1DECLARE
id emp.ename%TYPE;name emp.ename%TYPE;
BEGIN
7/27/2019 Adv Plsql1
120/140
BEGINDELETE FROM emp WHERE empno = 7566RETURNING empno, ename INTO id,name;
dbms_output.put_line('Deleted :'||id||','||name);END;
Ex - 2
DECLARETYPE key_rec_type IS RECORD (id NUMBER, name VARCHAR2 (100));v_erec key_rec_type;
BEGINDELETE FROM emp WHERE empno = 7566RETURNING empno, ename INTO v_erec;dbms_output.put_line('Deleted :'||v_erec.id||','||v_erec.name);
END;
Advantech 120 Krishnamurthy
FORALL statementEx:CREATE TABLE EMPLOY IS
SELECT * FROM EMP WHERE 1=0;
7/27/2019 Adv Plsql1
121/140
DECLARETYPE erectabtype IS TABLE OF employ%rowtype;
etab erectabtype;CURSOR empcursor IS SELECT * FROM EMP;
BEGIN
OPEN empcursor;FETCH empcursor BULK COLLECT INTO etab;FORALL i IN etab.first..etab.last
insert into employ values etab(i);
END;Note : can be used only if indexed numbers aresequential
Advantech 121 Krishnamurthy
Using RETURNING & FORALL
DECLARE
TYPE EmpTabType IS TABLE OF EMP.EMPNO%TYPE;emps EmpTabType;
7/27/2019 Adv Plsql1
122/140
BEGINDELETE FROM EMP WHERE HIREDATE LIKE '%81'
RETURNING empno BULK COLLECT INTO emps;dbms_output.put_line('Deleted Records are');FORALL i IN emps.first..emps.last
INSERT INTO DELETED_EMPS VALUES(emps(i));END;
Advantech 122 Krishnamurthy
The INDICES OF clause replaces the lower_bound..upper_bound to indicate that all valid index valuesshould be processed, even if there are gaps. It looks like
this:
7/27/2019 Adv Plsql1
123/140
FORALL index_name IN INDICES OF collection_name[BETWEEN lower_bound AND upper_bound]
sql_statement;
You can still limit the range processed by using the
BETWEEN syntax, which is optional.
Ex:FORALL i IN INDICES OF etab
insert into employ values etab(i);Note: can be used even if indexes are non-sequential(sparse)
Advantech 123 Krishnamurthy
CREATE TABLE ENAME_TABLE(names varchar2(12));
DECLARETYPE ename_table_type IS TABLE OF varchar2(12)d b l
7/27/2019 Adv Plsql1
124/140
index by pls_integer;enames ename_table_type;
BEGINFOR rec IN (select empno,ename from emp) LOOP
enames(rec.empno):=rec.ename;
END LOOP;FORALL x IN INDICES OF enamesinsert into ename_table values(enames(x));
END;
Advantech 124 Krishnamurthy
The VALUES OF clause enables you to processthe main collection in a different sequence. Youcreate a second collection containing only theindex numbers you want to process, in the orderyou want them processed
7/27/2019 Adv Plsql1
125/140
you want them processed.The statement then becomes:
FORALL index_name IN VALUES OFindex_collection
sql_statement;
Note:
-index cannot be used in iteration-dbms_output.put_line debug statement cannot be usedin iteration
Advantech 125 Krishnamurthy
CREATE TABLE ENAME_TABLE(names varchar2(12));
DECLARETYPE empno_tab_type IS TABLE OF emp.ename%type
INDEX BY l i t
7/27/2019 Adv Plsql1
126/140
INDEX BY pls_integer;empnames empno_tab_type;
TYPE index_table_type IS TABLE OF pls_integer;idx_tab index_table_type;
BEGINFOR rec IN (select empno,ename from emp) LOOP
empnames(rec.empno):=rec.ename;END LOOP;select empno bulk collect into idx_tab from emp;
FORALL x IN VALUES OF idx_tabinsert into ename_table select ename from emp where
ename=empnames(x);END;
Advantech 126 Krishnamurthy
Nested Table Multiset Operations
7/27/2019 Adv Plsql1
127/140
Advantech 127 Krishnamurthy
7/27/2019 Adv Plsql1
128/140
Advantech 128 Krishnamurthy
7/27/2019 Adv Plsql1
129/140
dbms_output.put_line('Distinct of t2 copied to t3');t3:=set(t2);for i IN t3.first..t3.last loop
dbms_output.put_line(t3(i));end loop;dbms output put line('t1 multiset union [distinct] t2');
7/27/2019 Adv Plsql1
130/140
dbms_output.put_line( t1 multiset union [distinct] t2 );t3:=t1 multiset union distinct(t2);
for i IN t3.first..t3.last loopdbms_output.put_line(t3(i));
end loop;dbms_output.put_line('t1 multiset intersect t2');t3:=t1 multiset intersect(t2);for i IN t3.first..t3.last loop
dbms_output.put_line(t3(i));
end loop;END;
Advantech 130 Krishnamurthy
VARRAYS
DECLARE
TYPE NumList IS VARRAY(3) OF VARCHAR2(12);nums NumList := NumList(10,20,30);BEGIN
7/27/2019 Adv Plsql1
131/140
for i in 1..3 loopDBMS_OUTPUT.PUT_LINE(nums(i));
end loop;nums(1):='A';nums(2):=60;nums(3):='welcome';
for i in 1..3 loopDBMS_OUTPUT.PUT_LINE(nums(i));end loop;
END;
Advantech 131 Krishnamurthy
Nested table column example
CREATE TYPE HOBBY_TAB_TYPE IS TABLE OF VARCHAR2(15);
CREATE TABLE EMPHOBBIES(empno NUMBER(4),ename VARCHAR2(12),
7/27/2019 Adv Plsql1
132/140
ename VARCHAR2(12),hobbies HOBBY_TAB_TYPE)
NESTED TABLE hobbies STORE AS HOBBY_EXT_TAB;
INSERT INTO EMPHOBBIES VALUES(7369,'SMITH',HOBBY_TAB_TYPE('FOOTBALL','CRICKET','MOVIES','SWIMMING'))
INSERT INTO EMPHOBBIES VALUES(7566,'JONES',HOBBY_TAB_TYPE('TV','SNOOKER','READING'));
SELECT * FROM EMPHOBBIES;
SELECT * FROM TABLE(SELECT HOBBIES FROM EMPHOBBIES WHEREEMPNO=7369);
Advantech 132 Krishnamurthy
SELECT E.EMPNO,E.ENAME,H.*FROM EMPHOBBIES E,TABLE(E.HOBBIES) H;
INSERT INTO TABLE(SELECT HOBBIES FROM EMPHOBBIES
WHERE EMPNO=7566)VALUES('TENNIS');
7/27/2019 Adv Plsql1
133/140
UPDATE TABLE(SELECT HOBBIES FROM EMPHOBBIES
WHERE EMPNO=7369)SET COLUMN_VALUE='READING' WHERECOLUMN_VALUE='SWIMMING';
DELETE TABLE(SELECT HOBBIES FROM EMPHOBBIES
WHERE EMPNO=7369)WHERE COLUMN_VALUE='CRICKET';
Advantech 133 Krishnamurthy
Using collections in database columns
CREATE TYPE ITEM_TYPE IS OBJECT(
ITEM_NAME VARCHAR2(12),ITEM_QTY NUMBER(2),ITEM_PRICE NUMBER(9,2));
7/27/2019 Adv Plsql1
134/140
CREATE TYPE ITEM_TAB_TYPE IS TABLE OF ITEM_TYPE;
CREATE TABLE INVOICE(INVOICE_NUM NUMBER(4),CUST_NAME VARCHAR2(12),
ITEM_DETAILS ITEM_TAB_TYPE)NESTED TABLE ITEM_DETAILS STORE AS ITEM_EXT_TABLE;
DESC INVOICE
DESC ITEM_EXT_TABLE
Advantech 134 Krishnamurthy
INSERT INTO INVOICE VALUES(1001,'PRAKASH',ITEM_TAB_TYPE(
ITEM_TYPE('P4 CPU',2,4500),ITEM_TYPE('INTEL M B',2,4750),
ITEM_TYPE('512MB RAM',3,1500)));
INSERT INTO INVOICE VALUES(1002,'MOHAN',
7/27/2019 Adv Plsql1
135/140
( , ,ITEM_TAB_TYPE(
ITEM_TYPE('KEYBOARD',5,450),ITEM_TYPE('SPEAKERS',3,370),ITEM_TYPE('ATX CABINET',3,1150),ITEM_TYPE('80GB HDD',2,5500)))
SELECT * FROM INVOICE;
SELECT ITEM_NAME,ITEM_QTY,ITEM_PRICE
FROM THE (SELECT ITEM_DETAILSFROM INVOICE WHERE INVOICE_NUM=1001);
Advantech 135 Krishnamurthy
SELECT * FROMTABLE(SELECT ITEM_DETAILSFROM INVOICEWHERE INVOICE_NUM=1001);
SELECT
7/27/2019 Adv Plsql1
136/140
SELECTI.INVOICE_NUM,
I.CUST_NAME,LI.ITEM_NAME,LI.ITEM_QTY,LI.ITEM_PRICEFROM INVOICE I,TABLE(I.ITEM_DETAILS) LI;
Now you can create a view for the above statement
Advantech 136 Krishnamurthy
CREATE VIEW INVOICE_ITEMASSELECTI.INVOICE_NUM,
I.CUST_NAME,LI.ITEM_NAME,LI.ITEM_QTY,
7/27/2019 Adv Plsql1
137/140
LI.ITEM_PRICE
FROM INVOICE I,TABLE(I.ITEM_DETAILS) LI;
Now we can query the view using item_name
SELECT * FROM INVOICE_ITEM
WHERE ITEM_NAME='80GB HDD';
To find total invoice amount for each customer
SELECT I.INVOICE_NUM,I.CUST_NAME,SUM(LI.ITEM_QTY*LI.ITEM_PRICE) "Total Amount"FROM INVOICE I,TABLE(I.ITEM_DETAILS) LIGROUP BY I.INVOICE_NUM,I.CUST_NAME
Advantech 137 Krishnamurthy
Performing DML operation on nested table column
Inserting into nested table column
INSERT INTO THE(SELECT ITEM_DETAILS FROM INVOICEWHERE INVOICE_NUM=1001)VALUES('120GB HDD',2,6500);
7/27/2019 Adv Plsql1
138/140
Updating a nested table column
UPDATE TABLE(SELECT ITEM_DETAILS FROM INVOICEWHERE INVOICE_NUM=1002)SET ITEM_PRICE=5200,ITEM_QTY=4 WHERE ITEM_NAME='80GB
HDD';
Deleting a nested table row
DELETE FROM TABLE(SELECT ITEM_DETAILS FROMINVOICE WHERE INVOICE_NUM=1002)WHERE ITEM_NAME='KEYBOARD';
Advantech 138 Krishnamurthy
varray in database columns
CREATE TYPE HOBBIES_ARRAY AS VARRAY(3) OF VARCHAR2(15);
CREATE TABLE PERSON(name VARCHAR2(12) PRIMARY KEY,HOBBY HOBBIES ARRAY);
7/27/2019 Adv Plsql1
139/140
HOBBY HOBBIES_ARRAY);
INSERT INTO PERSON VALUES('PRAKASH',HOBBIES_ARRAY('CRICKET','MOVIES','READING'))
INSERT INTO PERSON VALUES('GANESH',
HOBBIES_ARRAY('FOOTBALL','TENNIS','TV'));
SELECT * FROM PERSON;
SELECT * FROM TABLE(SELECT HOBBY
FROM PERSON WHERE NAME='PRAKASH');
SELECT P.NAME,H.*FROM PERSON P,TABLE(P.HOBBY) H;
Advantech 139 Krishnamurthy
While updating we have to update entine collection
UPDATE PERSON SET HOBBY=HOBBIES_ARRAY('FOOTBALL')WHERE NAME='PRAKASH';
When listed PRAKASH will be having only 'FOOTBALL' value
SELECT P NAME H *
7/27/2019 Adv Plsql1
140/140
SELECT P.NAME,H.*
FROM PERSON P,TABLE(P.HOBBY) H;
SELECT P.NAME,H.*FROM PERSON P,TABLE(P.HOBBY) HWHERE COLUMN_VALUE='FOOTBALL';
Advantech 140 Krishnamurthy