PLSQL 100 Rs

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 225

-----------------------------

“ORACLE PL-SQL 11g/12c”


-----------------------------

Focus Training Services


PUNE

Compiled And Edited By

Mr. Rahul V. Giri

Ms. Bhagyashri Phadatare

Version 2.0
Preface

It gives me an immense pleasure to come out with the Second


revised edition of this book on “ORACLE PL-SQL 11g/12c ”.
The arrangement of the contents in this book is made in order to
ensure a smooth flow of the subject for better understanding. I have
written this book especially for the students, so I have tried to cover
maximum part of the syllabus.

Starting from the basic concept and principle of PL-SQL, I have


covered the whole topic to measure the different attributes. At the
end of the book latest future trends of PL-SQL had been included.

I hope you will find this book very much beneficial. Your
suggestions are most welcome on.

Email: - rahul@focustraining.in

- Rahul V. Giri

Focus Trainig Services, Pune Page 1


Contents
OVERVIEW OF PL/SQL.............................................................................................................................. 9
1.1 What is PL/SQL? ................................................................................................................................. 9
1.2 Main Features of PL/SQL .................................................................................................................. 10
1.2.1 Block Structure........................................................................................................................... 10
1.2.2 Error Handling ............................................................................................................................ 11
1.2.3 Variables and Constants ............................................................................................................ 11
1.3 Data Abstraction ............................................................................................................................... 12
1.4 PL/SQL Architecture ......................................................................................................................... 13
PL/SQL DATATYPES AND VARIABLE DECLARATION ............................................................................ 14
2.1. Number Types: ................................................................................................................................ 15
2.2 Character Types: ............................................................................................................................... 17
2.3 LONG and LONG RAW ...................................................................................................................... 17
2..4 Boolean Type: .................................................................................................................................. 18
2.5 Datetime and Interval Types: ........................................................................................................... 18
2.6 VARIABLE DECLARATION .................................................................................................................. 19
2.6.1 Types of variables ...................................................................................................................... 19
2.6.2 Scope of variables in procedure. .............................................................................................. 25
PL/SQL CONTROL STRUCTURES ............................................................................................................. 29
3.1 Overview of PL/SQL Control Structures ........................................................................................... 29
3.2 Conditional Control: IF and CASE Statements .................................................................................. 30
3.2.1 IF-THEN-ELSE Statement ............................................................................................................ 30
3.2.2 CASE Statement ......................................................................................................................... 33
3.3 Iterative Control: LOOP and EXIT Statements .................................................................................. 34
3.3.1 LOOP .......................................................................................................................................... 34
3.3.2 EXIT ............................................................................................................................................ 35
3.3.3 EXIT-WHEN................................................................................................................................. 35
3.3.4 Basic Loop .................................................................................................................................. 36
3.3.5 WHILE-LOOP .............................................................................................................................. 37
3.3.6 FOR-LOOP .................................................................................................................................. 38
Composite Variable ............................................................................................................................... 42
4.1 Records ............................................................................................................................................. 42
4.2 %rowtype.......................................................................................................................................... 43
4.3 Index by table ................................................................................................................................... 44
ABOUT CURSORS ................................................................................................................................... 47

Focus Trainig Services, Pune Page 2


5.1 Overview of Implicit Cursors ............................................................................................................ 48
5.2 Overview of Explicit Cursors ............................................................................................................. 49
5.2.1 Declaring a Cursor...................................................................................................................... 49
5.2.2 Opening a Cursor ....................................................................................................................... 50
5.2.3 Fetching with a Cursor ............................................................................................................... 50
5.2.4 Closing a Cursor ......................................................................................................................... 50
5.3 Explicit cursor attributes ................................................................................................................. 51
5.3 1 Using Cursor FOR Loops ............................................................................................................. 52
5.4 Using Subqueries Instead of Explicit Cursors ................................................................................... 53
5.5 Parameterized Cursors ..................................................................................................................... 53
5.6 SELECT FOR UPDATE CURSOR ........................................................................................................ 55
5.7 Where current of clause .................................................................................................................. 57
HANDLING PL/SQL ERRORS ................................................................................................................... 60
6.1 Overview of PL/SQL Error Handling ................................................................................................. 60
6.2 Advantages of PL/SQL Exceptions .................................................................................................... 62
6.3 Predefined PL/SQL Exceptions (Named System Exceptions) ........................................................... 63
6.4 Non-predefined exceptions(Unnamed System Exceptions) ............................................................ 66
6.4.1Functions for trapping exceptions .............................................................................................. 68
6.5 Defining Your Own PL/SQL Exception .............................................................................................. 68
6.5.1 Declaring PL/SQL Exceptions ..................................................................................................... 69
6.5.2 Associating a PL/SQL Exception with a Number: Pragma EXCEPTION_INIT.............................. 69
6.5.3 Defining Your Own Error Messages: Procedure ........................................................................ 70
6.6 How PL/SQL Exceptions Propagate ................................................................................................. 71
SUBPROGRAMS (PROCEDURES & FUNCTIONS) .................................................................................... 75
7.1 Understanding PL/SQL Procedures .................................................................................................. 75
7.1.1 How to create stored procedure: .............................................................................................. 76
7.1.2 Parameters modes ..................................................................................................................... 77
7.1.3 Invoking Procedures .................................................................................................................. 79
7.1.4 Formal and Actual parameters .................................................................................................. 80
7.1.5 Methods of passing parameters ................................................................................................ 81
7.1.6 Using the DEFAULT option for parameters ............................................................................... 81
7.1.7 Viewing Procedures in the Data Dictionary ............................................................................... 82
7.1.8 Removing procedures ................................................................................................................ 83
7.2 Understanding PL/SQL Functions ..................................................................................................... 83
7.2.1.1 Invoke the function from plsql block. ................................................................................. 85

Focus Trainig Services, Pune Page 3


7.2.1.2 Invoke the function as a parameter value .......................................................................... 85
7.2.1.3 Using a host or bind variable ............................................................................................. 85
7.2.1.4 As an expression in a SQL statement .................................................................................. 85
7.2.2 Viewing Functions in the Data Dictionary ................................................................................ 85
7.2.3 list all functions within your schema ......................................................................................... 86
7.2.4 Removing functions ................................................................................................................... 86
7.3 Invoker's Rights versus Definer's Rights (AUTHID Clause) ............................................................... 86
7.3.1 Advantages of Invoker's Rights .................................................................................................. 87
PL/SQL PACKAGES.................................................................................................................................. 89
8.1 What Is a PL/SQL Package? .............................................................................................................. 89
8.1.1 Creating the package specification ............................................................................................ 90
8.1.2 Creating the package body ........................................................................................................ 91
8.2 Viewing packages in the Data Dictionary ......................................................................................... 93
8.2.1 To view the package specification use: ..................................................................................... 93
8.2.2 To view the package body use:.................................................................................................. 93
8.2.3 list all packages within your schema ......................................................................................... 93
8.3 Guidelines for writing packages ....................................................................................................... 93
8.4 Advantages of using Packages .......................................................................................................... 94
8.5 Removing Packages .......................................................................................................................... 94
8.6 Overloading Packaged Subprograms ............................................................................................... 97
8.6.1 The overloading feature in PL/SQL: ........................................................................................... 97
8.7 PL/SQL Wrapper (By using Unix Command) .................................................................................. 100
7.7.1 Running the Wrapper .............................................................................................................. 100
ORACLE PACKAGES .............................................................................................................................. 103
9.1 About the DBMS_OUTPUT Package ............................................................................................... 103
9.2 UTL_FILES........................................................................................................................................ 107
9.2.1 UTL_FILE_DIR = directory_name ............................................................................................. 107
9.2.2 UTL_FILE_DIR = /user/ngreenbe/my_app ............................................................................... 107
9.2.3 File Processing ......................................................................................................................... 107
9.2.4.1 The UTL_FILE Package: Procedures and Functions .............................................................. 108
9.2.4.2 The UTL_FILE Exceptions .................................................................................................. 109
9.2.5 Procedures and Functions: ...................................................................................................... 109
9.3. UTL_MAIL Package ........................................................................................................................ 115
9.3.1 Installing and Using UTL_MAIL ................................................................................................ 116
9.3.2 Example: .................................................................................................................................. 117

Focus Trainig Services, Pune Page 4


9.4 DBMS_SCHEDULER Package .......................................................................................................... 118
9.4.1 Overview of DBMS_SCHEDULER Package ............................................................................... 118
9.4.2 Creating Job with In-Line Parameters..................................................................................... 120
9.4.3 Managing Jobs ......................................................................................................................... 121
9.4.4 Data Dictionary Views for Managing Jobs ............................................................................... 124
9.5 how to generate XML from table data in PL/SQL........................................................................... 125
9.5.1 XMLTYPE .................................................................................................................................. 125
9.5.2 DBMS_XMLGEN ....................................................................................................................... 125
9.5.3 dbms_xmldom ......................................................................................................................... 127
9.6 Oracle dbms_ddl ............................................................................................................................ 129
9.6.1 DBMS_DDL.WRAP .................................................................................................................... 129
DATABASE TRIGGER............................................................................................................................. 133
10.2 Different Types of Triggers ........................................................................................................... 133
10.3 Guidelines for Designing Triggers ................................................................................................. 134
10.4 Creating DML Triggers .................................................................................................................. 135
10.4.1 DML Trigger Components: ..................................................................................................... 135
10.4.2 BEFORE Triggers ..................................................................................................................... 136
10.4.3 AFTER Triggers ....................................................................................................................... 136
10.4.4 INSTEAD OF Triggers ............................................................................................................. 136
10.5 Triggering user event:................................................................................................................... 136
10.6 Trigger types: ................................................................................................................................ 138
10.6.1 Statement Trigger .................................................................................................................. 138
10.6.2 Row Trigger ............................................................................................................................ 138
10.7 Using OLD and NEW Qualifiers ..................................................................................................... 140
10.8 INSTEAD OF Triggers .................................................................................................................... 142
10.8.1 Why Use INSTEAD OF Triggers?............................................................................................. 142
10.8.2 Creating an INSTEAD OF Trigger ............................................................................................ 143
10.9 Difference between Procedures and Triggers.............................................................................. 144
10.10 Managing Triggers: ..................................................................................................................... 145
10.10.1 Disable or reenable a database trigger: .............................................................................. 145
10.10.2 Disable or reenable all triggers for a table: ......................................................................... 145
10.10.3 Recompile a trigger for a table: ........................................................................................... 145
10.11 DROP TRIGGER Syntax ............................................................................................................... 145
10.11.1 Testing Triggers ................................................................................................................... 146
10.11.2 Trigger Execution Model and Constraint Checking ............................................................. 146

Focus Trainig Services, Pune Page 5


10.12 Trigger Execution Model ............................................................................................................ 146
10.13 Trigger Execution Model and Constraint Checking: ................................................................... 146
COLLECTIONS AND RECORDS .............................................................................................................. 148
11.1 Composite Data Types .................................................................................................................. 148
11.2 RECORD and TABLE Data Types.................................................................................................... 148
11.3 PL/SQL Records............................................................................................................................. 149
11.3.1 Creating a PL/SQL Record ...................................................................................................... 149
11.3.2 Defining and Declaring a PL/SQL Record ............................................................................... 149
11.4 PL/SQL Record Structure .............................................................................................................. 150
11.5 The %ROWTYPE Attribute ............................................................................................................ 150
11.5.1 Declaring Records with the %ROWTYPE Attribute ................................................................ 150
11.5.2 Advantages of Using %ROWTYPE .......................................................................................... 151
11.6 VARRAY ......................................................................................................................................... 151
11.7 Nested Table................................................................................................................................. 153
11.8 Associative Array (Index By Table) ............................................................................................... 155
11.8.1 Using Associative Array Methods .......................................................................................... 157
11.8.2 Method Description ............................................................................................................... 157
11.8.3 Associative Array of Records ................................................................................................. 158
11.9 Summary....................................................................................................................................... 158
BULK BINDING...................................................................................................................................... 160
12.1 Tuning PL/SQL Performance with Bulk Binds ............................................................................... 160
12.2 Reducing Loop Overhead for Collections with Bulk Binds ........................................................... 162
12.3 Bulk Binds Improve ....................................................................................................................... 163
12.4 Using the FORALL Statement ....................................................................................................... 166
12.5 Handling FORALL Exceptions with the %BULK_EXCEPTIONS Attribute ....................................... 167
12.6 Retrieving Query Results into Collections with the BULK COLLE Clause...................................... 169
12.7 Restrictions on BULK COLLECT ..................................................................................................... 171
12.8 Using FORALL and BULK COLLECT Together................................................................................. 172
12.9 Summary....................................................................................................................................... 172
Advanced Cursor .................................................................................................................................. 173
13.1 Cursor Variables ........................................................................................................................... 173
13.2 Why Use Cursor Variables? .......................................................................................................... 173
13.3 Defining a Cursor Variable ............................................................................................................ 173
13.3.1 Defining a Pointer of Type CURSOR ....................................................................................... 174
13.3.2 Defining a Variable of Type REF CURSOR .............................................................................. 174
13.3.3 Strong and Weak REF CURSOR Types .................................................................................... 174

Focus Trainig Services, Pune Page 6


13.4 Using a Cursor Variable ................................................................................................................ 175
13.4.1 Allocate Memory ................................................................................................................... 175
13.4.3 Fetching the Results into a PL/SQL Record or Individual PL/SQL Variables .......................... 176
13.4.4 Closing the Cursor Variable ................................................................................................... 177
13.5 Cursor Variables Assignment........................................................................................................ 178
13.6 Dynamism in Using Cursor Variables ........................................................................................... 180
Autonomous Transactions .................................................................................................................. 183
14.1 Features of Autonomous Transactions ........................................................................................ 184
14.2 Example Of Autonomous Transaction.......................................................................................... 184
14.3 Using Autonomous Transaction ................................................................................................... 186
NATIVE DYNAMIC SQL ......................................................................................................................... 187
15.1 What Is Dynamic SQL?.................................................................................................................. 187
15.2 The Need for Dynamic SQL ........................................................................................................... 188
15.3 Using the EXECUTE IMMEDIATE Statement ................................................................................. 188
15.4 Some Examples of Dynamic SQL .................................................................................................. 189

Appendix I: SQL*LOADER .................................................................................................................... 192


SQL*Loader Basics ................................................................................................................................ 192
B. SQL*Loader Control File ................................................................................................................... 193
C. Input Data and Datafiles ................................................................................................................... 193
Fixed Record Format ......................................................................................................................... 193
Variable Record Format .................................................................................................................... 194
D. Discarded and Rejected Records ..................................................................................................... 194
E. SQL*Loader Rejects ...................................................................................................................... 194
Oracle Rejects ................................................................................................................................... 195
SQL*Loader Discards ........................................................................................................................ 196
F. Log File and Logging Information ..................................................................................................... 196
Conventional Path Load versus Direct Path Load ............................................................................. 196
Conventional Path ............................................................................................................................ 196
Direct Path ........................................................................................................................................ 197
G. sqlldr command line options ........................................................................................................... 197
H. How to build control file .................................................................................................................. 197
Delimited File .................................................................................................................................... 197
Fixed length file................................................................................................................................. 198
How to load....................................................................................................................................... 198
How can you skip head records ........................................................................................................ 198

Focus Trainig Services, Pune Page 7


How can you change/transform data while loading ........................................................................ 198
How to selectively load data............................................................................................................. 199

Appendix II. OVERVIEW OF ORACLE ARCHITECTURE ......................................................................... 200


A. The Database.................................................................................................................................... 200
The Physical Layer ............................................................................................................................. 200
The Logical Layer............................................................................................................................... 201
B. Tablespaces and Datafiles ................................................................................................................ 201
C. Segments, Extents, and Data Blocks ................................................................................................ 202
Segments .......................................................................................................................................... 203
Extents .............................................................................................................................................. 203
Data Blocks........................................................................................................................................ 203
D. The Oracle Instance.......................................................................................................................... 203
The Oracle Memory Structure .......................................................................................................... 204
The System Global Area (SGA) .......................................................................................................... 204
The Program Global Area (PGA) ....................................................................................................... 205
Processes ....................................................................................................................................... 206
User Processes .............................................................................................................................. 206
Oracle Processes ........................................................................................................................... 206

Oracle Database 12c ............................................................................................................................ 208


A. Invoker Rights and the PL/SQL Function Result Cache ............................................................. 208
B. Define PL/SQL Subprograms in a SQL Statement ...................................................................... 211
C. Whitelists and the ACCESSIBLE BY Clause ................................................................................. 213
D. Grant Roles to Program Units ................................................................................................... 216
E. BOOLEAN Types ......................................................................................................................... 218
F. Record Types ............................................................................................................................. 219
G. Collections ................................................................................................................................. 220
H. TABLE Operator ......................................................................................................................... 223

Focus Trainig Services, Pune Page 8


1.
OVERVIEW OF PL/SQL
objective’s::
1) What is PL/SQL?
2) Main Features of PL/SQL
3) Data Abstraction
4) PL/SQL Architecture

Oracle first introduced Procedural Language/Structured Query Language (PL/SQL) in version 6.0 of its
relational database management system (RDBMS). As its RDBMS evolved, Oracle made
developmental changes to the PL/SQL language by introducing new features and enhancing existing
features. Oracle9i, the version of PL/SQL is PL/SQL 9.2 or 9.0 depending on whether it is Oracle9i
Release 2 (9.2.x) or Oracle9i Release 1 (9.0.x).

PL/SQL incorporates third-generation language (3GL) structures otherwise unavailable in Structured


Query Language (SQL). SQL is a fourth-generation language (4GL), meaning it uses constructs and
elements that specify "what to do" without having to specify "how to do it." It's a major language for
the Oracle RDBMS (as well as for other RDBMSs), and it's used for data definition, database querying,
and data manipulation and control. However, there are situations that demand the use of 3GL
constructs, such as conditional or iterative execution of SQL and the like. This kind of logic and
control flow can be achieved only in a 3GL language such as Java, C++, or C. To accommodate 3GL
features, Oracle designed and implemented the PL/SQL language as a procedural extension to SQL.
PL/SQL is integrated with SQL, and both SQL and PL/SQL serve as the major database server-side
languages, with each language complementing the other. You can also use PL/SQL in client-side
environments.

1.1 What is PL/SQL?


PL/SQL is Oracle procedural language extension to SQL. PL/SQL allows you to mix SQL statements
with procedural statements like IF statement, Looping structures etc. PL/SQL is the superset of SQL. It
uses SQL for data retrieval and manipulation and uses its own statements for data processing.

Focus Trainig Services, Pune Page 9


1.2 Main Features of PL/SQL
PL/SQL combines the data-manipulating power of SQL with the processing power of procedural
languages. When you can solve a problem with SQL, you can issue SQL statements from your PL/SQL
program, without learning new APIs. Like other procedural programming languages, PL/SQL lets you
declare constants and variables, control program flow, define subprograms, and trap runtime errors.
You can break complex problems into easily understandable subprograms, which you can reuse in
multiple applications.
Topics
 Blocks
 Error Handling
 Variables and Constants
 Subprograms
 Packages
 Triggers
 Input and Output (PL/SQL I/O-Processing Packages)
 Data Abstraction

1.2.1 Block Structure

PL/SQL is a block-structured language. That is, the basic units (procedures, functions, and anonymous
blocks) that make up a PL/SQL program are logical blocks, which can contain any number of nested
sub-blocks. Typically, each logical block corresponds to a problem or sub problem to be solved. Thus,
PL/SQL supports the divide-and-conquer approach to problem solving called stepwise refinement
 Anonymous Block

Figure - Block Structure(Anonymous Block)

Focus Trainig Services, Pune Page 10


A block (or sub-block) lets you group logically related declarations and statements. That way, you can
place declarations close to where they are used. The declarations are local to the block and cease to
exist when the block completes. As Figure below shows, a PL/SQL block has three parts: a declarative
part, an Executable part, and an Exception-handling part. (In PL/SQL, a warning or error condition is
called an exception.) Only the executable part is required. The order of the parts is logical. First
comes the declarative part, in which items can be declared. Once declared, items can be manipulated
in the executable part. Exceptions raised during execution can be dealt with in the exception-
handling part.
You can nest sub-blocks in the executable and exception-handling parts of a PL/SQL block or
subprogram but not in the declarative part. Also, you can define local subprograms in the declarative
part of any block. However, you can call local subprograms only from the block in which they are
defined

1.2.2 Error Handling

PL/SQL makes it easy to detect and handle errors. When an error occurs, PL/SQL raises an exception.
Normal execution stops and control transfers to the exception-handling part of the PL/SQL block. You
do not have to check every operation to ensure that it succeeded, as in a C program.

1.2.3 Variables and Constants


PL/SQL lets you declare variables and constants, and then use them wherever you can use an
expression. As the program runs, the values of variables can change, but the values of constants
cannot. For more information
 Subprograms

A PL/SQL subprogram is a named PL/SQL block that can be invoked repeatedly. If the
subprogram has parameters, their values can differ for each invocation. PL/SQL has two types of
subprograms, procedures and functions. A function returns a result.
Syntax of Procedure:
CREATE [OR REPLACE] PROCEDURE <procedure_name>
[ (parameter1 [mode] datatype1,
parameter2 [mode] datatype2,....) ]
IS | AS

Focus Trainig Services, Pune Page 11


local_variable declaration]
BEGIN
executable_section

[EXCEPTION
exception_section]
END [procedure_name];

 Packages

A package is a schema object that groups logically related PL/SQL types, variables, constants,
subprograms, cursors, and exceptions. A package is compiled and stored in the database, where
many applications can share its contents. You can think of a package as an application.
 Triggers

A trigger is a named PL/SQL unit that is stored in the database and run in response to an event
that occurs in the database. You can specify the event, whether the trigger fires before or after
the event, and whether the trigger runs for each event or for each row affected by the event.
For example, you can create a trigger that runs every time an INSERT statement affects the
EMPLOYEES table.
 Input and Output (PL/SQL I/O-Processing Packages)

Most PL/SQL input and output (I/O) is done with SQL statements that store data in database
tables or query those tables. For information about SQL statements, see Oracle Database SQL
Language Reference. All other PL/SQL I/O is done with PL/SQL packages that Oracle Database
supplies.

1.3 Data Abstraction


Data abstraction lets you work with the essential properties of data without being too involved with
details. You can design a data structure first, and then design algorithms that manipulate it.

Topics
 Cursors
 Composite Variables
 %ROWTYPE Attribute
 %TYPE Attribute
 Abstract Data Types

Focus Trainig Services, Pune Page 12


1.4 PL/SQL Architecture
The PL/SQL compilation and run-time system is a technology, not an independent product. Think of
this technology as an engine that compiles and executes PL/SQL blocks and subprograms. The engine
can be installed in an Oracle server or in an application development tool such as Oracle Forms or
Oracle Reports. The engine executes procedural statements but sends SQL statements to the SQL
Statement Executor in the Oracle server. Figure shows the PL/SQL engine processing an anonymous
block.

Focus Trainig Services, Pune Page 13


2.
PL/SQL DATATYPES AND VARIABLE
DECLARATION
Objective’s:
1) Number Types
2) Character Types
3) LONG and LONG RAW
4) Boolean Type
5) Datetime and Interval Types.

Every constant, variable, and parameter has a data type (or type), which specifies a storage format,
constraints, and valid range of values. PL/SQL provides a variety of predefined data types. For
instance, you can choose from integer, floating point, character, Boolean, date, collection, reference,
and LOB types. In addition, PL/SQL lets you define your own subtypes.

 Predefined Data types


A scalar type has no internal components. A composite type has internal components that can be
manipulated individually. A reference type holds values, called pointers that designate other program
items. A LOB type holds values, called lob locators that specify the location of large objects (graphic
images for example) stored out-of-line. Figure below shows the predefined data types available for
your use. The scalar types fall into four families, which store number, character, Boolean, and
date/time data, respectively.

Focus Trainig Services, Pune Page 14


Figure - Built-in Data types

2.1. Number Types:


Number types let you store numeric data (integers, real numbers, and floating-point Numbers),
represent quantities, and do calculations.

 BINARY_INTEGER
You use the BINARY_INTEGER data type to store signed integers. Its magnitude range is -2**31 ..
2**31.NUMBER you use the NUMBER data type to store fixed-point or floating-point numbers. Its
magnitude range is 1E-130 .. 10E125. You can specify precision, which is the total number of digits,
and scale, which is the number of digits to the right of the decimal point. The syntax follows:

 NUMBER [(precision, scale)]


To declare fixed-point numbers, for which following form: you must specify scale, use the

 NUMBER (precision, scale)


To declare floating-point numbers, for which you cannot specify precision or scale because the
decimal point can "float" to any position, use the following Form:

 NUMBER
To declare integers, which have no decimal point, use this form:
NUMBER (precision)

Focus Trainig Services, Pune Page 15


-- Same as NUMBER (precision, 0)
NUMBER Subtypes
You can use the following NUMBER subtypes for compatibility with ANSI/ISO and IBM types or when
you want a more descriptive name:
 DEC
 DECIMAL
 DOUBLE PRECISION
 FLOAT
 INTEGER
 INT
 NUMERIC
 REAL
 SMALLINT

Use the subtypes DEC, DECIMAL, and NUMERIC to declare fixed-point numbers with a maximum
precision of 38 decimal digits. Use the subtypes DOUBLE PRECISION and FLOAT to declare floating-
point numbers with a maximum precision of 126 binary digits, which is roughly equivalent to 38
decimal digits. Or, use the subtype REAL to declare floating-point numbers with a maximum
precision of 63 nary digits, which is roughly equivalent to 18 decimal digits. Use the subtypes
INTEGER, INT, and SMALLINT to declare integers with a maximum
precision of 38 decimal digits.

 PLS_INTEGER
You use the PLS_INTEGER data type to store signed integers. Its magnitude range is -2**31 .. 2**31.

Although PLS_INTEGER and BINARY_INTEGER have the same magnitude range, they are not fully
compatible. When a PLS_INTEGER calculation overflows, anexception is raised. However, when a
BINARY_INTEGER calculation overflows, noexception is raised if the result is assigned to a NUMBER
variable. Because of this small semantic difference, you might want to continue using
BINARY_INTEGER in old applications for compatibility. In new applications, always use PLS_INTEGER
for better performance.

Focus Trainig Services, Pune Page 16


2.2 Character Types:
Character types let you store alphanumeric data, represent words and text, and manipulate
character strings.

 CHAR
You use the CHAR data type to store fixed-length character data. The CHAR data type takes an
optional parameter that lets you specify a maximum size up to 32767 bytes.

The syntax follows:

CHAR[(maximum size [CHAR | BYTE] )]

If you do not specify a maximum size, it defaults to 1.

 VARCHAR2
You use the VARCHAR2 data type to store variable-length character data. The VARCHAR2 data type
takes a required parameter that specifies a maximum size up to 32767 bytes. The syntax follows:

VARCHAR2 (maximum_size [CHAR | BYTE])

If one value in a comparison has data type VARCHAR2 and the other value has data type CHAR, non-
blank-padding semantics are used. But, remember, when you assign a character value to a CHAR
variable, if the value is shorter than the declared length of the variable, PL/SQL blank-pads the value
to the declared length. So, given the declarations

last_name1 VARCHAR2(10) := 'STAUB';


last_name2 CHAR(10):= 'STAUB';

2.3 LONG and LONG RAW


You use the LONG data type to store variable-length character strings. The LONG data type is like the
VARCHAR2 data type, except that the maximum size of a LONG value is 32760 bytes.
You use the LONG RAW data type to store binary data or byte strings. LONG RAW data is like LONG
data, except that LONG RAW data is not interpreted by PL/SQL. The maximum size of a LONG RAW
value is 32760 bytes.

Focus Trainig Services, Pune Page 17


LONG columns can store text, arrays of characters, or even short documents. You can reference
LONG columns in UPDATE, INSERT, and (most) SELECT statements, but not in expressions, SQL
function calls, or certain SQL clauses such as WHERE, GROUP BY, and CONNECT BY.

 ROWID
Internally, every database table has a ROWID pseudo column, which stores binary values called
rowdies. Each rowid represents the storage address of a row. A physical rowid identifies a row in an
ordinary table. For example, in SQL*Plus (which implicitly converts rowids into character strings), the
query
SQL> SELECT row_id , ename FROM emp WHERE empno = 7788;

might return the following row:

ROWIDE NAME
------------------ ----------
AAAAqcAABAAADFNAAH SCOTT

2..4 Boolean Type:


You use the BOOLEAN datatype to store the logical values TRUE, FALSE, and NULL (which stands for a
missing, unknown, or inapplicable value). Only logic operations are allowed on BOOLEAN variables.

2.5 Datetime and Interval Types:


The datatypes in this section let you store and manipulate dates, times, and intervals (periods of
time). A variable that has a date/time datatype holds values called datetimes; a variable that has an
interval datatype holds values called intervals. A datetime or interval consists of fields, which
determine its value. The following list shows the valid values for each field:

 DATE
You use the DATE datatype to store fixed-length datetimes, which include the time of day in seconds
since midnight. The date portion defaults to the first day of the current month; the time portion
defaults to midnight. The date function SYSDATE returns the current date and time.

Focus Trainig Services, Pune Page 18


Tip: To compare dates for equality, regardless of the time portion of each date, use the function
result TRUNC(date_variable) in comparisons, GROUP BY operations, and so on.

You can add and subtract dates. In arithmetic expressions, PL/SQL interprets integer literals as days.
For instance, TIMESTAMP

The datatype TIMESTAMP, which extends the datatype DATE, stores the year, month,day, hour,
minute, and second.The syntax is:

TIMESTAMP[(precision)]

Where the optional parameter precision specifies the number of digits in the fractional part of the
seconds field. You cannot use a symbolic constant or variable to specify the precision; you must use
an integer literal in the range 0 .. 9. The default is 6. In the following example, you declare a variable
of type TIMESTAMP, and then assign a literal value to it:

DECLARE
checkout TIMESTAMP(3);
BEGIN
checkout := '1999-06-22 07:48:53.275';
...
END;
/

“In this example, the fractional part of the seconds field is 0.275.”

2.6 VARIABLE DECLARATION

2.6.1 Types of variables

 CHAR [(maximum length)]


 VARCHAR2 (maximum length)
 LONG
 NUMBER [(precision , scale)]

Focus Trainig Services, Pune Page 19


 BINARY INTEGER
 PLS_INTEGER
 BOOLEAN

BINARY INTEGER:-
Base type for integer between -2,147,483,647 and 2,147,483,647

PLS_INTEGER :-
Base type for signed integers between -2,147,483,647 and 2,147,483,647 PLS_INTEGER values
require less storage and are faster than NUMBER and BINARY_INTEGER values

BOOLEAN:-
Base type that stores one of three possible values used for logical calculations: TRUE, FALSE, NULL
This is the first program in plsql to print “Hello world”.
create or replace procedure sp1
as
-- First Program of Plsql
-- This Program Prints
-- Hello World on the Screen
begin
dbms_output.put_line('Hello World');
-- [dbms_output is a PL-SQL Package and put_line is their Package
member which is user for print Character or string ]
end;
/

 To Compile Stored Procedures


 Type @file name/procedure name.sql on SQL Prompt
 To see the output on sql prompt type command
 ‘set serveroutput on’ when you are logged in.
 TO Execute Stored Procedures
 Type exec procedure_name

Focus Trainig Services, Pune Page 20


 SET SERVEROUTPUT
Whenever you start Oracle SQL (PL/SQL) at that time you must have to write the "SET Serveroutput
ON" command.
PL/SQL program execution into Oracle engine so we always required to get serveroutput result and
display into the screen otherwise result can't be display

OUTPUT:

SQL> @sp1.sql
Procedure created.
No errors.

SQL> exec sp1


Hello Word

PL/SQL procedure successfully completed.

 Variable declaration and assigning value to variables.

create or replace procedure sp2


--This Program Shows How to declare variables, assign values and
constants.
as
v_myname CHAR(50);
v_myage NUMBER(2) NOT NULL := 21;
v_mycity VARCHAR2(13) := ‘Pune’;
v_salary CONSTANT NUMBER := 1400;

begin
v_myname := ‘Nagnath’;
dbms_output.put_line('My Name is '||v_myname);
dbms_output.put_line('My Age is '||v_myage);
end;
/

Focus Trainig Services, Pune Page 21


show errors
Set serveroutput on

OUTPUT:

SQL> @sp2.sql
Procedure created.
No errors.
SQL> exec sp2
My Name is Nagnath
My Age is 21

PL/SQL procedure successfully completed

 Passing value to variables.


create or replace procedure sp3(l_name varchar2, l_age number
default 100)
--This Program shows how to Pass Values to procedures
--Accept values in variable without specifying its length
As

begin
dbms_output.put_line('Name Entered By User: '||l_name);
dbms_output.put_line('Age Entered By User: '||l_age);
end;
/
show errors
Set serveroutput on

OUTPUT:

Focus Trainig Services, Pune Page 22


SQL> @sp3.sql
Procedure created.
No errors

SQL> exec sp3('nagnath',21);


Name Entered By User: nagnath
Age Entered By User: 21

PL/SQL procedure successfully completed.

 Selecting values from database tables.

“This Programs Shows how to Execute SQL quries from plsql”


create or replace procedure sp4
--
as
l_employee_id Number := 100;
l_employee_name varchar2(30);
begin
select last_name
into l_employee_name
from Employees
where employee_id = l_employee_id;
--into clause copies selected column's value
--into given variables
dbms_output.put_line('Employees Name is: '|| l_employee_name);
end;
/
show errors

OUTPUT

SQL> @sp4.sql

Focus Trainig Services, Pune Page 23


Procedure created.
No errors.
SQL> exec sp4
Employees Name is: King

PL/SQL procedure successfully completed.

 Use of %type variable.


create or replace procedure sp5(l_employee_id number)
--This Program shows
--how to use variables with same data type from tables
--Objective
--Accept Employee_id From User
--Print Name of That Employee
as
l_last_name employees.last_name%type;
begin
select last_name
into l_last_name
from employees
where employee_id = l_employee_id;
dbms_output.put_line('Name of Employee is:
'||l_last_name);
end;
/
show errors
set serveroutput on

OUTPUT:

SQL> @sp5
Procedure created.
No errors.

Focus Trainig Services, Pune Page 24


SQL> exec sp5(200);
Name of Employee is: Whalen

PL/SQL procedure successfully completed.

2.6.2 Scope of variables in procedure.

create or replace procedure sp6


--This Program shows Scope Of Variable in Stored Procedure

As
l_no number := 600;
l_msg varchar2(20) := 'Global Variable';
Begin
<<Inner_Block1>>
Declare
l_no Number := 1;
l_msg varchar2(20) := 'Local variable';
Begin
l_no := l_no +1;
dbms_output.put_line('In Inner Block1');
dbms_output.put_line(l_no);
dbms_output.put_line(l_msg);
End;
<<Inner_Block2>>
Declare
l_no number :=100;
Begin
dbms_output.put_line('In Inner Block2');
dbms_output.put_line(l_no);
dbms_output.put_line(sp16.l_msg);
End;
dbms_output.put_line('In Main');
dbms_output.put_line(l_no);

Focus Trainig Services, Pune Page 25


dbms_output.put_line(l_msg);
End;
/
show errors

 Variables declared in main procedure (Outermost variable) are global variables.


 Global variables can be accessable in all inner procedures.
 Inner procedures can define their own variables with same name
 as global variable and access.
 But it is not good programing practice.

OUTPUT:
SQL> @sp6.sql
Procedure created.
No errors.

SQL> exec sp6


In Inner
Block2 2
Local Variable
In Inner
Block2 100
Global
Variable In
Inner Main 600
Global Variable

PL/SQL procedure successfully completed

 DML Statements in Procedure


create or replace procedure sp7
--This Programs shows Executing DML statement in Plsql
As
Begin

Focus Trainig Services, Pune Page 26


--Inserting Data From Plsql Procedure
insert into test(test_id,test_name)
values(1,'sql');
insert into test(test_id,test_name)
values(2,'plsql');
--Updating Data From Plsql Procedure
update test
set test_id = 20
where test_id = 2;
--Deleting Data From Plsql Procedure
delete from test
where test_id = 20;
commit;
end;
/
show errors

OUTPUT:
create table test(test_id number,test_name varchar2(10));
Table created.
SQL> @sp7.sql
Procedure created.
No errors.
SQL> exec sp17
PL/SQL procedure successfully completed.
SQL> select * from test;
TEST_ID TEST_NAME
------- ----------------
1 sql

Focus Trainig Services, Pune Page 27


Exercise:

1. Passs the department number 80 and who work in that department?

2. Display employee name , salary, job_id,city,region_id and pass the department number using
parameter procedure?

3. Display employee name , salary, job whos employee_id is 100 (using %type veriable)?

Focus Trainig Services, Pune Page 28


3.
PL/SQL CONTROL STRUCTURES
Objects:
1) Overview of PL/SQL Control Structures
2) Conditional Control: IF and CASE Statements
3) Iterative Control: LOOP and EXIT Statements

3.1 Overview of PL/SQL Control Structures


According to the structure theorem, any computer program can be written using the basic control
structures shown in Figure. They can be combined in any way necessary to deal with a given
problem.

Figure Control Structures

The selection structure tests a condition, and then executes one sequence of statements instead of
another, depending on whether the condition is true or false. A condition is any variable or
expression that returns a Boolean value (TRUE or FALSE). The iteration structure executes a sequence
of statements repeatedly as long as a condition holds true. The sequence structure simply executes a
sequence of statements in the order in which they occur.

Focus Trainig Services, Pune Page 29


3.2 Conditional Control: IF and CASE Statements
IF statement lets you execute a sequence of statements conditionally. There are three forms of IF
statements: IF- HEN, IF-THEN-ELSE, and IF-THEN-ELSIF. The CASE statement is a compact way to
evaluate a single condition and choose between many alternative actions

3.2.1 IF-THEN-ELSE Statement

IF-THEN Statement
The simplest form of IF statement associates a condition with a sequence of statements enclosed by
the keywords THEN and END IF (not ENDIF), as follows:

IF condition THEN
sequence_of_statements
END IF;

The sequence of statements is executed only if the condition is true. If the condition is false or null,
the IF statement does nothing . You might want to place brief IF statements on a single line, as in

IF x > y THEN high := x; END IF;

IF-THEN-ELSE Statement
The second form of IF statement adds the keyword ELSE followed by an alternative sequence of
statements, as follows:

IF condition THEN
sequence_of_statements1
ELSE
sequence_of_statements2
END IF;

The sequence of statements in the ELSE c lause is executed only if the condition is falseor null.
Thus, the ELSE clause ensures that a sequence of statements is executed. In the following example,
the first UPDATE statement is executed when the condition is true, but the second UPDATE
statement is executed when the condition is false or null

Focus Trainig Services, Pune Page 30


IF-THEN- ELSIF-ELSE Statement
The simplest form of IF statement associates a condition with a sequence of statements enclosed by
the keywords THEN and END IF (not ENDIF), as follows:

Syntax:-

IF condition THEN
sequence_of_statements1

*{ELSIF condition THEN


sequence_of_statements2}
ELSE
sequence_of_statements3
END IF;

The sequence of statements is executed only if the condition is true. If the condition is false or null,
the IF statement does nothing. In either case, control passes to the next statement. An example
follows:

create or replace procedure sp8(p_employee_id in number)


– This procedure will give a salary raise
-- to an employee. Rules for the raise are as follows
-- 1. 20% for Employees working with us for at least 12 years
-- and whose salary is less than Rs. 6000/-
-- 2. 15% for Employees whose salary less than Rs. 6000/-
-- 3. 10% for employees working with us for at least 12 years

As
l_hire_date employees.hire_date%type;
l_salary employees.salary%type;
l_years_of_service number := 0;
l_new_salary number := 0;
begin
select hire_date, salary
into l_hire_date, l_salary
from employees

Focus Trainig Services, Pune Page 31


where employee_id = p_employee_id;
l_years_of_service := months_between(sysdate, l_hire_date)/12;
if l_salary < 6000 and l_years_of_service > 12 then
l_new_salary := l_salary * 1.2;
dbms_output.put_line('Giving 20% raise');
Elsif l_salary < 6000 then
l_new_salary := l_salary * 1.15;
dbms_output.put_line('Giving 15% raise');
Elsif l_years_of_service > 12 then
l_new_salary := l_salary * 1.1;
dbms_output.put_line('Giving 10% raise');
Else
l_new_salary := l_salary;
dbms_output.put_line('No salary raise ');
End if;

update employees
set salary = l_new_salary
where employee_id = p_employee_id;
commit;
end;
/
Show error
Set serveroutput on

OUTPUT:
SQL> @sp8.sql
Procedure created.
No errors.
SQL> select salary from employees where employee_id=101;
SALARY
----------
17000
SQL> exec sp8(101);

Focus Trainig Services, Pune Page 32


Giving 10% raise
PL/SQL procedure successfully completed.
SQL> select salary from employees where employee_id=101;
SALARY
----------
18700

3.2.2 CASE Statement

Like the IF statement, the CASE statement selects one sequence of statements to execute. However,
to select the sequence, the CASE statement uses a selector rather than multiple Boolean expressions.
To compare the IF and CASE statements, consider the following code that outputs descriptions of
school grades:
CASE selector
WHEN expression1 THEN result1
WHEN expression2 THEN result2
...
WHEN expressionN THEN resultN
[ELSE resultN+1;]
END;
--A CASE expression selects a result and returns it

create or replace procedure sp9(p_grade in varchar2)


As
l_appraisal varchar2(100);

begin
l_appraisal := CASE p_grade
WHEN 'A' THEN 'Excellent'
WHEN 'B' THEN 'Very Good'
WHEN 'C' THEN 'Good'
ELSE 'No such grade'

Focus Trainig Services, Pune Page 33


END;
DBMS_OUTPUT.PUT_LINE ('Grade: '|| p_grade ||' Appraisal ' ||
l_appraisal);
end;
/
show errors

OUTPUT:
SQL> @sp9.sql
Procedure created.
No errors.

SQL> exec sp9('C');


Grade: C Appraisal Good

PL/SQL procedure successfully completed.

The CASE statement is more readable and more efficient. So, when possible, rewrite lengthy IF-THEN-
ELSIF statements as CASE statements.Iterative Control: LOOP and EXIT Statements LOOP statements
let you execute a sequence of statements multiple times. There are three forms of LOOP statements:
LOOP, WHILE-LOOP, and FOR-LOOP.

3.3 Iterative Control: LOOP and EXIT Statements

3.3.1 LOOP
The simplest form of LOOP statement is the basic (or infinite) loop, which encloses a sequence of
statements between the keywords LOOP and END LOOP, as follows:

LOOP
sequence_of_statements
END LOOP;

With each iteration of the loop, the sequence of statements is executed, then control resumes at the
top of the loop. If further processing is undesirable or impossible, you can use an EXIT statement to
complete the loop.

Focus Trainig Services, Pune Page 34


3.3.2 EXIT
The EXIT statement forces a loop to complete unconditionally. When an EXIT statement is
encountered, the loop completes immediately and control passes to the next statement. An example
follows

LOOP
IF credit_rating < 3 THEN
EXIT;
-- exit loop immediately
END IF;
END LOOP;
-- control resumes here

*Remember, the EXIT statement must be placed inside a loop. To complete a PL/SQL block before
its normal end is reached, you can use the RETURN statement.*

3.3.3 EXIT-WHEN
The EXIT-WHEN statement lets a loop complete conditionally. When the EXIT statement is
encountered, the condition in the WHEN clause is evaluated. If the cond -ition is true, the loop
completes and control passes to the next statement after the loop. An example follows:

LOOP
FETCH c1 INTO ...
EXIT WHEN c1%NOTFOUND;
-- exit loop if condition is true
...
END LOOP;
CLOSE c1;

Until the condition is true, the loop cannot complete. So, a statement inside the loop must change
the value of the condition. In the last example, if the FETCH statement returns a row, the condition is
false. When the FETCH statement fails to return a row, the condition is true, the loop completes, and
control passes to the CLOSE statement.

Focus Trainig Services, Pune Page 35


3.3.4 Basic Loop
Use the basic loop when the statements inside the loop must execute at least once.
LOOP
statement1;
...
EXIT [WHEN condition ];
END LOOP;
 Basic loop perform repetative actions.

 Programer can use exit condition to terminate the loop An example follows:
create or replace procedure sp10 ( p_loop_counter in number)
As
i number;
Begin
i := 1;
loop
dbms_output.put_line(to_char(i) );
exit when i >= p_loop_counter;
i := i +1;
end loop;
End;
/
show errors

OUTPUT
SQL> @sp10.sql
Procedure created.
No errors.
SQL> exec sp10(5);
1
2
3
4
5
PL/SQL procedure successfully completed.

Focus Trainig Services, Pune Page 36


3.3.5 WHILE-LOOP

The WHILE-LOOP statement associates a condition with a sequence of statements enclosed by the
keywords LOOP and END LOOP, as follows:

WHILE condition LOOP


sequence_of_statements
END LOOP

Before each iteration of the loop, the condition is evaluated. If the condition is true, the sequence of
statements is executed, then control resumes at the top of the loop. If the condition is false or null,
the loop is bypassed and control passes to the next statement. An example follows:
create or replace procedure sp11 ( p_loop_counter in number)
as
i number;
begin
i := 1;
while i<= p_loop_counter
loop
dbms_output.put_line(to_char(i) );
i := i + 1;
end loop;
end;
/
show errors

 Use the WHILE loop if the condition has to be evaluated at the start of each iteration.
 While loop performs repetative actions until controling condition is no longer True.
 The condition is checked at start of each transaction.

Focus Trainig Services, Pune Page 37


OUTPUT
SQL> @sp11.sql
Procedure created.
No errors.
SQL> exec sp11(5);
1
2
3
4
5
PL/SQL procedure successfully completed.

3.3.6 FOR-LOOP
Whereas the number of iterations through a WHILE loop is unknown until the loopcompletes, the
number of iterations through a FOR loop is known before the loop is entered. FOR loops iterate over
a specified range of integers. The range is part of an iteration scheme, which is enclosed by the
keywords FOR and LOOPS. A double dot ( .. ) serves as the range operator. The syntax follows:

FOR counter IN [REVERSE] <lower_bound> . . <higher_bound LOOP>


sequence_of_statements
END LOOP

An example follows:

create or replace procedure sp12( p_loop_counter in number)


as
i number;
begin
-- Naming a loop is optional
<<my_for_loop>>
for i in 1..p_loop_counter loop
-- lower_bound..upper_bound LOOP
dbms_output.put_line(to_char(i) );
end loop my_for_loop;
dbms_output.put_line('------------------------');

Focus Trainig Services, Pune Page 38


-- now the reverse for loop
for i in reverse 1..p_loop_counter
loop
dbms_output.put_line(to_char(i) );
end loop;
end;
/
show errors

OUTPUT
SQL> @sp12.sql
Procedure created.
No errors.

SQL> exec sp12(3);


1
2
3
------------------------
3
2
1
PL/SQL procedure successfully completed.

 Dynamic Ranges

PL/SQL lets you determine the loop range dynamically at run time, as the following example shows:

SELECT COUNT(empno) INTO emp_count FROM emp;


FOR i IN 1..emp_count LOOP
...
END LOOP;

The value of emp_count is unknown at compile time; the SELECT statement returns the value at run
time. What happens if the lower bound of a loop range evaluates to a larger integer than the upper

Focus Trainig Services, Pune Page 39


bound? As the next example shows, the sequence of statements within the loop is not executed and
control passes to the next statement:

-- limit becomes 1
FOR i IN 2..limit LOOP
sequence_of_statements -- executes zero times
END LOOP;
-- control passes here

 Scope Rules
The loop counter is defined only within the loop. You cannot reference it outside the loop. After the
loop is exited, the loop counter is undefined, as the following example shows:

FOR ctr IN 1..10 LOOP


...
END LOOP;
sum := ctr - 1; -- not allowed

Focus Trainig Services, Pune Page 40


Exercise:
1. Display the output as follows :
3
6
9
12
15
18
21
24
27
30

2. Display all Last_name through out loop ?

3. Display employee with the bonous , Bonus is 15% of commission drawn by the employee if the
employee does not earn any commission then display message ‘ Does not earn any commission’.
Otherwise add Bonus to the salary of the mployee and display it on the screen.The block should
accept an input for the employe number ?

4. Create two table T1 and T2 add column e_id and d_name,

If d_name is ‘IT’ then all entries copied to table T1 otherwise T2 ?

5. Display that department name who belongs to department is 50 ?

Focus Trainig Services, Pune Page 41


4.
Composite Variable
Objectives:

1) Records
2) %rowtype
3) Index by table

4.1 Records
Composite Data type Records stores more than one data type under single record .

create or replace procedure sp13


--This program shows how to
--create composite data types
--First Composite data type is record
as
TYPE emp_sal_record is RECORD (last_name varchar2(20), salary
number(10));
emp_sal emp_sal_record ;
Begin
select last_name,salary
into emp_sal
from employees
where employee_id = 100;

dbms_output.put_line('Employee Name: '||emp_sal.last_name);


dbms_output.put_line('Employees Salary: '||emp_sal.salary);
end;
/
show errors

Focus Trainig Services, Pune Page 42


OUTPUT:
SQL> @sp13.sql
Procedure created.
No errors.

SQL> set serveroutput on

SQL> exec sp13


Employee Name: King
Employees Salary: 24000

PL/SQL procedure successfully completed.

4.2 %rowtype
%rowtype variable is used to store all column data types in single variable

create or replace procedure sp14


--This program shows how to
--create composite data types
--Second composite data type is %rowtype
as
emp_record employees%rowtype;

--emp_record stores all values of all columns from employees table

begin
select *
into emp_record
from employees
where employee_id = 100;
dbms_output.put_line('Name: '||emp_record.last_name);
dbms_output.put_line('Department Id: '||
emp_record.department_id);
end;

Focus Trainig Services, Pune Page 43


/
show errors

OUTPUT:
SQL> @sp14.sql
Procedure created.
No errors.

SQL> set serveroutput on

SQL> exec sp14


Name: King
Department Id: 90

PL/SQL procedure successfully completed.

4.3 Index by table


Third composite data type is Index by table This variable provide array-like access to rows.
create or replace procedure sp15
as
TYPE emp_type IS TABLE OF
employees%rowtype
index by binary_integer;
emp_array emp_type;
begin
for i in 101..104
loop
select *
into emp_array(i)
from employees
where employee_id = i;
end loop;
for i in emp_array.FIRST..emp_array.LAST

Focus Trainig Services, Pune Page 44


loop
dbms_output.put_line(emp_array(i).first_name||''||emp_array(i).
last_name);
end loop;
end;
/
show errors

OUTPUT

SQL> @sp15.sql
Procedure created.
No errors.

SQL> exec sp15


Neena Kochhar
Lex De Haan
Alexander Hunold
Bruce Ernst

PL/SQL procedure successfully completed.

Focus Trainig Services, Pune Page 45


Exercise:

1. Display employee name, salary, job_id and whos employee_id is 150 ?

2. Write pl/sql block to print employee full name, salary and manager full name when
employee_id is passed in. The out should be as follows: (By using %row type)

Employee Full name : Neena Kochhar


Salary :1700
Manager full name : Stephen king

3. The out put should be as follows : (by using records)

City No. of Employees Average salary


------------- ------------------------------------------- ------------------------------------------
London 5 5800

Focus Trainig Services, Pune Page 46


5.
ABOUT CURSORS
Objectives:
1) Overview of Implicit Cursors
2) Overview of Explicit Cursors
3) Explicit cursor attributes
4) Using Subqueries Instead of Explicit Cursors
5) Parameterized Cursors
6) SELECT FOR UPDATE CURSOR
7) Where current of clause

Cursor is a mechanism by which you can assign a name to a "select statement" and manipulate the
information within that SQL statement. PL/SQL uses two types of cursors: implicit and explicit.
PL/SQL declares a cursor implicitly for all SQL data manipulation statements, including queries that
return only one row. However, for queries that return more than one row, you must declare an
explicit cursor, use a cursorFOR loop, or use the BULK COLLECT clause.
While dealing with cursors, you may need to determine the status of your cursor. The following is a
list of the cursor attributes that you can use. You have already learned that you can include SQL
statements that return a single row in PL/SQL block. The data retrieved by the SQL statement should
be held in variables using the INTO clause.
The Oracle server allocates a private memory area called the context area for processing SQL
Statements. Information required for processing and information retrieved after processing is all
stored in this area. You have no control over this area because it is internally managed by the oracle
server.
A cursor is a pointer to the context area. However, this cursor is an implicit cursor and is
automatically managed by the Oracle server. When the executable block issues a SQL statement,
PL/SQL creates an implicit cursor.
There are two types of cursors:

Focus Trainig Services, Pune Page 47


5.1 Overview of Implicit Cursors
Implicit cursors are created and managed by the Oracle server. You do not have access to them.The
Oracle server creates such a cursor when it has to execute a SQL statement in the executable section
of PL/SQL block. SQL cursor attributes enables you to evaluate what happend when an implicit cursor
was last used.

1)SQL%ROWCOUNT
2)SQL%FOUND
3)SQL%NOTFOUND

 SQL%FOUND Attribute: Has a DML Statement Changed Rows?


Until a SQL data manipulation statement is executed, %FOUND yields NULL. Thereafter, %FOUND
yields TRUE if an INSERT, UPDATE, or DELETE statement affected one or more rows, or a SELECT INTO
statement returned one or more rows. Otherwise, %FOUND yields FALSE. In the following example,
you use %FOUND to insert a row if a delete succeeds:

DELETE FROM emp WHERE empno = my_empno;


IF SQL%FOUND THEN -- delete succeeded
INSERT INTO new_emp VALUES (my_empno, my_ename, ...);

 %NOTFOUND Attribute:

Has a DML Statement Failed to Change Rows?

%NOTFOUND is the logical opposite of %FOUND. %NOTFOUND yields TRUE if an INSERT, UPDATE, or
DELETE statement affected no rows, or a SELECT INTO statement returned no rows. Otherwise,
%NOTFOUND yields FALSE.

 %ROWCOUNT Attribute: How Many Rows Affected So Far?


%ROWCOUNT yields the number of rows affected by an INSERT, UPDATE, or DELETE statement, or
returned by a SELECT INTO statement. %ROWCOUNT yields 0 if an INSERT, UPDATE, or DELETE
statement affected no rows, o a SELECT INTO statement returned no rows. In the following example,
you use %ROWCOUNT to take action if more than ten rows have been deleted:

Focus Trainig Services, Pune Page 48


DELETE FROM emp WHERE ...
IF SQL%ROWCOUNT > 10 THEN -- more than 10 rows were deleted
...
Focus Training Services, Pune
END IF;

5.2 Overview of Explicit Cursors


The set of rows returned by a query can consist of zero, one, or multiple rows, depending on how
many rows meet your search criteria. When a query returns multiple rows, you can explicitly declare
a cursor to process the rows. Moreover, you can declare a cursor in the declarative part of any
PL/SQL block, subprogram, or package.
You can use explicit cursor to name a context area and to store processing information.As a
programmer you may want to retrieve multiple rows from a database table, have a pointer to each
row that is retrieved, and work on the rows one at a time.
In such case, you can declare cursors explicitly depending on your business requirements.Cursors
that are declared by programmers are called explicit cursors.
You declare explicit cursors in PL/SQL when you have a select statement that returns multiple rows.
You can process each row returned by the select statement.

5.2.1 Declaring a Cursor


Forward references are not allowed in PL/SQL. So, you must declare a cursor before referencing it in
other statements. When you declare a cursor, you name it and associate it with a specific query using
the syntax :

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


[RETURN return_type] IS select_statement;

For example, you might declare cursors named c1 and c2, as follows:

DECLARE
CURSOR c1 IS SELECT empno, ename, job, sal FROM emp
WHERE sal > 2000;
CURSOR c2 RETURN dept%ROWTYPE IS
SELECT * FROM dept WHERE deptno = 10;

Focus Trainig Services, Pune Page 49


5.2.2 Opening a Cursor
Opening the cursor executes the query and identifies the result set, which consists of all rows that
meet the query search criteria. For cursors declared using the FOR UPDATE clause, the OPEN
statement also locks those rows. An example of the OPEN statement follows:\

DECLARE
CURSOR c1 IS SELECT employee_id, job_id FROM employees WHERE
salary < 3000;
...
BEGIN
OPEN c1;
...
END;

Rows in the result set are not retrieved when the OPEN statement is executed. Rather, the FETCH
statement retrieves the rows.

5.2.3 Fetching with a Cursor


The FETCH statement retrieves the rows in the result set one at a time. Each fetch retrieves the
current row and then advances the cursor to the next row in the result set An Syntax follows:

FETCH [CURSOR NAME] INTO [LIST OF VARIABLES];

5.2.4 Closing a Cursor


The CLOSE statement disables the cursor, and the result set becomes undefined. Once a cursor is
closed, you can reopen it. Any other operation on a closed cursor raises the predefined exception
INVALID_CURSOR

CLOSE [CURSOR NAME]

*Note: Although it is possible to terminate the PL/SQL block without closing cursors, you should
make it a habit to close any cursor that you declared explicitly to free up resources.

Focus Trainig Services, Pune Page 50


5.3 Explicit cursor attributes
Obtain satus information about a cursor.
%ISOPEN - Boolean attribute evaluates to TRUE if the curosr is open
%FOUND - Boolean attribute evaluates to TRUE if the most recent fetch returns a row.
%NOTFOUND - Boolean attribute evaluates to TRUE if the most recent fetch does not returns
a row.
%ROWCOUNT - An interger value that represents number of row returned so far.
Example 1:
Declare
--declaration of cursor
cursor emp_cursor is select employee_id, last_name
from employees
where department_id=30;
empno employees.employee_id%type;
lname employees.last_name%type;
Begin
--opening the cursor
open emp_cursor;
--fetching data from the cursor
loop
fetch emp_cursor into empno, lname;
Exit when emp_cursor%notfound;
dbms_output.put_line(empno||' '||lname);
end loop;
--closing the cursor
close emp_cursor;
End;
/
set serveroutput on

Example2: Process the rows of the active set by fetching values into a PL/SQL record.
SQL>set serveroutput on
SQL>declare

Focus Trainig Services, Pune Page 51


--declaration of cursor
cursor emp_cursor is select employee_id, last_name
from employees
where department_id=30;
r1 emp_cursor%rowtype;
Begin
--opening the cursor
open emp_cursor;
--fetching data from the cursor
loop
fetch emp_cursor into r1;
exit when emp_cursor%notfound;
dbms_output.put_line(r1.employee_id||' '||r1.last_name);
end loop;
--closing the cursor
close emp_cursor;
end;
/
Show errors
Set serveroutput on

5.3 1 Using Cursor FOR Loops


The cursor FOR loop is a shortcut to process explicit cursors. It is shortcut because the cursor is
opened, a row is fetched once for each iteration in the loop, the loop exists when the last row is
processed and the cursor is closed automatically. The loop itself is terminated automatically at the
end of the iteration where the last row is fetched.
Example:
Declare
cursor c1 is select employee_id, salary from employees where
department_id=90;
Begin
for r1 in c1 loop
dbms_output.put_line(r1.employee_id||' '||r1.salary);
end loop;

Focus Trainig Services, Pune Page 52


End;
/

5.4 Using Subqueries Instead of Explicit Cursors


Example:
create or replace procedure sp16
As
Begin
for rec in (select last_name from employees where
department_id=20)
loop
dbms_output.put_line('Name: '||rec.last_name);
end loop;
end;
/

OUTPUT:
SQL> @sp16.sql
Procedure created.
No errors.
SQL> exec sp16
Name: Hartstein
Salary: 13000
Name: Fay
Salary: 6000

PL/SQL procedure successfully completed.

5.5 Parameterized Cursors


An explicit cursor can take parameters and return a data set for a specific parameter value. This
eliminates the need to define multiple cursors and hard-code a value in each cursor. In the following
code, the cursor example presented to illustrate parameterized cursors:

create or replace procedure sp17(deptno number,job varchar2)

Focus Trainig Services, Pune Page 53


--This Program shows
--How to pass parameters to cursor
as
cursor c1(l_deptno number,l_job varchar2) is
select employee_id,last_name
from employees
where department_id = l_deptno and job_id = l_job;
rec_c1 c1%rowtype;
--Declaration of cursor
Begin
for rec_c1 in c1(90,'AD_VP') loop
--Passing Paramenters to cursor
dbms_output.put_line('Depatment 90 '||' Job_id is AD_VP');
dbms_output.put_line('Employee ID: '||
to_char(rec_c1.employee_id));
dbms_output.put_line('Employee Name: '|| rec_c1.last_name);
dbms_output.put_line(‘------------------------’);
end loop;
open c1(deptno,job);
--Passing Paramenters to cursor
loop
fetch c1 into rec_c1;
exit when c1%notfound;
dbms_output.put_line(deptno||' Job id is '|| job);
dbms_output.put_line('Employee ID: '||
to_char(rec_c1.employee_id));
dbms_output.put_line('Employee Name: '|| rec_c1.last_name);
end loop;
close c1;
end;
/
show errors

OUTPUT:
SQL> @sp17.sql

Focus Trainig Services, Pune Page 54


Procedure created.
No errors.

SQL> exec sp17(60,'IT_PROG');


Depatment 80 Job id is SA_MAN
Employee ID: 101
Employee Name: Kochhar
------------------------
Depatment 80 Job id is SA_MAN
Employee ID: 102
Employee Name: De Haan
------------------------
60 Job id is IT_PROG
Employee ID: 103
Employee Name: Hunold
------------------------
60 Job id is IT_PROG
Employee ID: 104
Employee Name: Ernst

PL/SQL procedure successfully completed.

5.6 SELECT FOR UPDATE CURSOR


If there are multiple sessions for a single database, there is the possibility that the rows of a
particular table were updated after you opened your cursor. You see the updated data only when
you reopen the cursor. Therefore, it is better to have locks on the rows before you update or delete
rows. You can lock the rows with the FOR UPDATE clause in the cursor query. In other words,
 Use explicit locking to deny access to other sessions for the duration of transaction.
 Lock the rows before the update or delete.

Syntax:

select ....
from ....
for update [of column_reference] [NOWAIT | WAIT n];

Focus Trainig Services, Pune Page 55


 The SELECT... FOR UPDATE statement identifies the rows that are to be updated or deleted and then
locks each row in the result set. This is useful when you want to base an update on the existing
values in a row. In that case, you must make sure that the row is not changed by another session
before the update.
 The optional NOWAIT keyword tells the Oracle server not to wait if requested rows have been locked
by another user. Control is immediately returned to your program so that it can do other work before
trying again to acquire the lock. If you omit the NOWAIT keyword the oracle server waits until the
rows are available.
 You can use WAIT instead of NOWAIT, specify the number of seconds to wait, and determine
whether the rows are unlocked.
 If the rows are still locked after n seconds an error is returned.
 It is not mandatory for the FOR UPDATE OF clause to refer to a column, but it is recommended for
better readability and maintenance.
Example:
Declare
cursor c1 is select *
from empcopy
where department_id = 20 for update of salary nowait;

rec_c1 c1%rowtype;
l_new_sal number;

Begin

dbms_output.put_line(rpad('Employee',15)|| rpad('Old
Salary',15)|| rpad('New Salary',15));

open c1;

loop
fetch c1 into rec_c1;
exit when c1%notfound;
if rec_c1.salary < 7000 then
l_new_sal:= rec_c1.salary * 1.25;

Focus Trainig Services, Pune Page 56


update empcopy
set salary = l_new_sal
where employee_id = rec_c1.employee_id;
else

l_new_sal := rec_c1.salary * 1.15;


update empcopy
set salary = l_new_sal
where employee_id = rec_c1.employee_id;
end if;
bms_output.put_line(rpad(rec_c1.last_name,15)||
rpad(rec_c1.salary,15)|| rpad(l_new_sal,15));
end loop;
close c1;
end;
/
show errors

5.7 Where current of clause


Once you’ve defined a SELECT FOR UPDATE cursor, you use the WHERE CURRENT OF clause to
process the rows returned by it. You can use this clause in an UPDATE or DELETE statement. only
current row in cursor by defining 'where current of clause' It has the following syntax:
WHERE CURRENT of cursor_nam

Example:
create or replace procedure sp18
as
cursor c1 is
select employee_id,salary
from employees
where department_id = 20
for update of salary nowait;
l_new_sal number; rec_c1
c1%rowtype;
begin

Focus Trainig Services, Pune Page 57


dbms_output.put_line(rpad('Employee',10)|| rpad('Old
Salary',10)||rpad('New Salary',10));
open c1;
loop
fetch c1 into rec_c1;
exit when c1%notfound;

if rec_c1.salary < 7000 then


l_new_sal := rec_c1.salary * 1.25;
update employees set salary = l_new_sal
where current of c1;
else
l_new_sal := rec_c1.salary * 1.25;
update employees set salary =l_new_sal
where current of c1;
end if;
end loop;
close c1;
dbms_output.put_line(rpad(rec_c1.employee_id,10)||
rpad(rec_c1.salary,10)||rpad(l_new_sal,10));
end;
/
show errors

OUTPUT:

SQL> @sp18.sql
Procedure created.
No errors.

SQL> exec sp18


Employee Old SalaryNew Salary
202 11406.56 14258.2

PL/SQL procedure successfully completed.

Focus Trainig Services, Pune Page 58


Exercise:

1. Display the output as follows:

Department id employee_id
------------------------ --------------------------
10 3
20 2
30 1
40 6
------------------------------------------------------------------
Total : 11

2. Write a program that gives all employee in department 10 a 10% increase, Display a message
“How many Employees where evarded the increase?

3. Write PL/SQl Block that copies all departments to a table called dept_copy?

(It use while loop and Display how many rows were copied)).

4. To display top six employees with respect to the salaries ?

5. Display the output are as follows :

Total no. of rows Las_Name :


Total no. of rows Regio_name :
Total no. of rows City :

Focus Trainig Services, Pune Page 59


6.
HANDLING PL/SQL ERRORS
Objectives:
1) Overview of PL/SQL Error Handling
2) Advantages of PL/SQL Exceptions
3) Predefined PL/SQL Exceptions (Named System Exceptions)
4) Non-predefined exceptions(Unnamed System Exceptions)
5) Defining Your Own PL/SQL Exception
6) How PL/SQL Exceptions Propagate

Run-time errors arise from design faults, coding mistakes, hardware failures, and many other
sources. Although you cannot anticipate all possible errors, you can plan to handle certain kinds of
errors meaningful to your PL/SQL program. With PL/SQL, a mechanism called EXCEPTION HANDLING
lets you "bulletproof" your program so that it can continue operating in the presence of errors. An
exception is an error in PL/SQL that is raised during the execution of a block.
A block always terminates when PL/SQL raises an exception, but you can specify and exception
handler to perform final actions before the block ends.

6.1 Overview of PL/SQL Error Handling


In PL/SQL, a warning or error condition is called an exception. Exceptions can be internally defined
(by the run-time system) or user defined. Examples of internally defined exceptions include division
by zero and out of memory. Some common internal exceptions have predefined names, such as
ZERO_DIVIDE and STORAGE_ERROR. The other internal exceptions can be given names.
You can define exceptions of your own in the declarative part of any PL/SQL block, subprogram, or
package. For example, you might define an exception named insufficient_funds to flag overdrawn
bank accounts. Unlike internal exceptions, userdefined exceptions must be given names.
When an error occurs, an exception is raised. That is, normal execution stops and control transfers to
the exception-handling part of your PL/SQL block or subprogram. Internal exceptions are raised
implicitly (automatically) by the run- time system. Userdefined exceptions must be raised explicitly by
RAISE statements, which can also raise predefined exceptions.

Focus Trainig Services, Pune Page 60


Example of an exception:
Declare
lname varchar2(15);
Begin
select last_name into lname from employees where
first_name='John';
dbms_output.put_line(q'!John's last_name is :!'||lname);
End;
/

 There is no syntax error in above code, which means you must be able to successfully execute the
anonymous block.
 The select statement in the block retrieves the last_name of John. You see the following output when
you execute the code:

ERROR at line 1:
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at line 4

 The ORA-06512 error itself does not indicate the actual error. It normally indicates the line number at
which the oracle PL/SQL code has caused an error.
 There will be another main error occurred in your process and that error happened in the line
number as mentioned in ORA-06512 message description.
 Like for example, the first line of the error message like ORA-01422 may indicate the actual error that
occurred, while the second line of the error message (ie: ORA-06512) indicates that the error
occurred at which line number of the PLSQL code.
 The code does not work as expected. You expected the select statement to retrieve only one row;
however, it retrieves multiple rows.
 Such errors that occur at run time are called exceptions. When an exception occurs, the PL/SQL block
is terminated.
 You can handle such exceptions in your PL/SQL block.
 For exception handling, you include another optional section called the exception section. This
section begins with the keyword EXCEPTION.
 If present, this is last section in a PL/SQL block.

Focus Trainig Services, Pune Page 61


Declare
lname varchar2(15);
Begin
select last_name into lname from employees where
first_name='John';
dbms_output.put_line(q'!John's last_name is :!'||lname);
Exception
WHEN TOO_MANY_ROWS THEN
dbms_output.put_line('Your select statement retrieved multiple
rows. Consider using a cursor.');
End;
/
Show errors

The code is rewritten to handle the exception that occurred. The output of the code is:
Your select statement retrieved multiple rows. Consider using a
cursor.
PL/SQL prcedure successfully completed.

6.2 Advantages of PL/SQL Exceptions


Using exceptions for error handling has several advantages. Without exception handling, every time
you issue a command, you must check for execution errors

Error processing is not clearly separated from normal processing; nor is it robust. If you neglect to
code a check, the error goes undetected and is likely to cause other, seemingly unrelated errors.
With exceptions, you can handle errors conveniently without the need to code multiple checks.

Exceptions improve readability by letting you isolate error-handling routines. If the exception is ever
raised in that block (or any sub-block), you can be sure it will be handled.

There are 3 types of Exceptions.


1) Predefined exceptions
2) Non-predefined exceptions
3) User-defined Exceptions

Focus Trainig Services, Pune Page 62


6.3 Predefined PL/SQL Exceptions (Named System Exceptions)
System exceptions are automatically raised by Oracle, when a program violates a RDBMS rule.There
are some system exceptions which are raised frequently, so they are pre-defined and given a name in
Oracle which are known as Named System Exceptions.
For example : NO_DATA_FOUND and ZERO_DIVIDE are called Named System exceptions.
Named system exceptions are:
1) Not Declared explicitly,
2) Raised implicitly when a predefined Oracle error occurs,
3) caught by referencing the standard name within an exception-handling routine.
Sample of predefined exceptions:

Exception Oracle Error SQLCODE Value


ACCESS_INTO_NULL ORA-06530 -6530
COLLECTION_IS_NULL ORA-06592 -6592
CASE_NOT_FOUND FOUND ORA-06592 -6592 -6531
CURSOR_ALREADY_OPEN ORA-06511 -6511
DUP_VAL_ON_INDEX ORA-00001 -1
INVALID_CURSOR ORA-01001 -1001
INVALID_NUMBER ORA-01722 -1722
LOGIN_DENIED ORA-01017 -1017
NO_DATA_FOUND ORA-01403 +100
NOT_LOGGED_ON ORA-01012 -1012
PROGRAM_ERROR ORA-06501 -6501
ROWTYPE_MISMATCH ORA--6504 -6504
SELF_IS_NULL ORA-30625 -30625
STORAGE_ERROR ORA-06500 -6500
SUBSCRIPT_BEYOND_COUNT ORA-06533 -6533
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 -6532
SYS_INVALID_ROWID ORA-01410 -1410
TIMEOUT_ON_RESOURCE ORA-00051 -51
TOO_MANY_ROWS ORA-01422 -1422
VALUE_ERROR ORA-06502 -6502
ZERO_DIVIDE ORA-01476 -1476

Focus Trainig Services, Pune Page 63


Brief descriptions of the predefined exceptions follow:
Exception Raised when
ACCESS_INTO_NULL A program attempts to assign values to the
attributes of an uninitialized object.
CASE_NOT_FOUND None of the choices in the WHEN clauses of a
CASE statement is selected, and there is
no ELSE clause.
COLLECTION_IS_NULL A program attempts to apply collection methods
other than EXISTS to an uninitialized nested table
or varray, or the program attempts to assign
values to the elements of an uninitialized nested
table or varray.
CURSOR_ALREADY_OPEN A program attempts to open an already open
cursor. A cursor must be closed before it can be
reopened. A cursor FOR loop automatically opens
the cursor to which it refers, so your program
cannot open that cursor inside the loop.
DUP_VAL_ON_INDEX A program attempts to store duplicate values in a
database column that is constrained by a unique
index.
INVALID_CURSOR A program attempts a cursor operation that is
not allowed, such as closing an unopened cursor.
INVALID_NUMBER In a SQL statement, the conversion of a character
string into a number fails because the string does
not represent a valid number.(In procedural
statements, VALUE_ERROR is raised.) This
exception is also raised when the LIMIT- clause
expression in a bulk FETCH statement does not
evaluate to a positive number
LOGIN_DENIED A program attempts to log on to Oracle with an
invalid username or password.
NO_DATA_FOUND A SELECT INTO statement returns no rows, or

Focus Trainig Services, Pune Page 64


your program references a deleted element in a
nested table or an uninitialized element in an
index-by table. Because this exception is used
internally by some SQL functions to signal that
they are finished, you should not rely on this
exception being propagated if you raise it within
a function that is called as part of a query.
NOT_LOGGED_ON A program issues a database call without being
connected to Oracle.
PROGRAM_ERROR PL/SQL has an internal problem.
ROWTYPE_MISMATCH The host cursor variable and PL/SQL cursor
variable involved in an assignment have
incompatible return types. For example, when an
open host cursor variable is passed to a stored
subprogram, the return types of the actual and
formal parameters must be compatible.
SELF_IS_NULL A program attempts to call a MEMBER method,
but the instance of the object type has not been
initialized. The built-in parameter SELF points to
the object, and is always the first parameter
passed to a MEMBER method.
STORAGE_ERROR PL/SQL runs out of memory or memory has been
corrupted.
SUBSCRIPT_BEYOND_COUNT A program references a nested table or varray
element using an index number larger than the
number of elements in the collection
SUBSCRIPT_OUTSIDE_LIMIT A program references a nested table or varray
element using an index number (-1 for example)
that is outside the legal range.
SYS_INVALID_ROWID The conversion of a character string into a
universal rowid fails because the character string
does not represent a valid rowed
TIMEOUT_ON_RESOURCE A time-out occurs while Oracle is waiting for a

Focus Trainig Services, Pune Page 65


resource.
TOO_MANY_ROWS A SELECT INTO statement returns more than one
row.
VALUE_ERROR An arithmetic, conversion, truncation, or
sizeconstraint error occurs. For example, when
your program selects a column value into a
character variable, if the value is longer than the
declared length of the variable, PL/SQL aborts
the assignment and raises VALUE_ERROR. In
procedural statements, VALUE_ERROR is raised if
the conversion of a character string into a
number fails. (In SQL statements,
INVALID_NUMBER is raised.)
ZERO_DIVIDE A program attempts to divide a number by zero.

6.4 Non-predefined exceptions(Unnamed System Exceptions)


Those system exception for which oracle does not provide a name is known as unamed system
exception. These exception do not occur frequently. These Exceptions have a code and an associated
message.
There are two ways to handle unnamed sysyem exceptions:
1. By using the WHEN OTHERS exception handler, or
2. By associating the exception code to a name and using it as a named exception

 Non-predefined exceptions are similar to predefined exceptions; however, they are not defined as
PL/SQL exceptions in the Oracle server.
 They are standard Oracle errors. You create exceptions with standared oracle errors by using the
PRAGMA EXCEPTION_INIT function. Such exceptions are called non-predefined exceptions.
 You can trap a non-predefined Oracle server error by declaraing it first. The declared exception is
raised implicitly.
 In PL/SQL, PRAGMA EXCEPTION_INIT tells the complier to associate an exception name with an
Oracle error number. That enables you to refer to any internal exception by name and to write a
specific handler for it.

Focus Trainig Services, Pune Page 66


Example:
Step 1:
SQL> desc departments;

Name Null? Type


---------------- ---------- ------------
DEPARTMENT_ID NOT NULL NUMBER(4)
DEPARTMENT_NAME NOT NULL VARCHAR2(30)
MANAGER_ID NUMBER(6)
LOCATION_ID NUMBER(4)

Step 2:
SQL> begin
2 insert into departments (department_id, department_name)
values(280,null);
3 end;
4 /

OUTPUT:
Begin
*
ERROR at line 1:
ORA-01400: cannot insert NULL into
("VIVEK"."DEPARTMENTS"."DEPARTMENT_NAME")
ORA-06512: at line 2

Step 3:
SQL> set serveroutput on
SQL> declare
insert_excep EXCEPTION; -- declare the name of exception
PRAGMA EXCEPTION_INIT(insert_excep,-01400); --associate the
declared exception with the standard oracle server error number
begin
insert into departments(department_id, department_name)

Focus Trainig Services, Pune Page 67


values(280,null);
exception
when insert_excep then --caught by referencing the declared
exception
dbms_output.put_line('Insert operation failed');
dbms_output.put_line(SQLERRM);
end;
/

OUTPUT:
Insert operation failed
ORA-01400: cannot insert NULL into
("VIVEK"."DEPARTMENTS"."DEPARTMENT_NAME")

PL/SQL procedure successfully completed.

6.4.1Functions for trapping exceptions


When an exception occurs, you can identify the associated error code or error message by using two
functions. Based on the values of the code or the message, you can decide which subsequent actions
to take.
SQLCODE - Returns the numeric value for error code
(You can assign it to a NUMBER variable).
SQLERRM - Returns the character data containing the message associated with
the error number.

6.5 Defining Your Own PL/SQL Exception


Apart from sytem exceptions we can explicity define exceptions based on business rules. These are
known as user-defined exceptions.
Steps to be followed to use user-defined exceptions:
 They should be explicitly declared in the declaration section.
 They should be explicitly raised in the Execution Section.
 They should be handled by referencing the user-defined exception name in the exception section.

Focus Trainig Services, Pune Page 68


6.5.1 Declaring PL/SQL Exceptions
Exceptions can be declared only in the declarative part of a PL/SQL block, subprogram, or package.
You declare an exception by introducing its name, followed by the keyword EXCEPTION. In the
following example, you declare an exception named past_due:

DECLARE
past_due EXCEPTION;

Example:
SQL> declare
2 invalid_department EXCEPTION; --declare the name of the
exception
3 begin
4 update deptcopy
5 set department_name='Sports'
6 where department_id=999;
7 if sql%notfound then
8 raise invalid_department; --raise the exception explicitly
9 end if;
10 exception
11 when invalid_department then -- handle the raised exception
12 dbms_output.put_line('No such department id');
13 end;
14 /

OUTPUT:
No such department id

PL/SQL procedure successfully completed.

6.5.2 Associating a PL/SQL Exception with a Number: Pragma EXCEPTION_INIT


To handle error conditions (typically ORA- messages) that have no predefined name, you must use
the OTHERS handler or the pragma EXCEPTION_INIT. A pragma is a compiler directive that is

Focus Trainig Services, Pune Page 69


processed at compile time, not at run time. In PL/SQL, the pragma EXCEPTION_INIT tells the compiler
to associate an exception name with an Oracle error number. That lets you refer to any internal
exception by name and to write a specific handler for it. When you see an error stack, or sequence of
error messages, the one on top is the one that you can trap and handle You code the pragma
EXCEPTION_INIT in the declarative part of a PL/SQL block,subprogram, or package using the syntax

PRAGMA EXCEPTION_INIT(exception_name, -Oracle_error_number);

where exception_name is the name of a previously declared exception and the number is a negative
value corresponding to an ORA- error number. The pragma must appear somewhere after the
exception declaration in the same declarative section, as shown in the following example:

DECLARE
deadlock_detected EXCEPTION;
PRAGMA EXCEPTION_INIT(deadlock_detected, -60);
BEGIN
-- Some operation that causes an ORA-00060 error

EXCEPTION
WHEN deadlock_detected THEN
--handle the error
END;

6.5.3 Defining Your Own Error Messages: Procedure

RAISE_APPLICATION_ERROR()
 RAISE_APPLICATION_ERROR is a built-in procedure in oracle which is used to display the user-defined
error messages along with the error number whose range is in between -20000 and -20999.
 Whenever a message is displayed using RAISE_APPLICATION_ERROR, all previous transactions which
are not committed within the PL/SQL Block are rolled back automatically (i.e. change due to INSERT,
UPDATE, or DELETE statements).
RAISE_APPLICATION_ERROR raises an exception but does not handle it.
RAISE_APPLICATION_ERROR is used for the following reasons,
a) to create a unique id for an user-defined exception.
b) to make the user-defined exception look like an Oracle error.
Focus Trainig Services, Pune Page 70
The General Syntax to use this procedure is:
RAISE_APPLICATION_ERROR (error_number, error_message);

 The Error number must be between -20000 and -20999


 The Error_message is the message you want to display when the error occurs

example:
SQL> begin
2 update deptcopy
3 set department_name='Sports'
4 where department_id=999;
5 if sql%notfound then
6 raise_application_error(-20145,'No such department id');
7 end if;
8 end;
9 /

OUTPUT:
begin
ERROR at line 1:
ORA-20145: No such department id
ORA-06512: at line 6

*NOTE:-The RAISE_APPLICATION_ERROR procedure can be used in either executable section or


exception section of a PL/SQL program*

6.6 How PL/SQL Exceptions Propagate


When a subblock handles an exception, it terminates normally. Control resumes in the enclosing
block immediately after the subblock's END statement. However, if a PL/SQL raises an exception and
the current block does not have a handler for that exception,the exception propagates to successive
enclosing blocks until it finds a handler. If none of these blocks handle the exception, an unhanled
exception in the host environment results. When the exception propagates to an enclosing block, the
remaining executable actions in that block are bypassed.

Focus Trainig Services, Pune Page 71


An exception can propagate beyond its scope, that is, beyond the block in which it was declared
Example:

Focus Trainig Services, Pune Page 72


SQL> begin
declare
empid number;
begin
select employee_id into empid from employees where
department_id=89;
dbms_output.put_line(empid);
end;
dbms_output.put_line('Hi this vivek');
exception
when no_data_found then
dbms_output.put_line('no data found exception raised');
end;
/

OUTPUT:
no data found exception raised

PL/SQL procedure successfully completed.

Focus Trainig Services, Pune Page 73


Exercise:

1. Can the PL/SQL block process more than one exception at a time?
2. _________ function is used to get error message of the most recent error.
3. How do you associate an Oracle error with a user-defined error.
4. When UPDATE command could not update any rows then which of the following will happen?
a.NO_DATA_FOUND exception occurs
b.INVALID_UPDATE exception occurs
c.No exception is raised
5. When an exception is not handled in the current block
a. It results in error and terminates the block
b. It is propagated to outer block
c. It is ignored.

Focus Trainig Services, Pune Page 74


7.
SUBPROGRAMS (PROCEDURES &
FUNCTIONS)
Objectives:

1) Understanding PL/SQL Procedures


2) Understanding PL/SQL Functions
3) Invoker's Rights versus Definer's Rights (AUTHID Clause)
4) Advantages of Invoker's Rights

Anonymous blocks are unnamed executable PL/SQL blocks. Because they are unnamed they can be
neither use nor stored for later use.Subprograms are named PL/SQL blocks that can take parameters
and be invoked.PL/SQL has two types of subprograms calledProcedures and functions are named
PL/SQL blocks. They are also known as subprograms. These subprograms are compiled and stored in
the database.The block structure of the subprograms is similar to the structure of anonymous blocks.

A stored subprogram is a named PL/SQL block that's stored in the database. PL/SQL 11g/12c supports
three types of stored subprograms:
 Procedures
 Functions
 Packages

7.1 Understanding PL/SQL Procedures


A procedure is a subprogram that performs a specific action. You write procedures using the
syntax:\
CREATE [OR REPLACE] PROCEDURE <procedure_name>
[ (parameter1 [mode] datatype1,
parameter2 [mode] datatype2,....) ]
IS | AS
local_variable declaration]

Focus Trainig Services, Pune Page 75


BEGIN
executable_section

[EXCEPTION
exception_section]
END [procedure_name];

In the above syntax:


OR REPLACE- Specify OR REPLACE to re-create the procedure if it already exists. Use this
clause to change the definition of an existing procedure without dropping, re-creating.
 procedure_name- Specify the name of the procedure to be created. The optional parameter list
contains name, mode and datatypes of the parameters.
 parameter1- represents the name of a parameter.
 Parameter2- represents the name of a parameter
 mode - Parameters are subject to one of the three parameter-passing modes: IN, OUT or IN OUT.
 IN represents that value will be passed from outside and
 OUT represents that this parameter will be used to return a value outside of the procedure.
 Datatype - represents the parameter data type without any precision.

Q. What are Parameters?


Parmeters are used to pass or communicate date between the caller and subprogram. OR
Parameters are used to transfer data values to and from the calling environment and the
procedure( or subprogram). Parameters are declared in the subprogram header, after the
name and before the declaration section for local variables.

7.1.1 How to create stored procedure:


1. Save the content of the procedure raise_salary in a file
e.g :- raise_salary.sql.
2. Log into to SQL*PLUS session and type
SQL> @ raise_salary.sql.
3. In the case of compilation errors, you'll see the message Warning: Procedure created with
compilation errors.You can see the corresponding errors by using the command
SQL> show errors

Focus Trainig Services, Pune Page 76


4. In the case of successful compilation, you'll see the message Procedure created successfully.
5. This will create an object of type PROCEDURE named raise_salary in oracle database. You can call
it from a PL/SQL block as follows, once you've created the raise_salary procedure

7.1.2 Parameters modes


Parameters are assign to one of the three parameter passing modes: IN, OUT or IN OUT.

 IN
An IN parameter passes a constant value from the calling environment into the procedure. The IN
mode is the default if no mode is specified.IN parameters are passed as read-only values from the
calling environment into the procedure. Attempts to change the value of an IN parameter in called
subprogram result in compile-time error.

 OUT
The OUT parameter passes a value from procedure to the calling environment. The OUT parameter
can be assigned values only in the body of the procedure in which they are declared. Make sure that
the data type for the actual parameter variables used to retrieve values from OUT parameters has a
size sufficient to hold the data values being returned.

 IN OUT
An IN OUT parameter passes a value from the calling environment to the procedure and a possibly
different value from the procedure back to the calling environment using the same parameter.

Example using IN parameter:


create or replace procedure sp19(id in empcopy.employee_id%type,
precent in number)
Is
Begin
update empcopy
set salary=salary+(salary*percent)/100
where employee_id=id;
end raise_salary;
/
Show errors

Focus Trainig Services, Pune Page 77


Set serveroutput ON

Compile Of file
SQL> @<FILE_NAME>

Execute sp19(176,10); --calling the procedure


SQL> Exec sp19(176,10)

Example using OUT parameter:


Step1:-
create or replace procedure sp20(id in empcopy.employee_id%type, ename out
empcopy.last_name%type, esal out empcopy.salary%type)
is
begin
select last_name, salary into ename, esal
from empcopy
where employee_id=id;
end query_emp;
/
Show errors
Set serveroutput ON

Step2:-
declare
emp_name empcopy.last_name%type;
emp_sal empcopy.salary%type;
begin
query_emp(171,emp_name,emp_sal); --calling the procedure
dbms_output.put_line(emp_name||' '||emp_sal);
end;
/
Show errors
Set serveroutput ON

Focus Trainig Services, Pune Page 78


Example using IN OUT parameter:
Step1:
create or replace procedure sp21(citycountryname in out varchar2)
As
Begin
select country_name into citycountryname
from countries
join locations
using(country_id)
where city=citycountryname;
End;
/
Show errors
Set serveroutput on

Step2:
SQL> @ sp21
You have created database object
Procedure created.

Step3: We use Anonymous Block


SQL> declare
ccname varchar2(30):='Toronto';
begin
proc789(ccname);
dbms_output.put_line(‘The City Name : - ‘ ||ccname);
end;
/

OUTPUT:
The City Name :- Canada
PL/SQL procedure successfully completed.

7.1.3 Invoking Procedures


You can invoke or call procedures by

Focus Trainig Services, Pune Page 79


 Using EXECUTE keyword
 Using anonymous blocks
 Using another procedure

Example:
Create or replace procedure sp22(did number)
as
dname varchar2(40);
begin
select department_name into dname from departments where
department_id=did;
dbms_output.put_line(dname);
end;
/

SQL> @ sp22

SQL> execute sp22(10);


-------OR--------
SQL>begin
proc123(10);
end;
/

7.1.4 Formal and Actual parameters


 Formal parameters are local variables that are declared in the parameter list of subprogram
specification.
 Actual parameters can be literal values, variables and expressions that are provided in the parameter
list of a called subprogram
 The formal and actual parameters should be of compatible data types.

Focus Trainig Services, Pune Page 80


7.1.5 Methods of passing parameters
 Positional : Lists the actual parameter values in the order in which the formal parameters are
declared.
 Named : Lists the actual values in random order and uses the association operator to associate each
actual parameter with its formal parameter by name.
The PL/SQL association operator is =>.
 Combination: Lists the first parameter values by their position and the remainder by using the
special syntax of the named method.
Example:
create or replace proceduresp23(dname
departments.department_name%type, mgrid number, locid number)
As
Begin
insert into deptcopy values(seq1.nextval,dname,mgrid,locid);
End add_dept;
/
Show errors
Set serveroutput on

passing by positional notation:


execute sp23('Training',103,1800);

passing by named notation:


Execute sp23(locid=>1900,dname=>'Sports',mgrid=>108);

passing by combination
execute sp23('Transport',locid=>1700,mgrid=>100);

7.1.6 Using the DEFAULT option for parameters


When default values are assigned to formal parameters, you can call the procedure without
supplying an actual parameter value for the parameter. Thus you can pass different number of actual
parameters to a subprogram, either by accepting or by overriding the default values as required.

Focus Trainig Services, Pune Page 81


NOTE:-You can not assign default values to OUT and IN OUT parameters.You can not skip providing
an actual parameter if there is no default value provided for formal parameter.

There are two ways of assigning a default value to an IN parameter:


1) The assignment operator(:=)
2) The DEFAULT option.
Example:
Step1:
create or replace procedure sp24(dname departments.department_name%type := 'Unknown', locid
number default 1800)
as
begin
nsert into deptcopy values(seq1.nextval,dname,null,locid);
end add_dept1;
/

Step2:
OUTPUT:
SQL> execute sp24;
------OR------
SQL> execute sp24('Testing',1700);
------OR------
SQL>execute sp24(locid=>1900);

7.1.7 Viewing Procedures in the Data Dictionary


The source code for PL/SQL subprograms is stored in the data dictionary tables. The source code is
accessible to PL/SQL procedures that are successfully or unsuccessfully compiled. To view the PL/SQL
source code stored in the data dictionary, execute a SELECT statement on the following tables:
 The USER_SOURCE table to display PL/SQL code that you own.

Focus Trainig Services, Pune Page 82


 The ALL_SOURCE table to display PL/SQL code to which you have been granted the EXECUTE privilege
by the owner of that subprogram code.

Example:
SQL> SELECT text
FROM user_source
WHERE name='RAISE_SALARY' and type='PROCEDURE'
ORDER BY line;

 list all procedures within your schema.


OR
SQL> select object_name, object_type, created from user_objects
where object_type='PROCEDURE';

7.1.8 Removing procedures


The DROP PROCEDURE statement drops a standalone stored procedure from the database.
Syntax:

DROP PROCEDURE procedure_name;

Example:
SQL> DROP PROCEDURE raise_salary;

7.2 Understanding PL/SQL Functions


Function is named PL/SQL block that can accept parameters, be invoked, and returns a value. A
function must retrun a value to the calling environment, whereas a procedure returns zero or more
values to its calling environment.
Like procedure a function has a header, a declarative section, an executable section and an optional
exception handling section. A function must have a RETURN clause in the header and at least one
RETURN statement in the executable section. Syntax to create a functions in Oracle is:

Focus Trainig Services, Pune Page 83


CREATE [OR REPLACE] function function_name
parameter2 [mode] datatype2,....) ]
RETURN datatype
IS | AS
[local_variable declaration]
BEGIN
{executable_section

RETURN expression;}

[EXCEPTION
exception_section]

END [function_name];
/

Example:

Create or replace function get_sal(id employees.employee_id%type)


return number

As
sal number;
Begin
select salary into sal
from employees
where employee_id=id;
return sal;
End;
/

** Once the function is created it can be invoked in the following ways**

Focus Trainig Services, Pune Page 84


7.2.1.1 Invoke the function from plsql block.
SQL>set serveroutput on
SQL>declare
empsal number;
begin
empsal:=get_sal(108);
dbms_output.put_line(empsal);
end;
/

7.2.1.2 Invoke the function as a parameter value

execute dbms_output.put_line(get_sal(108));

7.2.1.3 Using a host or bind variable

variable empsal number;


execute :empsal:=get_sal(108);
print empsal;

7.2.1.4 As an expression in a SQL statement

SQL> select employee_id, get_sal(employee_id) from employees;

7.2.2 Viewing Functions in the Data Dictionary


The source code for PL/SQL subprograms is stored in the data dictionary tables.
To view the PL/SQL source code stored in the data dictionary, execute a SELECT statement on the
following tables:
 The USER_SOURCE table to display PL/SQL code that you own.
 The ALL_SOURCE table to display PL/SQL code to which you have been granted the EXECUTE privilege
by the owner of that subprogram code.

Focus Trainig Services, Pune Page 85


Example:
SELECT text
FROM user_source
WHERE name='RAISE_SALARY' and type='FUNCTION'
ORDER BY line;

7.2.3 list all functions within your schema

SQL> select object_name, object_type, created from user_objects where object_type='FUNCTION';

7.2.4 Removing functions


The DROP FUNCTIONS statement drops a standalone stored procedure from the database.
Syntax:
DROP FUNCTION function_name;

Example:
SQL> DROP FUNCTION raise_salary;

7.3 Invoker's Rights versus Definer's Rights (AUTHID Clause)


Definer's Rights Model –
All programs executed with the privileges of the user who created the subprogram. This is known as
the definer's rights model, which:
 Allows a caller of the program the privilege to execute the procedure, but no privileges on the
underlying objects that the procedure accesses.
 Requires the owner to have all necessary object privileges for the objects that procedure
references.
 For example,
if user Scott creates a PL/SQL subprogram get_employees that is subsequently invoked by Sarah,
then get_employees procedure runs with the privileges of the definer Scott.

Focus Trainig Services, Pune Page 86


Invoker's Rights Model -
In the invoker's rights model, programs are executed with the privileges of the calling user. A user of
a procedure running with invoker's rights requires privileges on the underlying objects that the
procedure references.
For example,
if Scott's PL/SQL subprogram get_employees is invoked by Sarah, the get_employees procedure runs
with the privileges of the invoker Sarah. Note that to enable code to run with Invoker rights, the
AUTHID clause with the current_user option must be used before the IS or AS keyword in the
subprogram header to indicate that the subprogram executes with the privileges of CURRENT_USER.

7.3.1 Advantages of Invoker's Rights


 Invoker's rights subprograms let you reuse code and centralize application logic. They are especially
useful in applications that store data using identical tables in different schemas. All the schemas in
one instance can call procedures owned by a central schema.
 Consider a company that uses a stored procedure to analyze sales. If the company has several
schemas, each with a similar SALES table, normally it would also need several copies of the stored
procedure, one in each schema.
 To solve the problem, the company installs an invoker's rights version of the stored procedure in a
central schema. Now, all the other schemas can call the same procedure, which queries the
appropriate to SALES table in each case.
Example Invoker's Rights With a Procedure

Create OR REPLACE PROCEDURE sp26( v_deptno NUMBER, v_dname


VARCHAR2,v_mgr NUMBER,v_loc NUMBER)
AUTHID CURRENT_USER
AS
BEGIN
INSERT INTO departments VALUES (v_deptno, v_dname, v_mgr,
v_loc);
END;

Focus Trainig Services, Pune Page 87


Exercise:
1. What are the restrictions on functions that are called within SQL statements?
2. How can the parameter list for a function or procedure be displayed?
3. What happens if an exception is unhandled within a procedure?

Focus Trainig Services, Pune Page 88


8.
PL/SQL PACKAGES
Objective’s:

1) What Is a PL/SQL Package?


2) Viewing packages in the Data Dictionary
3) Guidelines for writing packages
4) Advantages of using Packages
5) Removing Packages
6) Overloading Packaged Subprograms.

8.1 What Is a PL/SQL Package?


A Package is a schema object that groups logically related PL/SQL types, variables, constants,
subprograms, cursors, and exceptions into one container. For example, a Human Resources package
can contain employees hiring and firing procedures, commission and bonus functions.
A package usually consists of two parts stored separately in the database:
 A specification
 A body(optional)

The package specification, which declares the public items that can be referenced from outside the
package. You can think of the package specification as the application programming interface (API).
The package body defines its own subprograms and must fully implement subprograms declared in
the specification part. The package may also define PL/SQL constructs, such as types, variables,
constants, exceptions and cursors.

Public components are declared in the package specification. The specification defines a public
application programming interface for users of package features and functionality- that is, public
components can be referenced from any oracle server environment that is external to the package.
Private components are placed in the package body and can be referenced only by other constructs
within the same package body.

Focus Trainig Services, Pune Page 89


Note: The oracle server stores the specification and body of a package separately. This enables you to
change the implementation of a program construct in the
package body without invalidating other schema objects that call or reference the program
construct.

A package specification can exist without a package body- that is when the package specification
does not declare subprograms, a body is not required. However, a package body can not exist
without a package specification.

8.1.1 Creating the package specification


syntax:
CREATE [OR REPLACE] PACKAGE package_name
IS | AS
variable declaration
subprogram specifications
END [package_name];

Note: The package specification should contain procedure and function headings terminated by a
semicolon, without the IS (or AS) keyword and its PL/SQL block.
The implementation of procedure or function that is declared in a package specification is done in
the package body.
Example:
create or replace package calculation
is
procedure addition(a number, b number);
procedure substraction(a number, b number);
procedure multiplication(a number, b number);
procedure division(a number, b number);
end calculation;
/

Focus Trainig Services, Pune Page 90


OUTPUT:
SQL> @ calculation.sql
Package created.

8.1.2 Creating the package body


Syntax:
CREATE [OR REPALCE] PACKAGE BODY package_name
IS | AS
private variable decarations
subprogram bodies
BEGIN [initialization statements] -- is an optional block of code that executes when the package is
first referenced.
END [package_name];
/

Note: When creating a package body, perform following steps

 Specify the OR REPLACE option to overwrite an existing package body. Define the subprograms in an
appropriate order. The basic principle is that you must declare a variable or subprogram before it can
be referenced by other
 components in the same package body. It is common to see all private variables and subprograms
defined first and the public subprograms defined last in the package body.
 Complete the implementation for all procedures or functions declared in the package specification
within the package body.

Example:
create or replace package body calculation
as
procedure addition(a number, b number)
as
begin
dbms_output.put_line('the addition:='||(a+b));
end;

Focus Trainig Services, Pune Page 91


procedure substraction(a number, b number)
as
begin
dbms_output.put_line('the substraction:='||(a-b));
end;

procedure multiplication(a number, b number)


as
begin
dbms_output.put_line('the multiplication:='||(a*b));
end;
procedure division(a number, b number)
as
begin
dbms_output.put_line('the division:='||(a/b));
end;
begin
dbms_output.put_line('The package has called for the first
time in this session');
end calculation;
/

OUTPUT:
SQL> @calculation.sql
Package body created.
SQL> execute calculation.addition(5,8); --calling addition procedure
of package calculation

A subprogram must be declared before you can call it.


Coding standards often require that subprograms be kept in alphabetical sequence to make them
easy to find. The solution in this case is to use forward declarations provided in PL/SQL.
A forward declarations enables you to declare the heading of a subprogram, that is the subprogram
specification terminated by a semicolon.

Focus Trainig Services, Pune Page 92


8.2 Viewing packages in the Data Dictionary
The source code for PL/SQL packages is maintained and viewable through the USER_SOURCE and
ALL_SOURCE tables in the data dictionary.

8.2.1 To view the package specification use:


SELECT text
FROM user_source
WHERE name='PACKEMP' and type='PACKAGE';

8.2.2 To view the package body use:


SQL>SELECT text
FROM user_source
WHERE name='PACKEMP' and type='PACKAGE BODY';

8.2.3 list all packages within your schema


SQL> select object_name, object_type, created from user_objects
where object_type='PACKAGE';

8.3 Guidelines for writing packages

 Construct packages for general use.


 Package specification reflect the design of your application, so define them before defining package
bodies. The package specification should contain only those constructs that must be visible to the
users of the package.
 Changes to the package body do not require recompilation of dependent constructs, whereas
changes to the package specification require recompilation of every stored subprogram that
references the package. To reduce the need for recompiling when code is changed, place as few
constructs as possible in a package specification.
 Package itself cannot be called, parameterized or nested. After writing and compiling, the contents
can be shared with many applictions.

Focus Trainig Services, Pune Page 93


8.4 Advantages of using Packages

 Modularity and ease of maintenance: You encapsulate logically related pragramming structures in
named module. Each package is easy to understand and the interface between packages is simple,
clear and well defined.
 Hiding information: You decide which constructs are public (visible and accessible) and which are
private(hidden and inaccessible). Declarations in the package specification are visible and accessible
to applications. The package body hides the definition of private constructs.
 Better performance: When you call a packaged subprogram the first time, the entire package is
loaded into memory. Later calls to related subprograms in the package therefore require no further
disk I/O.
 Overloading: With packages, you can overload procedures and functions, which means you can
create multiple subprograms with the same name in the same package, each taking parameters of
different number or data type.

8.5 Removing Packages

To remove whole package(specification and body) use following syntax:

DROP PACKAGE package_name;

You can remove only package body and retain the package specification using following syntax:
DROP PACKAGE BODY package_name;

Example:
Step1:
SQL>create table emp(empno NUMBER,
empname VARCHAR2(20),
jobid VARCHAR2(20),
hdate DATE,
sal NUMBER,
comm NUMBER);
SQL>create sequence empno_seq;
SQL>create table salgrade(grade char, losal number, hisal number);

Focus Trainig Services, Pune Page 94


SQL>insert into salgrade values('A',20000,40000);
SQL>insert into salgrade values('B',10000,19999);
SQL>insert into salgrade values('C',1000,9999);

Step2:
CREATE OR REPLACE PACKAGE emp_actions
AS
/* Declare externally callable subprograms. */

PROCEDURE hire_employee (ename VARCHAR2, job VARCHAR2, esal


NUMBER, comm NUMBER);
PROCEDURE fire_employee (emp_id NUMBER);
PROCEDURE raise_salary (emp_id NUMBER, grade CHAR, amount
NUMBER);

END emp_actions;

Step3:
CREATE OR REPLACE PACKAGE BODY emp_actions
AS
PROCEDURE hire_employee (ename VARCHAR2, job VARCHAR2, esal
NUMBER, comm NUMBER)
AS
new_empno NUMBER;
BEGIN
SELECT empno_seq.NEXTVAL INTO new_empno FROM dual;
INSERT INTO emp VALUES (new_empno, ename, job,SYSDATE,
esal, comm);
DBMS_OUTPUT.PUT_LINE('employee inserted successfully');

END hire_employee;

PROCEDURE fire_employee (emp_id NUMBER)

Focus Trainig Services, Pune Page 95


AS

BEGIN
DELETE FROM emp WHERE empno = emp_id;
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE('employee '||emp_id||' deleted
successfully');
ELSE
DBMS_OUTPUT.PUT_LINE('invalid employee');
END IF;
END fire_employee;
/* Define local function, available only inside package. */
FUNCTION sal_ok (rank CHAR, salary NUMBER)
RETURN BOOLEAN
AS
min_sal NUMBER;
max_sal NUMBER;
BEGIN
SELECT losal, hisal INTO min_sal, max_sal
FROM salgrade
WHERE grade = upper(rank);
RETURN (salary >= min_sal) AND (salary <= max_sal);
END sal_ok;
PROCEDURE raise_salary (emp_id NUMBER, grade CHAR, amount
NUMBER)
AS
salary NUMBER;
BEGIN
SELECT sal INTO salary
FROM emp
WHERE empno = emp_id;
IF sal_ok(grade, salary + amount) THEN
UPDATE emp
SET sal = sal + amount
WHERE empno = emp_id;
DBMS_OUTPUT.PUT_LINE('salary of employee'||emp_id||'

Focus Trainig Services, Pune Page 96


is updated successfully');
ELSE
DBMS_OUTPUT.PUT_LINE('invalid salary');
END IF;
END raise_salary;
END emp_actions;
/

Once the above package is created you can do following operations-


 insert record into table emp
SQL>exec emp_actions.hire_employee('vivek','IT',15808,0.2);
SQL>exec emp_actions.hire_employee('maddy','hr',18978,0.5);
SQL>commit;

 check the inserted data

SQL>select * from emp_actions;

 check the salgrade table


SQL>select * from salgrade;

 lets change the salary


SQL>exec emp_actions.raise_salary(2,'A',5000);
SQL>commit;

 check the salary


SQL>select * from emp;

 lets remove the employee vivek from emp table


SQL>exec emp_actions.fire_employee(1);
SQL>select * from emp;

8.6 Overloading Packaged Subprograms

8.6.1 The overloading feature in PL/SQL:


 Enables you to create two or more subprograms with same name

Focus Trainig Services, Pune Page 97


 Requires that the subprogams's formal parameters differ in number, order or data type family.

Note:- Overloading can be done with package subprograms but not with stad-alone subprograms.
Step1:
CREATE OR REPLACE PACKAGE emp_actions AS
/* Declare externally callable subprograms. */
PROCEDURE hire_fire_employee (ename VARCHAR2, job VARCHAR2,
esal NUMBER, comm NUMBER);
PROCEDURE hire_fire_employee (emp_id NUMBER);
PROCEDURE raise_salary (emp_id NUMBER, grade CHAR, amount
NUMBER);

END emp_actions;

Step2:
CREATE OR REPLACE PACKAGE BODY emp_actions
AS
PROCEDURE hire_fire_employee (ename VARCHAR2,job VARCHAR2,
esal NUMBER, comm NUMBER)
AS
new_empno NUMBER;
BEGIN
SELECT empno_seq.NEXTVAL INTO new_empno FROM dual;
INSERT INTO emp VALUES (new_empno, ename, job,SYSDATE,
esal, comm);
DBMS_OUTPUT.PUT_LINE('employee inserted successfully');
END hire_fire_employee;

PROCEDURE hire_fire_employee (emp_id NUMBER)


AS

BEGIN
DELETE FROM emp WHERE empno = emp_id;

Focus Trainig Services, Pune Page 98


IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE('employee '||emp_id||' deleted
successfully');
ELSE
DBMS_OUTPUT.PUT_LINE('invalid employee');
END IF;
END hire_fire_employee;

/* Define local function, available only inside package. */


FUNCTION sal_ok (rank CHAR, salary NUMBER) RETURN BOOLEAN
AS
min_sal NUMBER;
max_sal NUMBER;
BEGIN
SELECT losal, hisal INTO min_sal, max_sal
FROM salgrade
WHERE grade = upper(rank);
RETURN (salary >= min_sal) AND (salary <= max_sal);
END sal_ok;

PROCEDURE raise_salary (emp_id NUMBER, grade CHAR, amount


NUMBER)
AS
salary NUMBER;
BEGIN
SELECT sal INTO salary
FROM emp
WHERE empno = emp_id;
IF sal_ok(grade, salary + amount) THEN
UPDATE emp
SET sal = sal + amount
WHERE empno = emp_id;
DBMS_OUTPUT.PUT_LINE('salary of employee '||emp_id||'
is updated successfully');
ELSE
DBMS_OUTPUT.PUT_LINE('invalid salary');

Focus Trainig Services, Pune Page 99


END IF;
END raise_salary;

END emp_actions;
/

Step3:
SQL>select * from emp;
SQL>exec emp_actions.hire_fire_employee('vivek','IT',15789,0.3);
SQL>commit;
SQL>select * from emp;
SQL>exec emp_actions.hire_fire_employee(1);
SQL>select * from emp;

8.7 PL/SQL Wrapper (By using Unix Command)


The PL/SQL wrapper is a stand utility that converts PL?SQL source code into portable object code.
Using it, you can deliver PL/SQL applications without axposing your source code, which many contain
priority algorithms and and data structure . The wrapper converts the readable source code into
unreadable code. By hiding application internals, it prevents minuse of your application. Wrapped
code, such as PL/SQL stored Programs, has several features:

 It is platform independents, so you do not need to deliver multiple versions of the same compilation
unit.
 It permits dynamic binding loading, so users need not shut down and relink to add a new feature.
 It permits dynamic binding, so external references are resolved at load time.
 It offers strict dependency checking, so that invalidated program units are recompiled automatically
when they are invoked.
 It supports normal importing and exporting, so the import/export utility can process wrapped files.

7.7.1 Running the Wrapper


The wrapper is an operating system executable called WRAP. To run the Wrapper, enter the
following command at your operating system prompt:

WRAP INAME=input_file_name [ONAME=output_file_name]

Focus Trainig Services, Pune Page 100


Each of the examples shown in the slide takes a file called test.sql as inpute and creates an output file
called test.plb After the wrapped file is created, execute the .plb file from SQL*Plus to compile and
store the wrapped version of the source code, as you would execute SQL cript files.
Note:-
 Only the INAME argument is required, if the ONAME argument is not specified, then the output file
acquires the same name as the input file with an extension of .plb
 The input file can have any extension, but the default is .sql.
 Case sensitivity of the INAME and ONAME values depends on the operating system.
 Generally, the output file is much larger then input file.
 Do not put spaces around the equal sign in the INAME and ONAME arguments and values.
Example:
Step1:( enter the following command at your operating system prompt)
Create or replace procedure test
as

begin
dbms_output.put_line('hello dada');
end;
/
show errors
set serveroutput on

Step2:

wrap iname=test.sql oname=test.plb

Focus Trainig Services, Pune Page 101


Exercise :

1. 19. Create a package namedc get_schema_info. This package should have one
public procedure get_tb_count which will have 2 in parameters as follows.
1. schema_name in varchar2
2. sort_order in varchar2 default 'D'
(A for Asc D for desc)

When you execute the procedure as follows a report should be generated.


A sample report is displayed below.

exec get_schema_info.get_tb_count('HR', 'D')

Table Count Report


------------------------------------------------------------

Date: June 23, 2012


------------------------------------------------------------

No. Table Name No. of Rows


--- --------------------- -----------------------
1 EMPLOYEES 1008
2. DEPARTMENTS 100
3. JOBS 88
4. LOCATION 22
5. REGIONS 4

Focus Trainig Services, Pune Page 102


9.
ORACLE PACKAGES
Objectives:

1) About the DBMS_OUTPUT Package


2) UTL_FILES
3) UTL_MAIL Package
4) DBMS_SCHEDULER Package
5) how to generate XML from table data in PL/SQL
6) Oracle dbms_ddl

9.1 About the DBMS_OUTPUT Package


Package DBMS_OUTPUT enables you to display output from PL/SQL blocks and subprograms, which
makes it easier to test and debug them. The procedure put_line outputs information to a buffer in
the SGA. You display the information by calling the procedure get_line or by setting SERVEROUTPUT
ON in SQL*Plus.

For example, suppose you create the following stored procedure:

CREATE or replace PROCEDURE calc_payroll (payroll OUT NUMBER)


AS
CURSOR c1 IS SELECT sal, comm FROM emp;
BEGIN
payroll := 0;
FOR c1rec IN c1 LOOP
c1rec.comm := NVL(c1rec.comm, 0);
payroll := payroll + c1rec.sal + c1rec.comm;
END LOOP;
/* Display debug info. */
dbms_output.put_line(’Value of payroll: ’ || TO_CHAR(payroll));
END;
/

Focus Trainig Services, Pune Page 103


When you issue the following commands, SQL*Plus displays the value assigned by the procedure to
parameter payroll:
SQL> SET SERVEROUTPUT ON
SQL> VARIABLE num NUMBER
SQL> CALL calc_payroll(:num);

Value of payroll: 31225

9.1.1 DBMS_OUTPUT Package Package Member

Package Member Description


NEW_LINE Procedure Terminates a line created with PUT

PUT_LINE Procedure Places partial line in buffer

GET_LINE Procedure GET_LINES Procedure

PUT Procedure Places a line in the buffer

DISABLE Procedure Disables message output

ENABLE Procedure Enables message output

9.1.2 Enables message output

This procedure disables calls to PUT, PUT_LINE, NEW_LINE, GET_LINE, and GET_LINES, and purges
the buffer of any remaining information.

As with the ENABLE Procedure, you do not need to call this procedure if you are using the
SERVEROUTPUT option of SQL*Plus.

Syntax

DBMS_OUTPUT.DISABLE;

Focus Trainig Services, Pune Page 104


 Pragmas:

pragma restrict_references(disable,WNDS,RNDS);

9.1.3 ENABLE Procedure

This procedure enables calls to PUT, PUT_LINE, NEW_LINE, GET_LINE, and GET_LINES. Calls to these
procedures are ignored if the DBMS_OUTPUT package is not activated.

Syntax

DBMS_OUTPUT.ENABLE (buffer_size IN INTEGER DEFAULT 20000);

 It is not necessary to call this procedure when you use the SET SERVEROUTPUT option of SQL*Plus.
 If there are multiple calls to ENABLE, then buffer_size is the last of the values specified. The
maximum size is 1,000,000, and the minimum is 2,000 when the user specifies buffer_size (NOT
NULL).
 NULL is expected to be the usual choice. The default is 20,000 for backwards compatibility with
earlier database versions that did not support unlimited buffering.

9.1.4 GET_LINE Procedure


This procedure retrieves a single line of buffered information.

Syntax:

DBMS_OUTPUT.GET_LINE (
line OUT VARCHAR2,
status OUT INTEGER);

9.1.5 GET_LINES Procedure

This procedure retrieves an array of lines from the buffer.

Syntax

DBMS_OUTPUT.GET_LINES ( lines OUT CHARARR, numlines IN OUT


INTEGER);

Focus Trainig Services, Pune Page 105


DBMS_OUTPUT.GET_LINES (
lines OUT DBMSOUTPUT_LINESARRAY,
numlines IN OUT INTEGER);

 You can choose to retrieve from the buffer a single line or an array of lines. Call the GET_LINE
procedure to retrieve a single line of buffered information. To reduce the number of calls to the
server, call the GET_LINES procedure to retrieve an array of lines from the buffer.
 You can choose to automatically display this information if you are using SQL*Plus by using the
special SET SERVEROUTPUT ON command.
 After calling GET_LINE or GET_LINES, any lines not retrieved before the next call to PUT, PUT_LINE,
or NEW_LINE are discarded to avoid confusing them with the next message.

9.1.6 PUT_LINE Procedure


This procedure places a line in the buffer.

Syntax

DBMS_OUTPUT.PUT_LINE (
item IN VARCHAR2);

 You can build a line of information piece by piece by making multiple calls to PUT, or place an entire
line of information into the buffer by calling PUT_LINE.
 When you call PUT_LINE the item you specify is automatically followed by an end-of-line marker. If
you make calls to PUT to build a line, then you must add your own end-of-line marker by calling
NEW_LINE. GET_LINE and GET_LINES do not return lines that have not been terminated with a
newline character.
 If your lines exceeds the line limit, you receive an error message.
 Output that you create using PUT or PUT_LINE is buffered. The output cannot be retrieved until the
PL/SQL program unit from which it was buffered returns to its caller.

Example:

SQL> SET SERVEROUTPUT ON


SQL> BEGIN
DBMS_OUTPUT.PUT_LINE ('hello');
DBMS_LOCK.SLEEP (10);

Focus Trainig Services, Pune Page 106


END;

9.2 UTL_FILES

What Is the UTL_FILE Package?


The UTL_FILE package provides text file I/O from within PL/SQL. Client-side security implementation
uses normal operating system file permission checking. Server-side security is implemented through
restrictions on the directories that can be accessed. In the init.ora file, the initialization parameter
UTL_FILE_DIR is set to the accessible directories desired.

9.2.1 UTL_FILE_DIR = directory_name


For example, the following initialization setting indicates that the directory /usr/ngreenbe/my_app is
accessible to the fopen function, assuming that the directory is accessible to the database server
processes. This parameter setting is case-sensitive on casesensitive operating systems.

9.2.2 UTL_FILE_DIR = /user/ngreenbe/my_app


The directory should be on the same machine as the database server. Using the following setting
turns off database permissions and makes all directories that are accessible to the database server
processes also accessible to the UTL_FILE package.
UTL_FILE_DIR = *
Note:
UTL_FILE_DIR = * is not recommended. Your init.ora file needs to include the parameter
UTL_FILE_DIR. If it does not, edit the init.ora file and add the parameter. Then restart the database
by using the SHUTDOWN and STARTUP commands.
Using the procedures and functions in the package, you can open files, get text from files, put text
into files, and close files. There are seven exceptions declared in the package to account for possible
errors raised during execution.

9.2.3 File Processing


Before using the UTL_FILE package to read from or write to a text file, you must first check whether
the text file is open by using the IS_OPEN function. If the file is not open, you open the file with the
FOPEN function. You then either read the file or write to the file until processing is done. At the end
of file processing, use the FCLOSE procedure to close the file.

Focus Trainig Services, Pune Page 107


Figure : File Processing Using the UTL_FILE Package

9.2.4.1 The UTL_FILE Package: Procedures and Functions


The UTL_FILE package comes with several procedures and functions for handling text files within
PL/SQL.

Procedures/Function Description
Opens a file for input or output with the default
FOPEN function
line size.
IS_OPEN function Determines if a file handle refers to an open file.
FCLOSE procedure Closes a file.
FCLOSE_ALL procedure Closes all open file handles.
GET_LINE procedure Reads a line of text from an open file.
Writes a line to a file. This does not append a line
PUT procedure
terminator
Writes one or more OS-specific line terminators
NEW_LINE procedure
to a file.
Writes a line to a file. This appends an OS-specific
PUT_LINE procedure line
terminator.
PUTF procedure A PUT procedure with formatting
FFLUSH procedure Physically writes all pending output to a file.

Focus Trainig Services, Pune Page 108


9.2.4.2 The UTL_FILE Exceptions
Exception Name Description
INVALID_PATH File location or filename was invalid
INVALID_MODE The open_mode parameter in FOPEN was invalid.
INVALID_FILEHANDLE File handle was invalid.
INVALID_OPERATION File could not be opened or operated on as
requested.
READ_ERROR Operating system error occurred during the read
operation.
WRITE_ERROR Operating system error occurred during the write
Operation.
INTERNAL_ERROR Unspecified PL/SQL error.

In addition to these package exceptions, procedures in UTL_FILE can also raise predefined PL/SQL
exceptions suchas NO_DATA_FOUND or VALUE_ERROR.

9.2.5 Procedures and Functions:

9.2.5.1 FOPEN function


This function opens a file for input or output. The file location must be an accessible directory, as
defined in the instance's initialization parameter UTL_FILE_DIR. The complete directory path must
already exist; it is not created by FOPEN. FOPEN returns a file handle, which must be used in all
subsequent I/O operations on the file. You can have a maximum of 50 files open simultaneously.

Syntax

UTL_FILE.FOPEN (
Location IN VARCHAR2,8
filename IN VARCHAR2,
open_mode IN VARCHAR2)
RETURN UTL_FILE.FILE_TYPE;

Parameters Description
Location Operating system-specific string that specifies

Focus Trainig Services, Pune Page 109


the directory
in which to open the file.
Filename Name of the file, including extension (file type),
without any
directory path information. (Under the UNIX
operating
system, the filename cannot be terminated with
a '/'.).
open_mode String that specifies how the fie is to be opened
(either upper or lower case letters can be used).
The supported values, and the UTL_FILE
procedures that can be used with them are: 'r'
read text (GET_LINE) 'w' write text (PUT,
PUT_LINE, NEW_LINE, PUTF, FFLUSH) 'a' appcend
text (PUT, PUT_LINE, NEW_LINE, PUTF, FFLUSH)

Note: If you open a file that does not exist using the 'a' value for open_mode, then the file is
created in write ('w') mode Returns.

FOPEN returns a file handle, whih must be passed to all subsequent procedures that operate on that
file. The specific contents of the file handle are private to the UTL_FILE package, and individual
components should not be referenced or changed by the UTL_FILE user.

9.2.5.2 IS_OPEN function


This function tests a file handle to see if it identifies an open file. IS_OPEN reports only whether a file
handle represents a file that has been opened, but not yet closed. It does not guarantee that there
will be no operating system errors when you attempt to use the file handle.

Syntax:

UTL_FILE.IS_OPEN (
file IN FILE_TYPE)
RETURN BOOLEAN;

Focus Trainig Services, Pune Page 110


Parameter Description
File Active file handle returned by an FOPEN call

9.2.5.3 FCLOSE procedure


This procedure closes an open file identified by a file handle. If there is buffered data yet to be
written when FCLOSE runs, then you may receive a WRITE_ERROR exception when closing a file.

Syntax

UTL_FILE.FCLOSE (
file IN OUT FILE_TYPE);

9.2.5.4. FCLOSE_ALL procedure


This procedure closes all open file handles for the session. This should be used as an emergency
cleanup procedure, for example, when a PL/SQL program exits on an exception.
Note: FCLOSE_ALL does not alter the state of the open file handles held by the user. This means that
an IS_OPEN test on a file handle after an FCLOSE_ALL call still returns TRUE, even though the file has
been closed. No further read or write operations can be performed on a file that was open before an
FCLOSE_ALL.
Syntax:

UTL_FILE.FCLOSE_ALL;

9.2.5.5 GET_LINE procedure


This procedure reads a line of text from the open file identified by the file handle and places the text
in the output buffer parameter. Text is read up to but not including the line terminator, or up to the
end of the file.
If the line does not fit in the buffer, then a VALUE_ERROR exception is raised. If no text was read due
to "end of file," then the NO_DATA_FOUND exception is raised. Because the line terminator
character is not read into the buffer, reading blank lines returns empty strings. The maximum size of
an input record is 1023 bytes, unless you specify a larger size in the overloaded version of FOPEN.
Syntax:
UTL_FILE.GET_LINE (
file IN FILE_TYPE

Focus Trainig Services, Pune Page 111


buffer OUT VARCHAR2);

Parameters Description
file Active file handle returned by an FOPEN call. The
file must be open for reading (mode 'r'),
otherwise an
INVALID_OPERATIONexception is raised.
Buffer Data buffer to receive the line read from the file.

Exceptions use:
 INVALID_FILEHANDLE
 INVALID_OPERATION
 READ_ERROR
 NO_DATA_FOUND
 VALUE_ERROR

9.2.5.6 PUT procedure


PUT writes the text string stored in the buffer parameter to the open file identified by the file handle.
The file must be open for write operations. No line terminator is appended by PUT; use NEW_LINE to
terminate the line or use PUT_LINE to write a complete line with a line terminator. The maximum
size of an input record is 1023 bytes, unless you specify a larger size in the overloaded version of
FOPEN.
Syntax:
UTL_FILE.PUT ( file IN FILE_TYPE, buffer IN VARCHAR2);

Parameters Description
File Active file handle returned by an FOPEN call.
Buffer Buffer that contains the text to be written to the
file.
You must have opened the file using mode 'w' or
mode 'a'; otherwise, anINVALID_OPERATION

Focus Trainig Services, Pune Page 112


exception is raised.

Exceptions
 INVALID_FILEHANDLE
 INVALID_OPERATION
 WRITE_ERROR

9.2.5.7 NEW_LINE procedure


This procedure writes one or more line terminators to the file identified by the input file handle. This
procedure is separate from PUT because the line terminator is a platformspecific character or
sequence of characters.
Syntax

UTL_FILE.NEW_LINE ( file IN FILE_TYPE, lines IN NATURAL := 1);

9.5.8 PUT_LINE procedure


This procedure writes the text string stored in the buffer parameter to the open file identified by the
file handle. The file must be open for write operations. PUT_LINE terminates the line with the
platform-specific line terminator character or characters.
The maximum size for an output record is 1023 bytes, unless you specify a larger value using the
overloaded version of FOPEN.

Syntax
UTL_FILE.PUT_LINE (
file IN FILE_TYPE,
buffer IN VARCHAR2);

9.2.5.9 PUTF procedure


This procedure is a formatted PUT procedure. It works like a limited printf(). The formatstring can
contain any text, but the character sequences '%s' and '\n' have special meaning.
 %s Substitute this sequence with the string value of the next argument in the argument list.

 \n Substitute with the appropriate platform-specific line terminator.

Focus Trainig Services, Pune Page 113


Syntax:
UTL_FILE.PUTF ( file IN FILE_TYPE, format IN VARCHAR2,
[arg1 IN VARCHAR2 DEFAULT NULL,
. . .
arg5 IN VARCHAR2 DEFAULT NULL]);

Exceptions
 INVALID_FILEHANDLE
 INVALID_OPERATION
 WRITE_ERROR

9.2.5.10 FFLUSH procedure


FFLUSH physically writes all pending data to the file identified by the file handle. Normally, data being
written to a file is buffered. The FFLUSH procedure forces any buffered data to be written to the file.
Flushing is useful when the file must be read while still open. For example, debugging messages can
be flushed to the file so that they can be read immediately.

Syntax
UTL_FILE.FFLUSH ( file IN FILE_TYPE);
invalid_maxlinesize EXCEPTION;

Exceptions
 INVALID_FILEHANDLE
 INVALID_OPERATION
 WRITE_ERROR

9.2.5.11 FOPEN function


This function opens a file. You can have a maximum of 50 files open simultaneously.

Syntax

UTL_FILE.FOPEN (
location IN VARCHAR2,

Focus Trainig Services, Pune Page 114


filename IN VARCHAR2,
open_mode IN VARCHAR2,
max_linesize IN BINARY_INTEGER)
RETURN file_type;

Parameter Description

Location Directory location of file.


Filename filename File name (including extension).
open_mode = Open mode ('r', 'w', 'a').
max_linesize Maximum number of characters per line,
including the newline
character, for this file. (minimum value 1,
maximum value 32767).

Exceptions

 INVALID_PATH: File location or name was invalid.


 INVALID_MODE: The open_mode string was invalid.
 INVALID_OPERATION: File could not be opened as requested.
 INVALID_MAXLINESIZE: Specified max_linesize is too large or too small.

9.3. UTL_MAIL Package


The UTL _MAIL Package:-

 It is utility for managing e-mail that includes such commonly used e-mail features as attachments,
CC, BCC and return receipt.

 Requires the SMTP_OUT_SERVER database initialization parameter to be set.


 Provides the following procedures:
- SEND for messages without attachments.
- SEND_ATTACH_ROW for messages with binary attachments.
- SEND _ATTACH_VARCHAR2 for messages with text attachments.

Focus Trainig Services, Pune Page 115


The UTL_MAIL Package is a utility for managing e-mail that includes such commonly used e-mail
features as attachments, CC, BCC and return receipt.

The UTL_MAIL Package is not installed by default because of the SMTP_OUT_SERVER configuration
requirement and the security exposure this involves, when installing UTL_MAIL you should take steps
to prevent the port defined by SMTP_OUT_SERVER being swamped by data transmission. To install
UTL_MAIL, login in as a DBA user in SQL*plus and execute the following scripts:-

@ORACLE_HOME/rdbms/admin/utlmail.sql

@ORACLE_HOME/rdbms/admin/prvtmail.plb

You should define the SMTP_OUT_SERVER parameter in the init.ora file database initialization file:-

SMTP_OUT_SERVER=mystmpserver.mydomain.com

The SMTP_OUT_SERVER parameter specifies the SMTP host and port to which UTL_MAIL delivers
outbound e-mail. Multiple servers can be specified, separated by the commas. If the first server in
the list is unavailable, then UTL_MAIL tries the second server, and so on. If SMTP_OUT_SERVER is not
defined, then this invokes a default setting derived from DB_DOMAIN ,which is a database
initialization parameter specifying for logical location of the database within the network structure
.For Example:-

db_domain=mydomain.com

9.3.1 Installing and Using UTL_MAIL


 : AS SYSDBA, using SQL*Plus:
- Set the SMTP_OUT_SERVER (require DBMS restart).
ALTER SYSTEM SET SMTP_OUT_SERVER=’smtp.server.com’ SCOPE=SPFILE
- Install the UTL_MAIL Package.
@?/rdbms/admin/utlmail.sql
@?/rdbms/admin/prvtmail.plb
 As a developer, invoke a UTL_MAIL procedure

BEGIN
UTL_MAIL.SEND (‘otn@oarcle.com’,’user@oracle.com’,
Message => ‘For latest downloads visit OTN’,
Subject => ‘OTN Newsletter’);
END;

Focus Trainig Services, Pune Page 116


The slide shows how to configure the SMTP_OUT_SERVER parameter to the names of the SMPT host
in your network, and how to install the UTL_MAIL package that is not installed by default. Changing
the SMTP_OUT_SERVER parameter requires restarting the database instance.These tasks are
performed by a user with SYSDBA capabilities.

The last example in the slide shows the simplest way to send a text message by using the
UTL_MAIL.SEND procedure with at least a subject and a message .The first two required parameter
are the following:

 The sender e-mail address (in this case,otn@oracle.com)

 The recipients e-mail address (for example, user@oracle.com).The value can be a comma-separated
list of addresses.

The UTL_MAIL.SEND procedure provides several other parameters, such as cc, bcc and priority with
default values. if not specified. In the example, the message parameter specifies the text for the e-
mail,and the subject parameter contains the text for the subject line. To send an HTML message with
HTML tags, add the mime_type parameter (for example, mime_type=>’text/html’).

9.3.2 Example:
create or replace procedure sp27
--This Program shows
--How to send mails using UTL_MAIL package
as
ora_no number;
ora_msg varchar2(100);
begin
UTL_MAIL.SEND( sender => 'gaurav@server1.example.com',
recipients => 'gaurav@server1.example.com',
cc => 'mithilesh@server1.example.com',
bcc => 'krunal@server1.example.com',
subject => 'test mail', message => 'hi how r
u??');

dbms_output.put_line('Message send successfully');


exception when others then
ora_no := sqlcode;

Focus Trainig Services, Pune Page 117


ora_msg := sqlerrm;
dbms_output.put_line('Message not send');
dbms_output.put_line(ora_no ||' '||ora_msg);
end;
/
show errors

OUTPUT
SQL> @sp27.sql
Procedure created.
No errors.
SQL> exec sp27
Message send successfully
PL/SQL procedure successfully completed.

9.4 DBMS_SCHEDULER Package

9.4.1 Overview of DBMS_SCHEDULER Package


The database scheduler compromise several components to enable jobs to be run. Use the DBMS_
SCHEDULER package to create each job with:-

 A unique job name


 A program (“what” should be executed)
 A schedule (“when it should run)

Oracle Database 10g provides collections of subprograms in the DBMS_SCHEDULER package to


simplify management and to provide a rich set of functionality for complex scheduling tasks.
Collectively, these subprograms are called scheduler can be called from any PL/SQL program. The
scheduler enables database administrators and application developers to control when and where
various tasks take place. By ensuring that many routine database task occurs without manual
intervention, you can lower operating costs, implement more reliable routine, and minimize human
error.

The diagram shows the following architectural component of the scheduler:

Focus Trainig Services, Pune Page 118


 A job is the combination of a program and a scheduler. Arguments required by the program can
be provided with the program or the job. All job names have the format [schema.] name. When
you create a job, you specify the job name, a program, a schedule, and (optionally) job
characteristics that can be provided through a job class.
 A Program determines what should be run. Every automated job involves a particular executable,
whether it is a PL/SQL block, a stored procedure, a native binary executable, or a shell script. A
Program provides a metadata about a particular executable and may require a list of arguments.
 A schedule specifies when and how many times a job is executed.
 A job class defines a category of jobs that share common resource usage requirements and
other characteristics .At any given time, each job can belong to only a single job class. A job class
has the following attributes:
- A database service name .The jobs in the job class will have an affinity to the particular service
specified – that is, the job, will run on the instances that cater to the specified service.
- A resource consumer group, which classifies a set of user’s sessions that have common resource
processing requirements. At any given time, a user session or job class can be belong to a single
resource consumer group. The resource consumer group that the job class associates with
determines the resources that are allocated to the job class.
 A Window is represented by an interval of time with a well-defined beginning and end, is used to
activate different resource plans at different times.
The slide focuses on the job components as the primary entity, however, a program, a scheduler,
a window, and a job class are components that can be created as individual entities that can be
associated with a job to be executed by the scheduler. When a job is created, it may contain all
the information needed in-line – that is, in the call that creates the job.Alternatinely, creating a
job may references a program or schedule component that was previously defined. Examples of
this are discussed in the next few pages.

The component that causes something to be executed at a specified time is called a Job. Use the
DBMS_SCHUDULER.CREATE_JOB procedure of the DBMS_SCHUDULER package to create a job,
which is in a disabled state by default. A jobs become active and scheduled when it is explicitly
enabled. To create a job, you:-

 Provides a name in the format [schema .] name


 Need the CREATE JOB privilege

Focus Trainig Services, Pune Page 119


Note:-A user with the CREATE ANY JOB privilege can create a job in any schema except the SYS
schema. Associating a job with a particular class requires the EXECUTE privilege for that class.

In simple turns, a job can be created specifying all the job details-the program to be executed (what)
and its schedule (when) - in the arguments of the CREATE JOB procedure. Alternatively, you can use
predefined program and schedule components. If you have a named program and schedule, then
these can be specified or combined with in-line arguments for maximum flexibility in the way a job is
created.

A simple logical check is performed on the schedule information (that is, checking the date
parameter when a job is created).The database checks whether the end date is after the start date .If
the start date refers to a time in the past, the start date is changed to the current date.

9.4.2 Creating Job with In-Line Parameters


Specify the type of code, code, start time, and frequency of the job to be run in the arguments of the
CREATE_JOB procedure.

Here is an example that schedules a PL/SQL block every hour:

BEGIN
DBMS_SCHEDULER.CERATE_JOB (
Job_name => ’JOB_NAME’,
Job_type => ’PLSQL_BLOCK’,
Job_action => ’BEGIN….; END; ’,
tart_date =>SYSTIMESTAMP,
Repeat interval => ‘FREQUENCY=HOURLY; INTERVAL=1’,
Enabled => TRUE);
END;
/

You can create a job to run a PL/SQL block, stored procedure, or external program by using the
DBMS_SCHEDULER.CREATE_JOB procedure. The CREATE_JOB procedure can be used directly without
requiring you to create program or schedule components.

The example in the slide shows how you can specify all the job details in-line. The parameter of the
CREATE_JOB procedure define “what” is to be executed, the schedule, and other job attributes. The
following parameters define what is to be executed.

Focus Trainig Services, Pune Page 120


 The job_type parameter can be one of the three values:
– PLSQL_BLOCK for any PL/SQL block or SQL statement. This type of job cannot accept
arguments.
– STORED_PROCEDURE for any stored stand-alone or packaged procedure. The procedure can
accept arguments that are supplied with the job.
– EXECUTABLE for an executable command-line operating system application.
 The schedule is specified by using the following parameters:
- The start_date accepts a time stamp, and the repeat interval is string-specified as a calendar
or PL/SQL expression. An end_date can be specified.

Note:-String expressions that are specified for repeat_interval are discussed later.

The example specifies that, the job should run every hour.

9.4.3 Managing Jobs


 Run a job:-
DBMS_SCHEDULER.RUN_JOB ( ‘SCHEMA.JOB_NAME’ ) ;
 Stop a job:-
DBMS_SCHEDULER.STOP_JOB ( ‘SCHEMA.JOB_NAME’ ) ;
 Drop a job even if it is currently running:
DBMS_SCHEDULER.DROP_JOB ( ‘JOB_NAME’ ,TRUE ) ;

After job has created, you can:

 Run the job by calling the RUN_JOB procedure specifying the name of the job.The job is
immediately executed in your current session.
 Stop the job by using the STOP_JOB procedure. If the job is running currently, it is stopped
immediately. The STOP_JOB procedure has two arguments:
- Job_name: -Is the name of the job to be stopped.

Force: -Attempts to gracefully terminate a job. If this fails and force is set to TRUE, then the job
slave is term If the DROP_JOB procedure is called and the job specified is currently running, then
the command fails unless the force option is set to TRUE. If the force option is set to TRUE, then
any instance of the job that is running is stopped and the job is dropped.

Focus Trainig Services, Pune Page 121


Note:-To run, stop, or drop a job that belongs to another user, you need ALTER privileges on that
jobs or the CREATE ANY JOB system privilege.

- inated.(Default value is FALSE).To use force, you must have the MANAGE_SCHUDULER system
privilege.
 Drop the job with the DROP_JOB procedure. This procedure has two arguments:
- Job_name: -Is the name of the job to be dropped.
- Force: -Whether the job should be stopped and dropped if it is currently running. (Default
value is FALSE).
Example of DBMS_SCHEDULER

create or replace procedure sp28


--This procedure shows
--How to use default package
--DBMS_SCHEDULER to schedule some task
as
orr_code number;
orr_msg varchar2(500);
begin
--create_job is inbuild procedure in DBMS_SCHEDULER
DBMS_SCHEDULER.CREATE_JOB (job_name => 'update_sales',
job_type => 'STORED_PROCEDURE',
job_action => 'sp11_4',
start_date => '20-APR-10 03.10.00.000000000 PM
ASIA/CALCUTTA',
repeat_interval => 'FREQ=SECONDLY;INTERVAL=10',
end_date => '20-APR-10 03.11.00.000000000 PM
ASIA/CALCUTTA',
comments => 'My new job');

exception when others then


orr_code := sqlcode;
orr_msg := sqlerrm;
dbms_output.put_line(orr_code||' '||orr_msg);
end;
/
show errors

OUTPUT
15:04:48 SQL> truncate table test_sch;
Table truncated.
15:04:57 SQL> @sp28.sql
Procedure created.
No errors.

Focus Trainig Services, Pune Page 122


15:05:01 SQL> exec sp28
PL/SQL procedure successfully completed.
15:05:06 SQL> exec
dbms_scheduler.set_scheduler_attribute('MAX_JOB_SLAVE_PROCESSES',
2);
-- requires manage scheduler privilege
PL/SQL procedure successfully completed.
15:05:22 SQL> exec dbms_scheduler.enable('update_sales');
-- enable the job
PL/SQL procedure successfully completed.
15:05:43 SQL> select * from test_sch;
no rows selected
15:07:31 SQL> select count(*) from test_sch;
COUNT(*)
----------
0
15:09:41 SQL> /
COUNT(*)
-------------------
100
15:10:04 SQL> /
COUNT(*)
----------
200

15:10:14 SQL> /
COUNT(*)
----------
300

15:10:27 SQL> /
COUNT(*)
----------
400

15:10:37 SQL> /
COUNT(*)
----------
500

15:10:46 SQL> /
COUNT(*)
----------
600
Focus Trainig Services, Pune Page 123
15:10:53 SQL> /
COUNT(*)
----------
600

9.4.4 Data Dictionary Views for Managing Jobs

 [DBA | ALL | USER]_SCHEDULER_JOBS


 [DBA | ALL | USER]_SCHEDULER_RUNNING_JOBS
 [DBA | ALL | USER]_SCHEDULER_JOB_CLASSES
 [DBA | ALL | USER]_SCHEDULER_JOB_LOG
 [DBA | ALL | USER]_SCHEDULER_JOB_RUN_DETAILS
 [DBA | ALL | USER]_SCHEDULER_PROGRAMS

The DBA_SCHEDULER_JOB_LOG view shows all completed job instances, both successful and failed.

To view the state of your jobs, use the following query:-


SELECT job_name, program_name, job_type, state FROM
USER_SCHEDULER_JOBS;

To determine which instance a job is running on, use the following query:-
SELECT owner, job_name, running_instance, resource_consumer_group
FROM DBA_SCHEDULER_RUNNING_JOBS;

To determine information about how a job is run,use the following query:-


SELECT job_name, instance_id, req_start_date, actual_start_date,
status FROM ALL_SCHEDULER_JOB_RUN_DETAILS;

To determine the status of your jobs, use the following query:-

SELECT job_name, status, error#, run_duration, cpu_used FROM


USER_SCHEDULER_JOB_RUN_DETAILS;

Focus Trainig Services, Pune Page 124


9.5 how to generate XML from table data in PL/SQL
The datatype to hold XML in PL/SQL or in the database is XMLTYPE. So you can use the generated
XML in PL/SQL, store it in table (XMLTYPE column), transform it to a CLOB (using the XMLTYPE
getClobVal member function which I use in the examples) and write it to a file.

9.5.1 XMLTYPE
The easiest way to create an XML document, is using the constructor of XMLTYPE. This constructor
can have several datatypes as input, like a CLOB and VARCHAR2, but as we’re going to base our XML
on table data, we’re using a REF CURSOR.

You can create a ref cursor and pass on this ref cursor to the XMLTYPE constructor like this:

DECLARE
l_refcursor SYS_REFCURSOR;
l_xmltype XMLTYPE;
BEGIN
OPEN l_refcursor FOR SELECT department_id , department_name
FROM departments
WHERE department_id IN (10,20);

l_xmltype := XMLTYPE(l_refcursor);
dbms_output.put_line(l_xmltype.getClobVal);
END;
/

OUTPUT:

<?xml version="1.0"?>
<ROWSET>
<ROW>
<DEPARTMENT_ID>10</DEPARTMENT_ID>
<DEPARTMENT_NAME>Administration</DEPARTMENT_NAME>
</ROW>
<ROW>
<DEPARTMENT_ID>20</DEPARTMENT_ID>

<DEPARTMENT_NAME Marketing </DEPARTMENT_NAME>


</ROW>
</ROWSET>

9.5.2 DBMS_XMLGEN
The DBMS_XMLGEN built-in is similar to the XMLTYPE constructor, but accepts a query directly:

DECLARE
l_xmltype XMLTYPE;
BEGIN
l_xmltype := dbms_xmlgen.getxmltype('SELECT department_id ,
department_name
FROM departments
WHERE department_id IN (10,20)’);

Focus Trainig Services, Pune Page 125


dbms_output.put_line(l_xmltype.getClobVal);
END;
/

OUTPUT:

<ROWSET>
<ROW>
<DEPARTMENT_ID>10</DEPARTMENT_ID>
<DEPARTMENT_NAME>Administration</DEPARTMENT_NAME>
</ROW>
<ROW>
<DEPARTMENT_ID>20</DEPARTMENT_ID>
<DEPARTMENT_NAME>Marketing</DEPARTMENT_NAME>
</ROW>
</ROWSET>

But it also provides procedures to change the ROWSET and ROW tags.

DECLARE
l_xmltype XMLTYPE;
l_ctx dbms_xmlgen.ctxhandle;
BEGIN
l_ctx := dbms_xmlgen.newcontext('SELECT department_id ,
department_name FROM departments WHERE department_id in (10,20)');

dbms_xmlgen.setrowsettag(l_ctx, 'Departments');
dbms_xmlgen.setrowtag(l_ctx, 'Dept');

l_xmltype := dbms_xmlgen.getXmlType(l_ctx) ;
dbms_xmlgen.closeContext(l_ctx);

dbms_output.put_line(l_xmltype.getClobVal);
End;
/

OUTPUT:

<Departments>
<Dept>
<DEPARTMENT_ID>10</DEPARTMENT_ID>
<DEPARTMENT_NAME>Administration</DEPARTMENT_NAME>
</Dept>
<Dept>
<DEPARTMENT_ID>20</DEPARTMENT_ID>
<DEPARTMENT_NAME>Marketing</DEPARTMENT_NAME>
</Dept>
</Departments>

Focus Trainig Services, Pune Page 126


9.5.3 dbms_xmldom

With the XMLTYPE constructor and DBMS_XMLGEN package, you can create simple XML documents,
fast and easy. When you need to create more advanced XML documents or want to have more
control on how your XML document looks like, DBMS_XMLDOM can be used. The DBMS_XMLDOM
package is a bit more complicated as you’ll have to create the entire document by calling functions
and procedures of the package.

The following example creates an XML document with the department information retrieved from
the query. In short, this is how it works: create new elements and add them as a (child) node.

DECLARE
l_xmltype XMLTYPE;

l_domdoc dbms_xmldom.DOMDocument;

l_root_node dbms_xmldom.DOMNode;

l_department_element dbms_xmldom.DOMElement;
l_departments_node dbms_xmldom.DOMNode;

l_dept_element dbms_xmldom.DOMElement;
l_dept_node dbms_xmldom.DOMNode;

l_name_element dbms_xmldom.DOMElement;
l_name_node dbms_xmldom.DOMNode;
l_name_text dbms_xmldom.DOMText;
l_name_textnode dbms_xmldom.DOMNode;

l_location_element dbms_xmldom.DOMElement;
l_location_node dbms_xmldom.DOMNode;
l_location_text dbms_xmldom.DOMText;
l_location_textnode dbms_xmldom.DOMNode;
BEGIN
-- Create an empty XML document
l_domdoc := dbms_xmldom.newDomDocument;

-- Create a root node


l_root_node := dbms_xmldom.makeNode(l_domdoc);

-- Create a new node Departments and add it to the root node


l_department_element := dbms_xmldom.createElement(l_domdoc,
'Deptartments' );
l_departments_node :=
dbms_xmldom.appendChild(l_root_node,dbms_xmldom.makeNode(l_dep
artment_element));

FOR r_dept IN (SELECT dept.department_id,


dept.department_name, loc.city
FROM departments dept
JOIN locations loc
Focus Trainig Services, Pune Page 127
ON loc.location_id = dept.location_id
WHERE dept.department_id IN (10,20))
LOOP
-- For each record, create a new Dept element with the Department ID
as attribute.
-- and add this new Dept element to the Departments node

l_dept_element := dbms_xmldom.createElement(l_domdoc, 'Dept'


);
dbms_xmldom.setAttribute(l_dept_element, 'DeptID',
r_dept.department_id);
l_dept_node
:=dbms_xmldom.appendChild(l_departments_node,dbms_xmldom.makeNode(l_
dept_element));
-- Each Dept node will get a Name node which contains the department
name as text
l_name_element := dbms_xmldom.createElement(l_domdoc, 'Name'
);
l_name_node :=
dbms_xmldom.appendChild(l_dept_node,dbms_xmldom.makeNode(l_name_elem
ent));
l_name_text := dbms_xmldom.createTextNode(l_domdoc,
r_dept.department_name );
l_name_textnode :=
dbms_xmldom.appendChild(l_name_node,dbms_xmldom.makeNode(l_name_text
));

-- Each Dept node will aslo get a Location node which contains
the location(city) as text
l_location_element := dbms_xmldom.createElement(l_domdoc,
'Location' );
l_location_node :=
dbms_xmldom.appendChild(l_dept_node,dbms_xmldom.makeNode(l_location_
element));
l_location_text := dbms_xmldom.createTextNode(l_domdoc,
r_dept.city );
l_location_textnode :=
dbms_xmldom.appendChild(l_location_node,dbms_xmldom.makeNode(l
_location_text));
END LOOP;

l_xmltype := dbms_xmldom.getXmlType(l_domdoc);
dbms_xmldom.freeDocument(l_domdoc);

dbms_output.put_line(l_xmltype.getClobVal);
END;
/

OUTPUT:

<Deptartments>
<Dept DeptID="10">
<Name>Administration</Name>
Focus Trainig Services, Pune Page 128
<Location>Seattle</Location>
</Dept>
<Dept DeptID="20">
<Name>Marketing</Name>
<Location>Toronto</Location>
</Dept>
</Deptartments>

9.6 Oracle dbms_ddl

Oracle never states in the documentation obfuscation is a secure solution, they say its obfuscation.
It would be interesting to see when Oracle will offer encryption tool for PL/SQL.

Using Oracle dbms_ddl


There is an analyze_object procedure that is part of the Oracle dbms_ddl package that has similar,
but not quite as powerful, functionality. This procedure must be created by a user with select access
on the dba_tables view and the required privileges to analyze the specified schema/owner.

I suggest an account similar to the SYSTEM account. Remember that stored objects cannot be
created based on privileges from a role, so even the SYSTEM account must be given a direct grant on
the dba_tables view.

Some dbms_ddl notes:

 dbms_ddl.analyze schema: Oracle provides many ways to analyze SQL optimizer statistics,
and Oracle recommends using the dbms_stats package. It is not always a good idea to use
Oracle's dbms_utility.analyze_schema or the dbms_ddl.analyze_object packages to perform
this task.

 Using the dbms_ddl.wrap procedure to encrypt PL/SQL

It’s important for vendors who write applications using Oracle PL/SQL to protect their intellectual
property and encrypt their PL/SQL source code. Oracle has two method for encrypting PL/SQL, the
wrap.exe and the dbms_ddl.wrap utility in release 10.2 and onwards.

9.6.1 DBMS_DDL.WRAP
The dbms_ddl.wrap procedure accepts as input a parameter containing a PL/SQL create or replace
statement and dbms_ddl.wrap returns the obfuscated PL/SQL, which can be written to a file or
stored in a table.. The outstanding example of using the dynamic PL/SQL encryption function:

SET SERVEROUTPUT ON SIZE UNLIMITED


CREATE OR REPLACE FUNCTION get_date_string wrapped
DECLARE
l_source VARCHAR2(32767);
l_wrap VARCHAR2(32767);
BEGIN
l_source := 'CREATE OR REPLACE FUNCTION get_date_string RETURN

Focus Trainig Services, Pune Page 129


VARCHAR2 AS' ||'BEGIN ' ||'RETURN TO_CHAR(SYSDATE, ''DD-MON-YYYY'');
' || 'END get_date_string;';
l_wrap := SYS.DBMS_DDL.WRAP(ddl => l_source);
DBMS_OUTPUT.put_line(l_wrap);
END;
/

OUTPUT:
a000000
b2
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
8
6f
aa
mV4eMSJ8EqqgErJT91l6UZ0pdDUwgyr6LZ5GfHSmUPiJfkEObQpeDb6D7glajI+ONulx
dqC1
0HvOPP4eJpQs5zxsKXpj6XL1
fvieXyWCr3BTzXTqcGYhfXrtqDVPztR/o+9UZ8l5OijDSsRW
ZPv6rISzFyqeEsCBweFUFyxd

In addition to the wrap functions, the dbms_ddl package also contains three overloaded procedures
called create_wrapped. These procedure have the same parameter lists as the three wrap function
overloads, and are used to wrap and compile the specified source. The following example shows
how the dbms_sql.varchar2a version is used:

Step1:

SET SERVEROUTPUT ON SIZE UNLIMITED


DECLARE
l_source DBMS_SQL.VARCHAR2A;
l_wrap DBMS_SQL.VARCHAR2A;
BEGIN
_source(1) := 'CREATE OR REPLACE FUNCTION get_date_string
RETURN VARCHAR2 AS ';
l_source(2) := 'BEGIN ';

Focus Trainig Services, Pune Page 130


l_source(3) := 'RETURN TO_CHAR(SYSDATE, ''DD-MON-YYYY''); ';
l_source(4) := 'END get_date_string;';

SYS.DBMS_DDL.CREATE_WRAPPED(ddl => l_source,


lb => 1,
ub => l_source.count);
END;
/

Step2:

PL/SQL procedure successfully completed.

SET PAGESIZE 100

SELECT text
FROM user_source
WHERE name = 'GET_DATE_STRING'
AND type = 'FUNCTION';

TEXT
--------------------------------------------------------------------
----
FUNCTION get_date_string wrapped
a000000
b2
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
8
6f aa
mV4eMSJ8EqqgErJT91l6UZ0pdDUwgyr6LZ5GfHSmUPiJfkEObQpeDb6D7glajI+ONulx
dqC1
0HvOPP4eJpQs5zxsKXpj6XL1fvieXyWCr3BTzXTqcGYhfXrtqDVPztR/o+9UZ8l5OijD
SsRW
ZPv6rISzFyqeEsCBweFUFyxd

Focus Trainig Services, Pune Page 131


The create_wrapped procedures are the equivalent of passing the wrapped source returned from
the wrap function into an execute immediate or dbms_sql.parse call, but they are optimized to
give better performance.

Focus Trainig Services, Pune Page 132


10.
DATABASE TRIGGER
Objectives:

1) Describe different types of triggers


2) Describe database triggers and their use
3) Create database triggers
4) Describe database trigger firing rules
5) Remove database triggers

A trigger:
• Is a PL/SQL block or a PL/SQL procedure associated with a table, view, schema, or the database
• Executes implicitly whenever a particular event takes place

10.2 Different Types of Triggers


 Application trigger:
Fires whenever an event occurs with a particular application
 Database trigger:
Fires whenever a data event (such as DML) or system event (such as logon or shutdown)
occurs on a schema or database.
Application triggers execute implicitly whenever a particular data manipulation language (DML) event
occurs within an application. An example of an application that uses triggers extensively is one
developed with Oracle Forms Developer.

Database triggers execute implicitly when a data event such as DML on a table (an INSERT, UPDATE,
or DELETE triggering statement), an INSTEAD OF trigger on a view, or data definition language (DDL)
statements such as CREATE and ALTER are issued, no matter which user is connected or which
application is used. Database triggers also execute implicitly when some user actions or database
system actions occur, for example, when a user logs on, or the DBA shut downs the database.

Note: Database triggers can be defined on tables and on views. If a DML operation is issued on a
view, the INSTEAD OF trigger defines what actions take place. If these actions include DML operations
on tables, then any triggers on the base tables are fired.Database triggers can be system triggers on a
Focus Trainig Services, Pune Page 133
database or a schema. With a database, triggers fire for each event for all users; with a schema,
triggers fire for each event for that specific user.

10.3 Guidelines for Designing Triggers


• Design triggers to:
– Perform related actions
– Centralize global operations
• Do not design triggers:
– Where functionality is already built into the Oracle server
– That duplicate other triggers

• Create stored procedures and invoke them in a trigger, if the PL/SQL code is very

lengthy.

• The excessive use of triggers can result in complex interdependencies, which may be difficult to
maintain in large applications.

Example:

create or replace trigger chk_emp_sal


--This programs shows
--How to declare
triggers --for each row
before insert or update
of salary
on employees
for each row
declare
v_error VARCHAR2(2000);
begin
if :new.salary > 25000 then
v_error:=:old.first_name||' cannot have that much!';
raise_application_error(-20999,v_error);
end if;
end;
/
show errors

OUTPUT:
SQL> @14_1.sql
Trigger created.
No errors.

Focus Trainig Services, Pune Page 134


SQL> insert into
employees(EMPLOYEE_ID,LAST_NAME,EMAIL,HIRE_DATE,JOB_ID,SALARY)
2 values(215,'Bhide','abc@gmail.com',sysdate,'IT_PROG',26000);
insert into
employees(EMPLOYEE_ID,LAST_NAME,EMAIL,HIRE_DATE,JOB_ID,SALARY)
*
ERROR at line 1:
ORA-20999: cannot have that much!
ORA-06512: at "HR.CHK_EMP_SAL", line 7
ORA-04088: error during execution of trigger 'HR.CHK_EMP_SAL'

10.4 Creating DML Triggers


A triggering statement contains:

• Trigger timing

– For table: BEFORE, AFTER

– For view: INSTEAD OF

• Triggering event: INSERT, UPDATE, or DELETE

• Table name: On table, view

• Trigger type: Row or statement

• WHEN clause: Restricting condition

• Trigger body: PL/SQL block

Before coding the trigger body, decide on the values of the components of the trigger: the trigger
timing, the triggering event, and the trigger type.

If multiple triggers are defined for a table, be aware that the order in which multiple triggers of the
same type fire is arbitrary. To ensure that triggers of the same type are fired in a particular order,
consolidate the triggers into one trigger that calls separate procedures in the desired order.

10.4.1 DML Trigger Components:


Trigger timing: When should the trigger fire?
• BEFORE: Execute the trigger body before the triggering DML event on a table.
• AFTER: Execute the trigger body after the triggering DML event on a table.
Focus Trainig Services, Pune Page 135
• INSTEAD OF: Execute the trigger body instead of the triggering statement. This is used for
views that are not otherwise modifiable.

10.4.2 BEFORE Triggers


This type of trigger is frequently used in the following situations:
• To determine whether that triggering statement should be allowed to complete. (This
situation enables you to eliminate unnecessary processing of the triggering statement and
its eventual rollback in cases where an exception is raised in the triggering action.)
• To derive column values before completing a triggering INSERT or UPDATE statement.
• To initialize global variables or flags, and to validate complex business rules.

10.4.3 AFTER Triggers


This type of trigger is frequently used in the following situations:
• To complete the triggering statement before executing the triggering action.
• To perform different actions on the same triggering statement if a BEFORE trigger is
already present.

10.4.4 INSTEAD OF Triggers


This type of trigger is used to provide a transparent way of modifying views that cannot be modified
directly through SQL DML statements because the view is not inherently modifiable.
You can write INSERT, UPDATE, and DELETE statements against the view. The INSTEAD OF trigger
works invisibly in the background performing the action coded in the trigger body directly on the
underlying tables.

10.5 Triggering user event:


Which DML statement causes the trigger to execute? You can use any of the
Following:
• INSERT
• UPDATE
• xxxxDELETE

The triggering event or statement can be an INSERT, UPDATE, or DELETE statement on a table.

Focus Trainig Services, Pune Page 136


 When the triggering event is an UPDATE statement, you can include a column list to identify
which columns must be changed to fire the trigger. You cannot specify a column list for an
INSERT or for a DELETE statement, because they always affect entire rows.
.

. . UPDATE OF salary . . .

• The triggering event can contain one, two, or all three of these DML operations.
. . . INSERT or UPDATE or DELETE
. . . INSERT or UPDATE OF job_id . . .
Example:

create or replace trigger trig_example


before insert or delete or update on trig_eg
for each row
declare
ChangeType varchar2(10);
begin
/* Use 'I' for an INSERT, 'D' for DELETE, and 'U' for UPDATE.
*/
if inserting then
ChangeType := 'I';
elsif updating then
ChangeType := 'U';
else
ChangeType := 'D';
end if;
insert into changes_record values(ChangeType,USER,SYSDATE);
end trig_example;
/
show errors

OUTPUT:

SQL> @sp14_2.sql
Trigger created.
No errors.

SQL> select * from CHANGES_RECORD;


no rows selected

SQL> insert into trig_eg values(1,'aaa');


1 row created.

SQL> insert into trig_eg values(2,'bbb');


1 row created.

Focus Trainig Services, Pune Page 137


SQL> update trig_eg set name = 'xxxx' where id = 2;
1 row updated.

SQL> delete from trig_eg where id = 2;


1 row deleted.

SQL> select * from CHANGES_RECORD;


CHANGE USER_NAME CHANGE_DA
---------- ---------- ---------
I GAURAV 18-APR-10
I GAURAV 18-APR-10
U GAURAV 18-APR-10
D GAURAV 18-APR-10
SQL> select * from trig_eg;
ID NAME
---------- ----------
1 aaa

10.6 Trigger types:

Should the trigger body execute for each row the statement affects or only once?
 Statement: The trigger body executes once for the triggering event. This is the default. A
statement trigger fires once, even if no rows are affected at all.
 Row: The trigger body executes once for each row affected by the triggering event. A row trigger
is not executed if the triggering event affects no rows. Statement Triggers and Row Triggers
You can specify that the trigger will be executed once for every row affected by the triggering
statement (such as a multiple row UPDATE) or once for the triggering statement, no matter how
many rows it affects.

10.6.1 Statement Trigger


A statement trigger is fired once on behalf of the triggering event, even if no rows are affected at all.
Statement triggers are useful if the trigger action does not depend on the data from rows that are
affected or on data provided by the triggering event itself: for example, a trigger that performs a
complex security check on the current user.

10.6.2 Row Trigger


A row trigger fires each time the table is affected by the triggering event. If the triggering event
affects no rows, a row trigger is not executed. Row triggers are useful if the trigger action depends on
data of rows that are affected or on data provided by the triggering event itself.

Focus Trainig Services, Pune Page 138


Trigger body: What action should the trigger perform?
The trigger body is a PL/SQL block or a call to a procedure. The trigger action defines what needs to
be done when the triggering event is issued.The PL/SQL block can contain SQL and PL/SQL
statements, and can define PL/SQLconstructs such as variables, cursors, exceptions, and so on. You
can also call a PL/SQL procedure or a Java procedure.
Additionally, row triggers use correlation names to access the old and new column values of the row
being processed by the trigger.
Note: The size of a trigger cannot be more than 32 K.
Syntax for Creating DML Statement Triggers

CREATE [OR REPLACE] TRIGGER trigger_name


timing
event1 [OR event2 OR event3]
ON table_name
trigger_body
--Note: Trigger names must be unique with respect to other triggers
in the same schema.
CREATE OR REPLACE TRIGGER secure_emp
BEFORE INSERT ON employees
BEGIN
IF (TO_CHAR(SYSDATE,'DY') IN ('SAT','SUN')) OR
(TO_CHAR(SYSDATE,'HH24:MI')
NOT BETWEEN '08:00' AND '18:00')
THEN RAISE_APPLICATION_ERROR (-20500,'You may
insert into EMPLOYEES table only
during business hours.');
END IF;
END;
/

Example:
Step1:
SQL> create table deptcopy as select * from departments;

Step2:

Focus Trainig Services, Pune Page 139


create or replace trigger securedept
before INSERT
on deptcopy
begin
if (to_char(sysdate,'DY') ='MON') OR (to_char(sysdate,'HH24:MI') NOT
BETWEEN '11:00' and '20:00') then
raise_application_error(-20500,'You may insert into departments table
during business hours');
end if;
End;
/

Step3:
OUTPUT:

Trigger created.

SQL> insert into deptcopy values(280,'Sports',null,null);


insert into deptcopy values(280,'Sports',null,null)
*
ERROR at line 1:
ORA-20500: You may insert into departments table during business
hours
ORA-06512: at "SAURABHG.SECUREDEPT", line 3
ORA-04088: error during execution of trigger 'SAURABHG.SECUREDEPT'

10.7 Using OLD and NEW Qualifiers

CREATE OR REPLACE TRIGGER audit_emp_values


AFTER DELETE OR INSERT OR UPDATE ON employees
FOR EACH ROW
BEGIN
INSERT INTO audit_emp_table (user_name, timestamp, id,
old_last_name, new_last_name, old_title, new_title, old_salary,
new_salary) VALUES (USER, SYSDATE, :OLD.employee_id, :OLD.last_name,

Focus Trainig Services, Pune Page 140


:NEW.last_name, :OLD.job_id, :NEW.job_id, :OLD.salary, :NEW.salary
);

END;
/

Within a ROW trigger, reference the value of a column before and after the data change by prefixing
it with the OLD and NEW qualifier
OUTPUT:
Update Employees
*
ERROR at line 1:
ORA-20202: Employee can not this amount
ORA-06512: at “PL/SQL.RESTRICT_SALARY”, line 5
ORA-04088: error during execution of trigger
‘PLSQL.RESTRICTp_SALARY’

The OLD and NEW qualifiers are available only in ROW triggers.
• Prefix these qualifiers with a colon (:) in every SQL and PL/SQL statement.
• There is no colon (:) prefix if the qualifiers are referenced in the WHEN restricting condition.

Note: Row triggers can decrease the performance if you do a lot of updates on larger tables. To
restrict the trigger action to those rows that satisfy a certain condition, provide a WHEN clause.

Create a trigger on the EMPLOYEES table to calculate an employee’s commission when a row is
added to the EMPLOYEES table, or when an employee’s salary is modified. The NEW qualifier cannot
be prefixed with a colon in the WHEN clause because the WHEN clause is outside the PL/SQL blocks.

Focus Trainig Services, Pune Page 141


10.8 INSTEAD OF Triggers

Use INSTEAD OF triggers to modify data in which the DML statement has been issued against an
inherently non-updatable view. These triggers are called INSTEAD OF triggers because, unlike other
triggers, the Oracle server fires the trigger instead of executing the triggering statement. This trigger
is used to perform an INSERT, UPDATE, or DELETE operation directly on the underlying tables.

You can write INSERT, UPDATE, or DELETE statements against a view, and the INSTEAD OF trigger
works invisibly in the background to make the right actions take place.

10.8.1 Why Use INSTEAD OF Triggers?


A view cannot be modified by normal DML statements if the view query contains set operators,
group functions, clauses such as GROUP BY, CONNECT BY, START, the DISTINCT operator, or joins.
For example, if a view consists of more than one table, an insert to the view may entail an insertion
into one table and an update to another. So, you write an INSTEAD OF trigger that fires when you
write an insert against the view. Instead of the original insertion, the trigger body executes, which
results in an insertion of data into one table and an update to another table.
Note: If a view is inherently updateable and has INSTEAD OF triggers, the triggers take precedence.

INSTEAD OF triggers are row triggers.


The CHECK option for views is not enforced when insertions or updates to the view are performed by
using INSTEAD OF triggers. The INSTEAD OF trigger body must enforce the check.

Focus Trainig Services, Pune Page 142


10.8.2 Creating an INSTEAD OF Trigger
Syntax:

CREATE [OR REPLACE] TRIGGER trigger_name


INSTEAD OF
event1 [OR event2 OR event3]
ON view_name
[REFERENCING OLD AS old | NEW AS new]
[FOR EACH ROW]
trigger_body

Parameters of Triggers:

Trigger_name Is the name of the Trigger.

INSTEAD of Indicates that the trigger belong to a view

EVENT Identifies the data manipulation that cause

the trigger to fire:

INSERT

UPDATE [of column]

DELETE,

VIEW_NAME Indicate the view associate with trigger

REFERENCEING Specifies correlation name for the old and

new values of the current row (The defaults

are OLD and NEW)

FOR EACH ROW DESIGN the trigger to be a row trigger,

INSTEAD OF trigger can only be row triggers.

If this is omitted, the trigger is still define as a

row trigger.

Focus Trainig Services, Pune Page 143


TRIGGER BODY Is the trigger body that defines the action

performed by the trigge beginning with either

DECLEARE or BEGIN, and ending with END or

a call to a procedur

Note: INSTEAD OF triggers can be written only for views. BEFORE and AFTER options are not valid.

You can create an INSTEAD OF trigger in order to maintain the base tables on which a view is based.
Assume that an employee name will be inserted using the view EMP_DETAILS that is created based
on the EMPLOYEES and DEPARTMENTS tables. Create a trigger that results in the appropriate INSERT
and UPDATE to the base tables. Because of the INSTEAD OF TRIGGER on the view EMP_DETAILS,
instead of inserting the new employee record into the EMPLOYEES table:
• A row is inserted into the NEW_EMPS table.
• TheTOTAL_DEPT_SAL column of the NEW_DEPTS table is updated. The salary value
supplied for the new employee is added to the existing total salary of the department to
which the new employee has been assigned.

10.9 Difference between Procedures and Triggers

1. We can execute a stored procedure whenever we want with the help of the exec command,
but a trigger can only be executed whenever an event (insert, delete, and update) is fired on
the table on which the trigger is defined.
2. We can call a stored procedure from inside another stored procedure but we can't directly
call another trigger within a trigger. We can only achieve nesting of triggers in which the
action (insert, delete, and update) defined within a trigger can initiate execution of another
trigger defined on the same table or a different table.
3. Stored procedures can be scheduled through a job to execute on a predefined time, but we
can't schedule a trigger.
4. Stored procedure can take input parameters, but we can't pass parameters as input to a
trigger.
5. Stored procedures can return values but a trigger cannot return a value.

Focus Trainig Services, Pune Page 144


6. We can use Print commands inside a stored procedure for debugging purposes but we can't
use print commands inside a trigger.
7. We can use transaction statements like begin transaction, commit transaction, and rollback
inside a stored procedure but we can't use transaction statements inside a trigger.
8. We can call a stored procedure from the front end (.asp files, .aspx files, .ascx files, etc.) but
we can't call a trigger from these files.
9. Stored procedures are used for performing tasks. Stored procedures are normally used for
performing user specified tasks. They can have parameters and return multiple results sets.
10. The Triggers for auditing work: Triggers normally are used for auditing work. They can be used
to trace the activities of table events.

Triggers are fully compiled when the CREATE TRIGGER command is issued and the P code is

stored in the data dictionary. If errors occur during the compilation of a trigger, the trigger is still

created.

10.10 Managing Triggers:

10.10.1 Disable or reenable a database trigger:


ALTER TRIGGER trigger_name DISABLE | ENABLE;

10.10.2 Disable or reenable all triggers for a table:


ALTER TABLE table_name DISABLE | ENABLE ALL TRIGGERS;

10.10.3 Recompile a trigger for a table:


ALTER TRIGGER trigger_name COMPILE;

10.11 DROP TRIGGER Syntax


To remove a trigger from the database, use the DROP TRIGGER syntax:

DROP TRIGGER trigger_name;

Example:
DROP TRIGGER secure_emp;

Focus Trainig Services, Pune Page 145


10.11.1 Testing Triggers
 Ensure that the trigger works properly by testing a number of cases separately.
 Take advantage of the DBMS_OUTPUT procedures to debug triggers. You can also use the
Procedure Builder debugging tool to debug triggers.

10.11.2 Trigger Execution Model and Constraint Checking


1. Execute all BEFORE STATEMENT triggers.
2. Loop for each row affected:
a. Execute all BEFORE ROW triggers.
b. Execute all AFTER ROW triggers.
3. Execute the DML statement and perform integrity constraint checking.
4. Execute all AFTER STATEMENT triggers.

10.12 Trigger Execution Model


A single DML statement can potentially fire up to four types of triggers: BEFORE and AFTER
statement and row triggers. A triggering event or a statement within the trigger can cause one or
more integrity constraints to be checked. Triggers can also cause other triggers to fire (cascading
triggers). All actions and checks done as a result of a SQL statement must succeed. If an exception is
raised within a trigger and the exception is not explicitly handled, all actions performed because of
the original SQL statement are rolled back. This includes actions performed by firing triggers. This
guarantees that integrity constraints can never be compromised by triggers. When a trigger fires, the
tables referenced in the trigger action may undergo changes by other users transactions. In all cases,
a read-consistent image is guaranteed for modified values the trigger needs to read (query) or write
(update)

10.13 Trigger Execution Model and Constraint Checking:


Example
Step1:
CREATE OR REPLACE TRIGGER constr_emp_trig
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
INSERT INTO departments
VALUES (999, 'dept999', 140, 2400);

Focus Trainig Services, Pune Page 146


END;
/

Step2:
UPDATE employees SET department_id = 999
WHERE employee_id = 170;
-- Successful after trigger is fired

The example in the slide explains a situation in which the integrity constraint can be taken care of by
using a trigger. Table EMPLOYEES has a foreign key constraint on the DEPARTMENT_ID column of the
DEPARTMENTS table.
In the first SQL statement, the DEPARTMENT_ID of the employee with EMPLOYEE_ID 170 is modified
to 999. Because such a department does not exist in the DEPARTMENTS table, the statement raises
the exception -2292 for the integrity constraint violation.
A trigger CONSTR_EMP_TRIG is created that inserts a new department 999 into the DEPARTMENTS
table.
When the UPDATE statement that modifies the department of employee 170 to 999 is issued, the
trigger fires. Then, the foreign key constraint is checked. Because the trigger inserted the department
999 into the DEPARTMENTS table, the foreign key constraint check is successful and there is no
exception.

Practice Example:

1)Create a trigger to allow only certain employees to be able to earn a salary of more than 15,000.

Focus Trainig Services, Pune Page 147


11.
COLLECTIONS AND RECORDS
Objectives
1) Create user-defined PL/SQL records
2) Create a Varray
3) Create a Nested Table
4) Create an Associative Array
5) Create an Associative Array of records
6) Describe the difference between records, tables and tables of records

11.1 Composite Data Types


1) Are of two types:
 PL/SQL RECORDs
 PL/SQL Collections
 Associative Array
 Nested Table
 VARRAY

2) Contain internal components


3) Are reusable

11.2 RECORD and TABLE Data Types


Like scalar variables, composite variables have a data type. Composite data types (also known as
collections) are RECORD, TABLE, NESTED TABLE, and VARRAY. You use the RECORD data type to treat
related but dissimilar data as a logical unit. You use the TABLE data type to reference and manipulate
collections of data as a whole object. A record is a group of related data items stored as fields, each
with its own name and data type. A table contains a column and a primary key to give you array-like
access to rows. After they are defined, tables and records can be reused.

Focus Trainig Services, Pune Page 148


11.3 PL/SQL Records
 Must contain one or more components of any scalar, RECORD, or Associative Array data type,
called fields
 Are similar in structure to records in a third generation language (3GL)
 Are not the same as rows in a database table
 Treat a collection of fields as a logical unit
 Are convenient for fetching a row of data from a table for processing

11.3.1 Creating a PL/SQL Record


Syntax:
Where field_declaration is:
TYPE type_name IS RECORD
(field_declaration[, field_declaration]…);
identifier type_name;
field_name {field_type | variable%TYPE
| table.column%TYPE | table%ROWTYPE}
[[NOT NULL] {:= | DEFAULT} expr]

11.3.2 Defining and Declaring a PL/SQL Record


To create a record, you define a RECORD type and then declare records of that type. In the syntax:
type_name is the name of the RECORD type. (This identifier is used to declare records.) field_name is
the name of a field within the record. field_type is the data type of the field. (It represents any
PL/SQL data type except REF CURSOR. You can use the %TYPE and %ROWTYPE attributes.) expr is the
field_type or an initial value.
The NOT NULL constraint prevents assigning nulls to those fields. Be sure to initialize NOT NULL
fields.

Declare variables to store the name, job, and salary of a new employee.
Example:
...
TYPE emp_record_type IS RECORD
(last_name VARCHAR2(25),
job_id VARCHAR2(10),

Focus Trainig Services, Pune Page 149


salary NUMBER(8,2));
emp_record emp_record_type;
...

Field declarations are like variable declarations. Each field has a unique name and a specific data
type. There are no predefined data types for PL/SQL records, as there are for scalar variables.
Therefore, you must create the record type first and then declare an identifier using that type. In the
example on the slide, a EMP_RECORD_TYPE record type is defined to hold the values for the
last_name, job_id, and salary. In the next step, a record EMP_RECORD, of the type
EMP_RECORD_TYPE is declared.
Note: You can add the NOT NULL constraint to any field declaration to prevent assigning nulls to that
field. Remember, fields declared as NOT NULL must be initialized.

11.4 PL/SQL Record Structure


Fields in a record are accessed by name. To reference or initialize an individual field, use dot notation
and the following
syntax:

record_name.field_name

11.5 The %ROWTYPE Attribute


• Declare a variable according to a collection of columns in a database table or view.
• Prefix %ROWTYPE with the database table.
• Fields in the record take their names and data types from the columns of the table or
view.

11.5.1 Declaring Records with the %ROWTYPE Attribute


To declare a record based on a collection of columns in a database table or view, you use the
%ROWTYPE attribute. The fields in the record take their names and data types from the columns of
the table or view. The record can also store an entire row of data fetched from a cursor or cursor
variable. In the following example, a record is declared using %ROWTYPE as a data type specifier.

DECLARE
emp_record employees%ROWTYPE;

Focus Trainig Services, Pune Page 150


The emp_record record will have a structure consisting of the following fields, each representing a

column in the EMPLOYEES table.

Syntax:
DECLARE
identifier reference%ROWTYPE;

where: identifier is the name chosen for the record as a whole. reference is the name of the table,
view, cursor, or cursor variable on which the record is to be based. The table or view must exist for
this reference to be valid. To reference an individual field, you use dot notation and the following
syntax:

record_name.field_name

11.5.2 Advantages of Using %ROWTYPE


 The number and data types of the underlying database columns need not be
known.

 The number and data types of the underlying database column may change at run
time.
 The attribute is useful when retrieving a row with the SELECT * statement.

11.6 VARRAY
They are densely populated arrays (no gaps in the index sequence) and behave like traditional
programming arrays. They can be accessed by either SQL or PL/SQL, at creation they have a fixed size
which cannot be changed. Varrays use sequential integers for there subscripts (index), however the
subscript starts from 1 not 0.
Varrays are single dimensional structures which can be used in table, record and object definitions,
they can be accessed via both SQL and PL/SQL. Varrays have to be defined, declared and initialized
also remember that the subscript starts at 1 not 0
Example:

declare
type int_array is varray(5) of number;

Focus Trainig Services, Pune Page 151


a int_array:=int_array(3,4,6,7,1);
temp number;
begin
for i in a.first..a.last loop
for j in a.first..a.last-i loop
if(a(j)<a(j+1)) then
temp:=a(j);
a(j):=a(j+1);
a(j+1):=temp;
end if;
end loop;
end loop;
dbms_output.put_line('The sorted array is:=');
for i in a.first..a.last loop
dbms_output.put_line(a(i));
end loop;
end;
/

Output:

SQL> @ap1.sql
The sorted array is:=
7
6
4
3
1

PL/SQL procedure successfully completed

Example 2:

declare

Focus Trainig Services, Pune Page 152


type char1 is varray(5) of varchar2(10);
c1 char1:=char1();
begin
c1.extend;
c1(1):='ABC';
c1.extend;
c1(2):='XYZ';
dbms_output.put_line('Array Elements are:');
for i in c1.first..c1.last
loop
dbms_output.put_line(c1(i));
end loop;
end;
/

Output:

SQL> @ap2.sql
Array Elements are:
ABC
XYZ

PL/SQL procedure successfully completed.

11.7 Nested Table


They are initially defined as densely populated arrays but become sparsely populated when records
are deleted. They can be accessed by either SQL or PL/SQL, they can also be dynamically extended.
Nested Tables use sequential integers for there subscripts (index), however the subscript starts from
1 not 0.
You would use nested tables when the physical size is unknown due to run-time variations and when
the type may be used in tables. These are like the traditional lists or bags in other programming
languages

Focus Trainig Services, Pune Page 153


Nested Tables are single dimensional structures which can be used in table, record and object
definitions, they can be accessed via both SQL and PL/SQL. Nested Tables have to be defined,
declared and initialized, also remember that the subscript starts at 1 not 0. The size of a Nested table
is only constrained with the available memory in the SGA
Example

Step1:

create or replace type card1 is table of varchar2(5);

Step2:

declare
c1 card1:=card1(null,null,null);
begin
c1(1):='Ace';
c1(2):='Two';
c1(3):='Three';
dbms_output.put_line('Array Elements:');
for i in 1..3
loop
dbms_output.put_line(c1(i));
end loop;
end;
/

Step3:

Output:
SQL> @ap3.sql
Type created.
Array Elements:
Ace
Two
Three

Focus Trainig Services, Pune Page 154


PL/SQL procedure successfully completed.

Note: extend is a method that adds a new empty element to a nested table, this must be called
first.

11.8 Associative Array (Index By Table)


They are a sparsely populated array which means the numbering does not have to be sequential,
only unique. The subscript supports either unique integers or strings, they can grow dynamically but
they can only be accessed via PL/SQL.
Associative arrays use sequential or non-sequential integers or strings for there subscript.
You would associative arrays when the physical size is unknown due to run-time variations and when
the type will not be used in tables. These are like the traditional sets or maps in other programming
languages.
Associated Arrays are single dimensional structures which can be used in programming structures.
They can only be accessed in PL/SQL, they have a different approach t 
 
 Do not require initialization and have no constructor syntax, they do not need to allocate space
before assign values (no extend method).
 Can be indexed numerically or use unique variable-length strings
 Can use any integer as index value which means any negative, positive or zero whole number
 Are implicitly converted from equivalent %rowtype, record type and object type return values to
associative array structures
 Are the key to using the forall statement or bulk collect clause, which enablesbulk transfers of
records from a database table to a programming unit

You cannot store an associative array directly in the database, so you need logic to store and retrieve
the values in this type of collection with the database, it also cannot be use in SQL.Varrays and
Nested tables

Example:
create or replace procedure asso1
is

Focus Trainig Services, Pune Page 155


type arr is varray(5) of varchar2(30);
type asso is table of varchar2(30) index by varchar2(5);
arr1 arr:=arr('A','B','C','D','E');
asso1 asso;
begin

asso1(arr1(1)):='Ant';
asso1(arr1(2)):='Bat';
asso1(arr1(3)):='Cat';
asso1(arr1(4)):='Deer';
asso1(arr1(5)):='Egg';

dbms_output.put_line('Associative Table Elements');


for i in 1..5
loop
dbms_output.put_line(asso1(arr1(i))||' '||arr1(i));
end loop;
end;
/

Output:

SQL> @ap4.sql
ddl event occure

Procedure created.

SQL> exec asso1


Associative Table Elements
Ant A
Bat B
Cat C
Deer D
Egg E

Focus Trainig Services, Pune Page 156


PL/SQL procedure successfully completed.

11.8.1 Using Associative Array Methods


The following methods make Associative Array easier to use:
 NEXT
 TRIM
 DELETE
 EXISTS
 COUNT
 FIRST and LAST
 PRIOR
A Associative Array method is a built-in procedure or function that operates on tables and is called
using dot notation.
Syntax:
array_name.method_name[ (parameters) ]

11.8.2 Method Description


 EXISTS(n) Returns TRUE if the nth element in a PL/SQL table exists
 COUNT Returns the number of elements that a PL/SQL table currently contains
 FIRST, LAST Returns the first and last (smallest and largest) index numbers in a
PL/SQL table. Returns NULL if the PL/SQL table is empty.
 PRIOR(n) Returns the index number that precedes index n in a PL/SQL table
 NEXT(n) Returns the index number that succeeds index n in a PL/SQL table
 TRIM removes one element from the end of a PL/SQL table.
 TRIM(n) removes n elements from the end of a PL/SQL table.
 DELETE removes all elements from a PL/SQL table.
 DELETE(n) removes the nth element from a PL/SQL table.
 DELETE(m, n) removes all elements in the range m ... n from a PL/SQL table.

Focus Trainig Services, Pune Page 157


11.8.3 Associative Array of Records
 Define a TABLE variable with a permitted PL/SQL data type.
 Declare a PL/SQL variable to hold department information.
Example:
DECLARE
TYPE dept_table_type IS TABLE OF
departments%ROWTYPE
INDEX BY BINARY_INTEGER;
dept_table dept_table_type;
-- Each element of dept_table is a record

At a given point of time, a Associative Array can store only the details of any one of the columns of a
database table. There is always a necessity to store all the columns retrieved by a query. The
Associative Array of records offers a solution to this. Because only one table definition is needed to
hold information about all of the fields of a database table, the table of records greatly increases the
functionality of Associative Arrays.

11.9 Summary
In this chapter, you should have learned to:
• Define and reference PL/SQL variables of composite data types:
– PL/SQL records
– Associative Arrays
– Associative Array of records

• Define a PL/SQL record by using the %ROWTYPE attribute
A PL/SQL record is a collection of individual fields that represent a row in a table. By using records
you can group the data into one structure and then manipulate this structure as one entity or logical
unit. This helps reduce coding, and keeps the code easier to maintain and understand.
Like PL/SQL records, the table is another composite data type. Associative Arrays are objects of a
TABLE type and look similar to database tables but with a slight difference. Associative Arrays use a
primary key to give you array-like accessto rows. The size of a Associative Array is unconstrained.
Associative Arrays can have one column and a primary key, neither of which can be named. The
column can have any data type, but the primary key must be of the BINARY_INTEGER type.

Focus Trainig Services, Pune Page 158


Associative Array of records enhances the functionality of Associative Arrays, because only one table
definition is required to hold information about all the fields.
The following collection methods help generalize code, make collections easier to use, and make
your applications easier to maintain: EXISTS, COUNT, LIMIT, FIRST and LAST, PRIOR and NEXT, TRIM
and DELETE The %ROWTYPE is used to declare a compound variable whose type is the same as that
of a row of a database table.

Focus Trainig Services, Pune Page 159


12.
BULK BINDING
Objectives
1) Bulk binding

2) Tuning PL/SQL performance with bulk binding

3) How do bulk binds improve performance

4) Using the FOR ALL statement

12.1 Tuning PL/SQL Performance with Bulk Binds


When SQL statements execute inside a loop using collection elements as bind variables, context
switching between the PL/SQL and SQL engines can slow down execution. For example, the following
UPDATE statement is sent to the SQL engine with each iteration of the FOR loop:
create or replace procedure bulk_collect
is
type namelist is table of employees.last_name%type;
type sallist is table of employees.salary%type;
cursor c1 is select last_name,salary from employees where salary>1000;
names namelist;
sals sallist;
begin
open c1;
fetch c1 bulk collect into names,sals;
dbms_output.put_line('The Names of employees :');
for i in names.first..names.last
loop
dbms_output.put_line(names(i));
end loop;

dbms_output.put_line('The salaries of employees :');

Focus Trainig Services, Pune Page 160


for i in sals.first..sals.last
loop
dbms_output.put_line(sals(i));
end loop;
close c1;
end;
/

Output:

SQL> @ap8.sql

Procedure created.

SQL> exec bulk_collect

The Names of employees :


OConnell
Grant
Whalen
Hartstein
Fay
Mavris
Baer
Higgins

The Salaries of employees :


2800
2800
4600
13200
6200
6700
10200
12200

Focus Trainig Services, Pune Page 161


To maximize performance, rewrite your programs as follows:
 If an INSERT, UPDATE, or DELETE statement executes inside a loop and references collection
elements, move it into a FORALL statement.
 If a SELECT INTO, FETCH INTO, or RETURNING INTO clause references a collection, incorporate
the BULK COLLECT clause.
 If possible, use host arrays to pass collections back and forth between your programs and the
database server.
 If the failure of a DML operation on a particular row is not a serious problem, include the
keywords SAVE EXCEPTIONS in the FORALL statement and report or clean up the errors in a
subsequent loop using the %BULK_EXCEPTIONS attribute.
 These are not a trivial tasks. They require careful analysis of program control-flows and
dependencies.

12.2 Reducing Loop Overhead for Collections with Bulk Binds


As the figure below shows, the PL/SQL engine executes procedural statements but sends SQL
statements to the SQL engine, which executes the SQL statements and, in some cases, returns data
to the PL/SQL engine.

Too many context switches between the PL/SQL and SQL engines can harm performance. That can
happen when a loop executes a separate SQL statement for each element of a collection, specifying

Focus Trainig Services, Pune Page 162


the collection element as a bind variable. For example, the following DELETE statement is sent to the
SQL engine with each iteration of the FOR loop:
DECLARE
TYPE NumList IS VARRAY(20) OF NUMBER;
depts NumList := NumList(10, 30, 70); -- department numbers
BEGIN
...
FOR i IN depts.FIRST..depts.LAST LOOP
DELETE FROM emp WHERE deptno = depts(i);
END LOOP;
END;
/
In such cases, if the SQL statement affects four or more database rows, the use of bulk binds can
improve performance considerably.

12.3 Bulk Binds Improve

Q. How Do Bulk Binds Improve Performance?


The assigning of values to PL/SQL variables in SQL statements is called binding. PL/SQL binding
operations fall into three categories:

 in-bind When a PL/SQL variable or host variable is stored in the database by an INSERT or
UPDATE statement.

 out-bind When a database value is assigned to a PL/SQL variable or a host variable by the
RETURNING clause of an INSERT, UPDATE, or DELETE statement.

 define When a database value is assigned to a PL/SQL variable or a host

variable by a SELECT or FETCH statement.


A DML statement can transfer all the elements of a collection in a single operation, a process known
as bulk binding. If the collection has 20 elements, bulk binding lets you perform the equivalent of 20
SELECT, INSERT, UPDATE, or DELETE statements using a single operation. This technique improves
performance by minimizing the number of

Focus Trainig Services, Pune Page 163


context switches between the PL/SQL and SQL engines. With bulk binds, entire collections, not just
individual elements, are passed back and forth. To do bulk binds with INSERT, UPDATE, and DELETE
statements, you enclose the SQL statement within a PL/SQL FORALL statement. To do bulk binds with
SELECT statements, you include the BULK COLLECT clause in the SELECT statement instead of using
INTO.

Example: Performing a Bulk Bind with DELETE


The following DELETE statement is sent to the SQL engine just once, even though it performs three
DELETE operations:
DECLARE
TYPE NumList IS VARRAY(20) OF NUMBER;
depts NumList := NumList(10, 30, 70); -- department numbers
BEGIN
FORALL i IN depts.FIRST..depts.LAST
DELETE FROM emp WHERE deptno = depts(i);
END;
/

Example: Performing a Bulk Bind with INSERT


In the example below, 5000 part numbers and names are loaded into index-by tables. All table elements
are inserted into a database table twice: first using a FOR loop, then using a FORALL statement. The
FORALL version is much faster.
Step1:
SQL> SET SERVEROUTPUT ON
SQL> CREATE TABLE parts (pnum NUMBER(4), pname CHAR(15));
Table created.
SQL> GET test.sql

Step2:
DECLARE
TYPE NumTab IS TABLE OF NUMBER(4) INDEX BY BINARY_INTEGER;
TYPE NameTab IS TABLE OF CHAR(15) INDEX BY BINARY_INTEGER;
pnums NumTab;
pnames NameTab;

Focus Trainig Services, Pune Page 164


t1 NUMBER(5);
t2 NUMBER(5);
t3 NUMBER(5);

BEGIN
FOR j IN 1..5000 LOOP -- load index-by tables
pnums(j) := j;
pnames(j) := ’Part No. ’ || TO_CHAR(j);
END LOOP;
t1 := dbms_utility.get_time;
FOR i IN 1..5000 LOOP -- use FOR loop
INSERT INTO parts VALUES (pnums(i), pnames(i));
END LOOP;
t2 := dbms_utility.get_time;
FORALL i IN 1..5000 -- use FORALL statement
INSERT INTO parts VALUES (pnums(i), pnames(i));
get_time(t3);
dbms_output.put_line(’Execution Time (secs)’);
dbms_output.put_line(’---------------------’);
dbms_output.put_line(’FOR loop: ’ || TO_CHAR(t2 - t1));
dbms_output.put_line(’FORALL: ’ || TO_CHAR(t3 - t2));
END;

Step3:

SQL> /
Execution Time (secs)
---------------------
FOR loop: 32
FORALL: 3
PL/SQL procedure successfully completed.

Focus Trainig Services, Pune Page 165


12.4 Using the FORALL Statement
The keyword FORALL instructs the PL/SQL engine to bulk-bind input collections before sending them
to the SQL engine. Although the FORALL statement contains an iteration scheme, it is not a FOR loop.
Its syntax follows:

FORALL index IN lower_bound..upper_bound sql_statement;

The index can be referenced only within the FORALL statement and only as a collection subscript. The
SQL statement must be an INSERT, UPDATE, or DELETE statement that references collection
elements. And, the bounds must specify a valid range of consecutive index numbers. The SQL engine
executes the SQL statement once for each index number in the range.

Counting Rows Affected by FORALL Iterations with the %BULK_ROWCOUNT Attribute

To process SQL data manipulation statements, the SQL engine opens an implicitcursor named SQL.
This cursor’s scalar attributes, %FOUND, %ISOPEN,

%NOTFOUND, and %ROWCOUNT, return useful information about the most recently executed SQL
data manipulation statement.

The SQL cursor has one composite attribute, %BULK_ROWCOUNT, designed for use with the FORALL
statement. This attribute has the semantics of an index-by table. Its ith element stores the number of
rows processed by the ith execution of an INSERT, UPDATE or DELETE statement. If the ith execution
affects no rows, %BULK_ROWCOUNT(i) returns zero. An example follows:
DECLARE
TYPE NumList IS TABLE OF NUMBER;
depts NumList := NumList(10, 20, 50);
BEGIN
FORALL j IN depts.FIRST..depts.LAST
UPDATE emp SET sal = sal * 1.10 WHERE deptno = depts(j);
-- Did the 3rd UPDATE statement affect any rows?
IF SQL%BULK_ROWCOUNT(3) = 0 THEN ...
END;
/

Focus Trainig Services, Pune Page 166


The FORALL statement and %BULK_ROWCOUNT attribute use the same subscripts.
For example, if FORALL uses the range 5 .. 10, so does %BULK_ROWCOUNT.
%BULK_ROWCOUNT is usually equal to 1 for inserts, because a typical insert operation affects only a
single row. But for the INSERT ... SELECT construct, %BULK_ROWCOUNT might be greater than 1. For
example, the FORALL statement below inserts an arbitrary number of rows for each iteration. After
each iteration, %BULK_ROWCOUNT returns the number of items inserted:
You can also use the scalar attributes %FOUND, %NOTFOUND, and %ROWCOUNT with bulk binds.
For example, %ROWCOUNT returns the total number of rows processed by all executions of the SQL
statement.
%FOUND and %NOTFOUND refer only to the last execution of the SQL statement.
However, you can use %BULK_ROWCOUNT to infer their values for individual executions. For
example, when %BULK_ROWCOUNT(i) is zero, %FOUND and %NOTFOUND are FALSE and TRUE,
respectively.

12.5 Handling FORALL Exceptions with the %BULK_EXCEPTIONS Attribute

PL/SQL provides a mechanism to handle exceptions raised during the execution of a FORALL
statement. This mechanism enables a bulk-bind operation to save information about exceptions and
continue processing.
To have a bulk bind complete despite errors, add the keywords SAVE EXCEPTIONS to your FORALL
statement. The syntax follows:
FORALL index IN lower_bound..upper_bound SAVE EXCEPTIONS {insert_stmt | update_stmt |
delete_stmt}
All exceptions raised during the execution are saved in the new cursor attribute %BULK_EXCEPTIONS,
which stores a collection of records. Each record has two fields. The first field,
%BULK_EXCEPTIONS(i).ERROR_INDEX, holds the "iteration" of the FORALL statement during which
the exception was raised. The second field, %BULK_EXCEPTIONS(i).ERROR_CODE, holds the
corresponding Oracle error code.
The values stored by %BULK_EXCEPTIONS always refer to the most recently executed FORALL
statement. The number of exceptions is saved in the count attribute of %BULK_EXCEPTIONS, that is,
%BULK_EXCEPTIONS.COUNT. Its subscripts range from 1 to COUNT.
If you omit the keywords SAVE EXCEPTIONS, execution of the FORALL statement stops when an
exception is raised. In that case, SQL%BULK_EXCEPTIONS.COUNT returns 1, and

Focus Trainig Services, Pune Page 167


SQL%BULK_EXCEPTIONS contains just one record. If no exception is raised during execution,
SQL%BULK_EXCEPTIONS.COUNT returns 0. The following example shows how useful the cursor
attribute %BULK_EXCEPTIONS can be:
DECLARE
TYPE NumList IS TABLE OF NUMBER;
num_tab NumList := NumList(10,0,11,12,30,0,20,199,2,0,9,1);
errors NUMBER;
dml_errors EXCEPTION;
PRAGMA exception_init(dml_errors, -24381);
BEGIN
FORALL i IN num_tab.FIRST..num_tab.LAST SAVE EXCEPTIONS
DELETE FROM emp WHERE sal > 500000/num_tab(i);
EXCEPTION
WHEN dml_errors THEN
errors := SQL%BULK_EXCEPTIONS.COUNT;
dbms_output.put_line(’Number of errors is ’ || errors);
FOR i IN 1..errors LOOP
dbms_output.put_line(’Error ’ || i || ’ occurred during ’||
’iteration ’ || SQL%BULK_EXCEPTIONS(i).ERROR_INDEX);
dbms_output.put_line(’Oracle error is ’ ||
SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
END LOOP;
END;
/

In this example, PL/SQL raised the predefined exception ZERO_DIVIDE when I equalled 2, 6, 10. After
the bulk-bind completed, SQL%BULK_EXCEPTIONS.COUNT returned 3, and the contents of
SQL%BULK_EXCEPTIONS were (2,1476), (6,1476), and (10,1476). To get the Oracle error message
(which includes the code), we negated the value of SQL%BULK_EXCEPTIONS(i).ERROR_CODE and
passed the result to the error-reporting function SQLERRM, which expects a negative number.Here is
the
OUTPUT:

Number of errors is 3
Error 1 occurred during iteration 2

Focus Trainig Services, Pune Page 168


Oracle error is ORA-01476: divisor is equal to zero
Error 2 occurred during iteration 6
Oracle error is ORA-01476: divisor is equal to zero
Error 3 occurred during iteration 10
Oracle error is ORA-01476: divisor is equal to zero

12.6 Retrieving Query Results into Collections with the BULK COLLE Clause
The keywords BULK COLLECT tell the SQL engine to bulk-bind output collections before returning
them to the PL/SQL engine. You can use these keywords in the SELECT INTO, FETCH INTO, and
RETURNING INTO clauses.
Here is the syntax:
... BULK COLLECT INTO collection_name[, collection_name] ...

The SQL engine bulk-binds all collections referenced in the INTO list. The corresponding columns can
store scalar or composite values including objects. In the following example, the SQL engine loads the
entire empno and ename database columns into nested tables before returning the tables to the
PL/SQL engine:
DECLARE
TYPE NumTab IS TABLE OF emp.empno%TYPE;
TYPE NameTab IS TABLE OF emp.ename%TYPE;
enums NumTab; -- no need to initialize
names NameTab;
BEGIN
SELECT empno, ename BULK COLLECT INTO enums, names FROM emp;
...
END;
/

The SQL engine initializes and extends collections for you. (However, it cannot extend varrays beyond
their maximum size.) Then, starting at index 1, it inserts elements consecutively and overwrites any
pre-existent elements. The SQL engine bulk-binds entire database columns. So, if a table has 50,000
rows, the engine loads 50,000 column values into the target collection. However, you can use the
pseudocolumn ROWNUM to limit the number of rows processed.

Focus Trainig Services, Pune Page 169


Examples of Bulk Fetching from a Cursor Into One or More Collections
You can bulk-fetch from a cursor into one or more collections:
DECLARE
TYPE NameList IS TABLE OF emp.ename%TYPE;
TYPE SalList IS TABLE OF emp.sal%TYPE;
CURSOR c1 IS SELECT ename, sal FROM emp WHERE sal > 1000;
names NameList;
sals SalList;
BEGIN
OPEN c1;
FETCH c1 BULK COLLECT INTO names, sals;
END;
/

Into a Collection of Records


You can bulk-fetch from a cursor into a collection of records:
DECLARE
TYPE DeptRecTab IS TABLE OF dept%ROWTYPE;
dept_recs DeptRecTab;
CURSOR c1 IS
SELECT deptno, dname, loc FROM dept WHERE deptno > 10;
BEGIN
OPEN c1;
FETCH c1 BULK COLLECT INTO dept_recs;
END;
/

Limiting the Rows for a Bulk FETCH Operation with the LIMIT Clause
The optional LIMIT clause, allowed only in bulk (not scalar) FETCH statements, lets you limit the
number of rows fetched from the database. The syntax is

FETCH ... BULK COLLECT INTO ... [LIMIT rows];

where rows can be a literal, variable, or expression but must evaluate to a number. Otherwise,
PL/SQL raises the predefined exception VALUE_ERROR. If the number is not positive, PL/SQL raises
INVALID_NUMBER. If necessary, PL/SQL rounds the number to the nearest integer.
Focus Trainig Services, Pune Page 170
Retrieving DML Results into a Collection with the RETURNING INTO Clause
You can use the BULK COLLECT clause in the RETURNING INTO clause of an INSERT, UPDATE, or
DELETE statement, as the following example shows:
DECLARE
TYPE NumList IS TABLE OF emp.empno%TYPE;
enums NumList;
BEGIN
DELETE FROM emp WHERE deptno = 20
RETURNING empno BULK COLLECT INTO enums;
-- if there were five employees in department 20,
-- then enums contains five employee numbers
END;
/

12.7 Restrictions on BULK COLLECT


The following restrictions apply to the BULK COLLECT clause:
1) You cannot bulk collect into an associative array that has a string type for the key.
2) You can use the BULK COLLECT clause only in server-side programs (not in client-side
programs). Otherwise, you get the error this feature is not supported in client-side programs.
3) All targets in a BULK COLLECT INTO clause must be collections, as the
following example shows:
DECLARE
TYPE NameList IS TABLE OF emp.ename%TYPE;
names NameList;
salary emp.sal%TYPE;
BEGIN
SELECT ename, sal BULK COLLECT INTO names, salary -- illegal
target
FROM emp WHERE ROWNUM < 50;
...
END;
/

Focus Trainig Services, Pune Page 171


4) Composite targets (such as objects) cannot be used in the RETURNING INTO clause.
Otherwise, you get the error unsupported feature with RETURNING clause.
5) When implicit datatype conversions are needed, multiple composite targets cannot be
used in the BULK COLLECT INTO clause.
6) When an implicit datatype conversion is needed, a collection of a composite target (such as
a collection of objects) cannot be used in the BULK COLLECT INTO clause.

12.8 Using FORALL and BULK COLLECT Together


You can combine the BULK COLLECT clause with a FORALL statement, in which case, the SQL engine
bulk-binds column values incrementally. In the following example, if collection depts has 3 elements,
each of which causes 5 rows to be deleted, then collection enums has 15 elements when the
statement completes:
FORALL j IN depts.FIRST..depts.LAST
DELETE FROM emp WHERE empno = depts(j)
RETURNING empno BULK COLLECT INTO enums;

The column values returned by each execution are added to the values returned previously. (With a
FOR loop, the previous values are overwritten.)
You cannot use the SELECT ... BULK COLLECT statement in a FORALL statement. Otherwise, you get
the error implementation restriction: cannot use FORALL and BULK COLLECT INTO together in
SELECT statements.

12.9 Summary

In this chapter, we learned that Binding an entire collection at once is called bulk binding. Bulk binds
improve performance by minimizing the number of context switches between the PL/SQL and SQL
engines. With bulk binds, entire collections, not just individual elements, are passed back and forth.
The keyword FORALL instructs the PL/SQL engine to bulk bind input collections before sending them
to the SQL engine. Although the FORALL statement contains an iteration scheme, it is not a FOR loop.
Tuning performance with bulk binds and reduce loop overhead for collections. Bulk collect and
restrictions in using bulk collect.

Focus Trainig Services, Pune Page 172


13.
Advanced Cursor
Objectives:
1) Cursor Variables
2) Why Use Cursor Variables?
3) Defining a Cursor Variable
4) Dynamism in Using Cursor Variables

13.1 Cursor Variables


An explicit cursor once declared was associated with a specific query—only the one specific query
that was known at compile time. In this way, the cursor declared was static and couldn’t be changed
at runtime. It always pointed to the same work area until the execution of the program completed.
However, you may sometimes want to have a variable that can point to different work areas
depending on runtime conditions. PL/SQL 2.2 onward offers this facility by means of cursor variables.
A cursor variable is a single PL/SQL variable that you can associate with different queries at runtime.
The same variable can point to different work areas. In this way, cursor variables and cursors are
analogous to PL/SQL variables and constants, but from a cursor perspective. A cursor variable acts
like a pointer that holds the address of a specific work area defined by the

13.2 Why Use Cursor Variables?


The primary advantage of using cursor variables is their capability to pass resultsets between stored
subprograms. Before cursor variables, this wasn’t possible. Now, with cursor variables, the work area
that a cursor variable points to remains accessible as long as the variable points to it. Hence, you can
point a cursor variable to a work area by opening a cursor for it, and then any application such as
Pro*C, an Oracle client, or another server application can fetch from the corresponding resultset.
Another advantage of cursor variables is their introduction of a sort of dynamism, in that a single
cursor variable can be associated with multiple queries at runtime.query it’s pointing to.

13.3 Defining a Cursor Variable


Defining a cursor variable consists of defining a pointer of type REF CURSOR and defining a variable
of this type. These steps are outlined in the following sections.
Focus Trainig Services, Pune Page 173
13.3.1 Defining a Pointer of Type CURSOR
In PL/SQL, a pointer is declared using the syntax

 REF type
The keyword REF implies that the new type so defined is a pointer to the defined type. PL/SQL offers two
types of REF types: CURSOR and an object type. So, the definition of a cursor variable involves the
definition of a REF CURSOR first, as shown here:
TYPE rc IS REF CURSOR;

13.3.2 Defining a Variable of Type REF CURSOR


Once you’ve defined a REF CURSOR type, the next step is to declare a variable of this type. Here’s the
code for this:
v_rc rc;

So the complete declaration of a cursor variable is as follows:


TYPE rc IS REF CURSOR;
v_rc rc;

This code suggests that rc is a pointer of type CURSOR and v_rc (in fact, any variable) defined of type
rc points to a SQL cursor.

13.3.3 Strong and Weak REF CURSOR Types


The REF CURSOR type defined earlier is called a weak REF CURSOR type. This is because it doesn’t
dictate the return type of the cursor. Hence, it can point to any SELECT query with any number of
columns. Weak cursor types are available in PL/SQL 2.3 and higher versions. PL/SQL lets you define a
strong REF CURSOR having a return type using the following
syntax:

TYPE ref_type_name IS REF CURSOR RETURN return_type;

Here, ref_type_name is the name of the new pointer name and return_type is a record type of either
%ROWTYPE or a user-defined record type. For example, you can declare strong REF CURSORS as
follows:

Focus Trainig Services, Pune Page 174


TYPE rc is REF CURSOR RETURN hrc_tab%ROWTYPE;
v_rc rc;
or
TYPE hrc_rec is RECORD (hrc_code NUMBER, hrc_name VARCHAR2(20));
TYPE rc IS REF CURSOR RETURN hrc_rec;

13.4 Using a Cursor Variable


Once you’ve defined a cursor variable, you can use it to associate it with a query.
Here are the steps:
1. Allocate memory.
2. Open the cursor variable for a query.

3. Fetch the results into a PL/SQL record or individual PL/SQL variables.


4. Close the cursor variable.

The following sections provide more detail about each step in the process.

13.4.1 Allocate Memory


Once you declare a cursor variable in PL/SQL, the PL/SQL engine in PL/SQL 2.3 and higher versions
automatically allocates memory for storage of rows. Prior to PL/SQL 2.3, a host environment was
needed to explicitly allocate memory to a cursor variable. 15.4.2 Opening the Cursor Variable Once
you’ve defined a cursor variable, you have to open it for a multirow query, either with an arbitrary
number of columns in the case of a weak REF CURSOR or with a\ type-compatible query in the case
of a strong REF CURSOR. Opening the cursor variable identifies the associated query, executes it, and
also identifies the resultset.

You open a cursor variable using the OPEN-FOR statement. Here’s the syntax:

OPEN {cursor_variable_name | :host_cursor_variable_name} FOR


{ select_query
| dynamic_string [USING bind_variable[, bind_variable] . . . ] };
where cursor_variable_name is the name of the declared cursor variable and select_query is the
SELECT query associated with the cursor variable. Also, host_cursor_variable_name is the name of
the cursor variable declared in a PL/SQL host environment (such as Pro*C), and bind_variable
represents the name of a PL/SQL bind variable. dynamic_string represents a dynamic SQL string
Focus Trainig Services, Pune Page 175
instead of a hard-coded SELECT statement. You open cursor variables for dynamic strings using native
dynamic SQL. Here’s an example that illustrates opening the cursor variable for the previously
declared weak cursor variable

v_rc:
DECLARE
TYPE rc is REF CURSOR;
v_rc rc;
BEGIN
OPEN v_rc FOR SELECT * from hrc_tab;
/* . . . FETCH the results and process the resultset */
END;

13.4.3 Fetching the Results into a PL/SQL Record or Individual PL/SQL Variables
The next step is to fetch the cursor variable into a PL/SQL record or individual variables. This retrieves
individual rows of data into the PL/SQL variables for processing. You fetch a cursor variable using the
FETCH statement, which has three forms. Here’s the

syntax:

FETCH cursor_variable_name INTO var1, var2, . . . , varN;


or
FETCH cursor_variable_name INTO table_name%ROWTYPE;
or
FETCH cursor__variable_name INTO record_name;

Here, var1, var2, and varN represent PL/SQL variables having data types identical to the cursor
variable query. table_name%ROWTYPE represents a PL/SQL record type with attributes implicitly
defined as the column names of the table identified by table_name, which are identical to the cursor
variable SELECT. In this case, you need to explicitly define the record type. Lastly, record_name is a
variable of a PL/SQL record type that’s explicitly defined. In this case also, the number and data types
of the individual attributes of the record should exactly match the columns in the cursor variable
SELECT. Here’s an example that extends the previous example of v_rc to fetching rows:
DECLARE
TYPE rc is REF CURSOR;

Focus Trainig Services, Pune Page 176


v_rc rc;
hrc_rec hrc_tab%ROWTYPE;
BEGIN
OPEN v_rc FOR SELECT * from hrc_tab;
LOOP
FETCH v_rc INTO hrc_rec;
EXIT WHEN v_rc%NOTFOUND;
/* . . . Process the individual records */
END LOOP;
END;
/

The number and data types of the individual variables should exactly match the columns list in the
cursor variable’s associated SELECT statement. If the cursor is fetched into a record type (either
table_name%ROWTYPE or record_name), the number and data type of each attribute in the record
should exactly match the columns list of the cursor variable associated SELECT statement. If this isn’t
the case, then PL/SQL raises an error at compile time if the cursor variable is strongly typed, and a
predefined exception called ROWTYPE_MISMATCH at runtime if the cursor variable is weakly typed.

13.4.4 Closing the Cursor Variable


Once the processing of the rows is completed, you can close the cursor variable. Closing the cursor
variable frees the resources allocated to the query but doesn’t necessarily free the storage of the
cursor variable itself. The cursor variable is freed when the variable is out of scope. You close a cursor
using the CLOSE statement. Here’s the syntax:
CLOSE cursor_variable_name;
Here’s a complete example of using the v_rc cursor, involving all the steps previously
covered:
DECLARE
TYPE rc is REF CURSOR;
v_rc rc;
hrc_rec hrc_tab%ROWTYPE;
BEGIN
OPEN v_rc FOR SELECT * from hrc_tab;
dbms_output.put_line(‘Hierarchy Details’);

Focus Trainig Services, Pune Page 177


dbms_output.put_line(‘------------------------’);
dbms_output.put_line(‘Code’||’ ‘||rpad(‘Description’,20,’ ‘));
dbms_output.put_line(rpad(‘-’,4,’-’)||’ ‘||rpad(‘-’,20,’- ’));
LOOP
FETCH v_rc INTO hrc_rec;
EXIT WHEN v_rc%NOTFOUND;
dbms_output.put_line(to_char(hrc_rec.hrc_code)||’ ‘||
rpad(hrc_rec.hrc_descr,20,’ ‘));
END LOOP;
CLOSE v_rc;
END;
/

OUTPUT:

Here’s the output of this program:


Hierarchy Details
----------------------------
Code Description
-------- ----------------
1 CEO/COO
2 VP
3 Director
4 Manager
5 Analyst
PL/SQL procedure successfully completed.

This code is similar to the code used for static cursors, except that it uses cursor variables instead of
cursors.

13.5 Cursor Variables Assignment


One way to make a cursor variable point to a query work area is to open a query for the cursor
variable. You saw this earlier. Here, I describe a second way to make a cursor variable point to a

Focus Trainig Services, Pune Page 178


query work area. Simply assign the cursor variable to an already OPENed cursor variable. Here’s an
example of cursor variable assignment:

DECLARE
TYPE rc is REF CURSOR;
v_rc1 rc;
v_rc2 rc;
hrc_rec hrc_tab%ROWTYPE;
BEGIN
OPEN v_rc1 FOR SELECT * from hrc_tab;
dbms_output.put_line(‘Hierarchy Details’);
dbms_output.put_line(‘------------------------’);
dbms_output.put_line(‘Code’||’ ‘||rpad(‘Description’,20,’ ‘));
dbms_output.put_line(rpad(‘-’,4,’-’)||’ ‘||rpad(‘-’,20,’- ’));
/* Assign v_rc1 to v_rc2 */
v_rc2 := v_rc1;
LOOP
/* Fetch from the second cursor variable, i.e., v_rc2
*/
FETCH v_rc2 INTO hrc_rec;
EXIT WHEN v_rc2%NOTFOUND;
dbms_output.put_line(to_char(hrc_rec.hrc_code)||’ ‘||
rpad(hrc_rec.hrc_descr,20,’ ‘));
END LOOP;
CLOSE v_rc2;
END;
/
The output of this program is the same as the output of the earlier example without the assignment.
Note that closing v_rc2 also closes v_rc1 and vice versa. However, if the source cursor variable is
strongly typed, the target cursor variable must be of the same type as the source cursor variable. This
restriction doesn’t apply if the source cursor variable is weakly typed. Here’s an example that
illustrates this concept
DECLARE
TYPE rc1 is REF CURSOR RETURN hrc_tab%ROWTYPE;
TYPE rc2 is REF CURSOR RETURN hrc_tab%ROWTYPE;

Focus Trainig Services, Pune Page 179


TYPE rc is REF CURSOR;
v_rc1 rc1;
v_rc2 rc2;
v_rc3 rc;
v_rc4 rc;
hrc_rec hrc_tab%ROWTYPE;
BEGIN
OPEN v_rc1 FOR SELECT * from hrc_tab;
/* Assign v_rc1 to v_rc2 */
v_rc2 := v_rc1; — This causes type error.
v_rc3 := v_rc1; — This succeeds.
v_rc4 := v_rc3; — This succeeds.
/* . . . FETCH and process . . . */
END;
/

13.6 Dynamism in Using Cursor Variables


The real use of cursor variables is when you have a need to open multiple queries using the same
cursor variable or to dynamically assign different queries to the same cursor variable depending on
runtime conditions. I discuss two examples in the following sections that illustrate the dynamism
involved in using cursor variables. To open multiple queries using the same cursor variable, use this
code:
DECLARE
TYPE rc is REF CURSOR;
v_rc rc;
hrc_rec hrc_tab%ROWTYPE;
v_hrc_descr VARCHAR2(20);
v_org_short_name VARCHAR2(30);
BEGIN
OPEN v_rc FOR SELECT * from hrc_tab;
dbms_output.put_line(‘Hierarchy Details’);
dbms_output.put_line(‘------------------------’);
dbms_output.put_line(‘Code’||’ ‘||rpad(‘Description’,20,’‘));
dbms_output.put_line(rpad(‘-’,4,’-’)||’ ‘||rpad(‘-’,20,’- ’));

Focus Trainig Services, Pune Page 180


LOOP
FETCH v_rc INTO hrc_rec;
EXIT WHEN v_rc%NOTFOUND;
dbms_output.put_line(to_char(hrc_rec.hrc_code)||’ ‘||
rpad(hrc_rec.hrc_descr,20,’ ‘));
END LOOP;
OPEN v_rc FOR SELECT h.hrc_descr, o.org_short_name
FROM org_tab o, hrc_tab h
WHERE o.hrc_code = h.hrc_code;
dbms_output.put_line(‘Hierarchy and Organization
Details’);
dbms_output.put_line(‘------------------------’);
dbms_output.put_line(rpad(‘Hierarchy’,20,’ ‘)||’ ‘||
rpad(‘Description’,30,’ ‘));
dbms_output.put_line(rpad(‘-’,20,’-’)||’ ‘||rpad(‘-’,30,’-
’));
LOOP
FETCH v_rc INTO v_hrc_descr, v_org_short_name;
EXIT WHEN v_rc%NOTFOUND;
dbms_output.put_line(rpad(v_hrc_descr,20,’ ‘)||’ ‘||
rpad(v_org_short_name,30,’ ‘));
END LOOP;
CLOSE v_rc;
END;
/

Here’s the output of this program:

Hierarchy Details
-------------------------
Code Description
------ --------------
1 CEO/COO
2 VP
3 Director

Focus Trainig Services, Pune Page 181


4 Manager
5 Analyst

Hierarchy and Organization Details


-------------------------------------------------
Hierarchy Description
---------------- -----------------------------------
CEO/COO Office of CEO ABC Inc.
CEO/COO Office of CEO XYZ Inc.
CEO/COO Office of CEO DataPro Inc.
VP Office of VP Sales ABC Inc.
VP Office of VP Mktg ABC Inc.
VP Office of VP Tech ABC Inc.

The following points are worth noting:


• The same cursor variable v_rc is used to point to two different queries.
• After you open v_rc for the first query and fetch the results, v_rc isn’tclosed. It’s simply
reopened for a second query and a new resultset is identified.

Focus Trainig Services, Pune Page 182


14 .

Autonomous Transactions
Objectives

1) What is Autonomus Transaction ?


2) Features of Autonomous Transactions.
3) Examples Features of Autonomous Transactions.

A transaction as a serious of statements that does a logical of work that completes or fails as an
integrated unit. Often , One transaction start another that many need to operate outside the scope
of the transaction that started it. That is , in an existing transaction, a required independent
transaction may need to commit or rollback changes without affecting the outcome of the starting
transaction. For example, in a stock purchase transaction , the customer’s information must be
committed regardless of whether the overall stock purchase completes. Or, while running that same
transaction, you want to log massages to a table even if the overall transaction rollback .

Since Oracle 8i, the autonomous transaction were added to make it possible to care an independent
transaction, An autonomous transaction (AT) is an independent transaction started by another main
transaction (MT), The slide depicts the behavior of an AT:

1. The main transaction begins.

Focus Trainig Services, Pune Page 183


2. A proc2 procedure is called to start the autonomous transaction.

3. The main transaction is suspended.

4. The autonomous transactional operation begins.

5. The autonomous transaction ends with a commit or rollback operation.

6. The main transaction is resume.

7. The main transaction is End;

14.1 Features of Autonomous Transactions


 Although called within a transaction, autonomous transaction are independet of that transaction,
That is, they are not nested transactions.

 If the main transaction rollback, autonomous transaction do not.

 Changes made by an autonomous transaction become visible to other transactions when their
stack-like functionality, only the “top” transaction is accessible at any givine time. After
completion, the autonomous transactioni is popped, and the calling transaction is resumed

 There are no limits other than resource limits on how may autonomous transactions can be
recursively called.

 Autonomous transaction must be explicitly committed or rollback; otherwise , an arror is


returned when attemting to return from the autonomous block.

 You cannot use PRAGMA to marked all subprograms in a packages as autonomous. Only
individual routines can be marked autonomous.

 You cannot mark a nestedor anonymous PL/SQL block as autonomous .

14.2 Example Of Autonomous Transaction


Step1:

create or replace procedure auto0


is
pragma autonomous_transaction;
begin
insert into t234 values(4,'abc');
commit;
end;
/

Focus Trainig Services, Pune Page 184


Step2:

create or replace procedure auto1


is
begin
delete from t23;
auto0;
rollback;
--Rows of t23 will rollback as we have used autonomous transaction
in auto0 procedure.
end;
/

Step3:

OUTPUT :

SQL> @ap17.sql

Procedure created.

Procedure created.

SQL> exec auto1;

PL/SQL procedure successfully completed.

Step4:

SQL> select * from t23;

ID NAME
---------- ------------------------------

Focus Trainig Services, Pune Page 185


1 abc

2 pqr

14.3 Using Autonomous Transaction

To define autonomous transaction , you use PRAGMA AUTONOMOUS_TRANSACTION . PRAGMA


instructs the PL/SQL comiler to make a routine as autonomous (independent). In this context, the
term “routine” include top-level not nested) anonymous PL/SQL block; local, stand-alone, and
packagesd functions and procedure s; methods of a SQL object type; and database triggers. You can
code PRAGMA anywhere in the declarative section of a routine. However, for readability, it is best
placed at the top of the DECLARATION section.

In the example in the slide, you track where the bankcard is used, regardless of whether the
transaction is successful. The following are benefits of autonomous transactions:

 After starting, an autonomous transaction is fully independent. It shares on lock, resources, or


commit dependencies with the main transaction, so you can log events, increment retry
counters, and so on even if the main transactions roll back.

 More important, sutonomous transactions help you build modular , reusable software
components. nFor example, stored procedure can start and finish autonomous transactions on
thir own. A calling application need not know about a procedure’s autonomous operations, and
the procedure need not know about the application’s transaction context. That makes
autonomous transactions less error-prone then regular transaction and easier to use

Focus Trainig Services, Pune Page 186


15.
NATIVE DYNAMIC SQL
Objectives
1) What Is Dynamic SQL?

2) The Need for Dynamic SQL

3) Using the EXECUTE IMMEDIATE Statement

4) Using the OPEN-FOR, FETCH, and CLOSE Statements

5) Tips and Traps for Dynamic SQL

15.1 What Is Dynamic SQL?


Most PL/SQL programs do a specific, predictable job. For example, a stored procedure might accept
an employee number and salary increase, then update the sal column in the emp table. In this case,
the full text of the UPDATE statement is known at compile time. Such statements do not change from
execution to execution. So, they are called static SQL statements. However, some programs must
build and process a variety of SQL statements at run time. For example, a general- purpose report
writer must build different SELECT statements for the various reports it generates. In this case, the
full text of the statement is unknown until run time. Such statements can, and probably will, change
from execution to execution. So, they are called dynamic SQL statements. Dynamic SQL statements
are stored in character strings built by your program at run time. Such strings must contain the text
of a valid SQL statement or PL/SQL block.
They can also contain placeholders for bind arguments. A placeholder is an undeclared identifier, so
its name, to which you must prefix a colon, does not matter. For example, PL/SQL makes no
distinction between the following strings:
’DELETE FROM emp WHERE sal > :my_sal AND comm < :my_comm’
’DELETE FROM emp WHERE sal > :s AND comm < :c’

Focus Trainig Services, Pune Page 187


To process most dynamic SQL statements, you use the EXECUTE IMMEDIATE statement. However, to
process a multi-row query (SELECT statement), you must use the OPEN-FOR, FETCH, and CLOSE
statements.

15.2 The Need for Dynamic SQL


You need dynamic SQL in the following situations:

1) You want to execute a SQL data definition statement (such as CREATE), a data control

statement (such as GRANT), or a session control statement (such as ALTER SESSION). In

PL/SQL, such statements cannot be executed statically.

2) You want more flexibility. For example, you might want to defer your choice of schema

objects until run time. Or, you might want your program to build different search conditions for the

WHERE clause of a SELECT statement. A more complex program might choose from various

SQL operations, clauses, etc.

3) You use package DBMS_SQL to execute SQL statements dynamically, but you want

better performance, something easier to use, or functionality that DBMS_SQL lacks such as

support for objects and collections.

15.3 Using the EXECUTE IMMEDIATE Statement


The EXECUTE IMMEDIATE statement prepares (parses) and immediately executes a dynamic SQL
statement or an anonymous PL/SQL block. The syntax is
EXECUTE IMMEDIATE dynamic_string
[INTO {define_variable[, define_variable]... | record}]
[USING [IN | OUT | IN OUT] bind_argument
[, [IN | OUT | IN OUT] bind_argument]...]
[{RETURNING | RETURN} INTO bind_argument[, bind_argument]...];

where dynamic_string is a string expression that represents a SQL statement or PL/SQL block,
define_variable is a variable that stores a selected column value, and record is a user-defined or
%ROWTYPE record that stores a selected row.

Focus Trainig Services, Pune Page 188


An input bind_argument is an expression whose value is passed to the dynamic SQL statement or
PL/SQL block. An output bind_argument is a variable that stores a value returned by the dynamic SQL
statement or PL/SQL block.
Except for multi-row queries, the dynamic string can contain any SQL statement (without the
terminator) or any PL/SQL block (with the terminator). The string can also contain placeholders for
bind arguments. However, you cannot use bind arguments to pass the names of schema objects to a
dynamic SQL statement.
Used only for single-row queries, the INTO clause specifies the variables or record into which column
values are retrieved. For each value retrieved by the query, there must be a corresponding, type-
compatible variable or field in the INTO clause.
Used only for DML statements that have a RETURNING clause (without a BULK COLLECT clause), the
RETURNING INTO clause specifies the variables into which column values are returned. For each
value returned by the DML statement, there must be a corresponding, type-compatible variable in
the RETURNING INTO clause. You can place all bind rguments in the USING clause. The default
parameter mode is IN. For DML statements that have a RETURNING clause, you can place OUT
arguments in the RETURNING INTO clause without specifying the parameter mode, which, by
definition, is OUT. If you use both the USING clause and the RETURNING INTO clause, the USING
clause can contain only IN arguments. At run time, bind arguments replace corresponding
placeholders in the dynamic string. So, every placeholder must be associated with a bind argument in
the USING clause and/or RETURNING INTO clause. You can use numeric, character, and string literals
as bind arguments, but you cannot use Boolean literals (TRUE, FALSE, and NULL). Dynamic SQL
supports all the SQL datatypes. So, for example, define variables and\ bind arguments can be
collections, LOBs, instances of an object type, and refs.
As a rule, dynamic SQL does not support PL/SQL-specific types. So, for example, define variables and
bind arguments cannot be Booleans or index-by tables. The only exception is that a PL/SQL record
can appear in the INTO clause. You can execute a
dynamic SQL statement repeatedly using new values for the bind arguments. However, you incur
some overhead because EXECUTE IMMEDIATE reprepares the dynamic string before every execution.

15.4 Some Examples of Dynamic SQL


The following PL/SQL block contains several examples of dynamic SQL: procedure for showing values
of table in desending order
create or replace procedure dyn1

Focus Trainig Services, Pune Page 189


is

cursor c2 is select * from table10 order by 2 desc;


r1 c2%rowtype;

begin

open c2;

loop
dbms_output.put_line(rpad('TABLE NAME',20)||'COUNT');
dbms_output.put_line('-----------------------------------------
--');
fetch c2 into r1;
exit when c2%notfound;
dbms_output.put_line(rpad(r1.tname,20)||r1.cnt1);

end loop;

close c2;

end;
/
show error

set serveroutput on

Example2:
create or replace procedure dyn2
is
cursor c1 is select table_name from user_tables;
r1 c1%rowtype;
cnt number;
sql1 varchar2(200);
sql2 varchar2(200);

Focus Trainig Services, Pune Page 190


begin
open c1;
loop
fetch c1 into r1;
exit when c1%notfound;
sql1:='select count(*) from '||r1.table_name; --dynamic sql
statement
execute immediate sql1 into cnt;
insert into table10 values (r1.table_name,cnt);
end loop;
close c1;
dyn1;
end;
/
set serveroutput on
show error

OUTPUT:
Output:

TABLE NAME COUNT


---------------- --------------------
ORDERDETAILS 2154
ORDERS 830
EMPLOYEES 107
TABLE10 92
CUSTOMERS 91
PRODUCTS 77
OLDDEPT 56
TERRITORIES 53

Focus Trainig Services, Pune Page 191


Appendix I: SQL*LOADER

SQL*Loader Basics
SQL*Loader loads data from external files into tables of an Oracle database.
SQL*Loader:
 Has a powerful data parsing engine which puts little limitation on the format of the
 data in the datafile.
 Can load data from multiple datafiles during the same load session.
 Can load data into multiple tables during the same load session.
 Is character set aware (you can specify the character set of the data).
 Can selectively load data (you can load records based on the records' values).
 Can manipulate the data before loading it, using SQL functions.
 Can generate unique sequential key values in specified columns.
 Can use the operating system's file system to access the datafile(s).
 Can load data from disk, tape, or named pipe.
 Does sophisticated error reporting which greatly aids troubleshooting.
 Supports two loading "paths" -- Conventional and Direct. While conventional path loading is very
flexibility,direct path loading provides superior loading performance.
 Can load arbitrarily complex object-relational data.

Figure : SQL*Loader Overview

Focus Trainig Services, Pune Page 192


SQL*Loader takes as input a control file, which controls the behavior of SQL*Loader, and one or
more datafiles. Output of the SQL*Loader is an Oracle database (where the data is loaded), a log file,
a bad file, and potentially a discard file.

B. SQL*Loader Control File


The control file is a text file written in a language that SQL*Loader understands. The control file
describes the task that the SQL*Loader is to carry out. The control file tells SQL*Loader where to find
the data, how to parse and interpret the data, where to insert the data.

C. Input Data and Datafiles


The other input to SQL*Loader, other than the control file, is the data. SQL*Loader reads data from
one or more files (or operating system equivalents of files) specified in the control file. From
SQL*Loader's perspective, the data in the datafile is organized as records. A particular datafile can be
in fixed record format, variable record format, or stream record format. Important: If data is
specified inside the control file (that is, INFILE * was specified in the control file), then tthe data is
interpreted in the stream record format with the default record terminator.

Fixed Record Format


When all the records in a datafile are of the same byte length, the file is in fixed record format.
Although this format is the least flexible, it does result in better performance than variable or stream
format. Fixed format is also simple to specify, for example:
INFILE <datafile_name> "fix n"
specifies that SQL*Loader should interpret the particular datafile as being in fixed record format
where every record is n bytes long.
Example : Loading Data in Fixed Record Format
load data
infile 'example.dat' "fix 11"
into table example
fields terminated by ',' optionally enclosed by '"'
(col1 char(5),
col2 char(7))
example.dat:
001,cd, 0002,fghi,
00003,lmn,

Focus Trainig Services, Pune Page 193


1, "pqrs",
0005,uvwx,

Variable Record Format


When you specify that a datafile is in variable record format, SQL*Loader expects to find the length
of each record in a character field at the beginning of each record in the datafile. This format
provides some added flexibility over the fixed record format and a performance advantage over the
stream record format. For example, you can specify a datafile which is to be interpreted as being in
variable record format as follows: INFILE "datafile_name" "var n" where n specifies the number of
bytes in the record length field. Note that if n is not specified, it defaults to five. If it is not specified,
SQL*Loader assumes a length of five. Also note that specifying n larger than 2^32 -1 will result in an
error.
Example : Loading Data in Variable Record Format
load data
infile 'example.dat' "var 3"
into table example
fields terminated by ',' optionally enclosed by '"'
(col1 char(5),
col2 char(7))
example.dat:
009hello,cd,010world,im,
012my,name is,

D. Discarded and Rejected Records


Records read from the input file might not be inserted into the database. Figure below shows the
stages at which records may be rejected or discarded. The Bad File
The bad file contains records rejected, either by SQL*Loader or by Oracle. Some of the possible
reasons for rejection are discussed in the next sections.

E. SQL*Loader Rejects
Records are rejected by SQL*Loader when the input format is invalid. For example, if the second
enclosure delimiter is missing, or if a delimited field exceeds its maximum length, SQL*Loader rejects
the record. Rejected records are placed in the bad file.

Focus Trainig Services, Pune Page 194


Figure : Record Filtering

Oracle Rejects
After a record is accepted for processing by SQL*Loader, a row is sent to Oracle for insertion. If
Oracle determines that the row is valid, then the row is inserted into the database. If not, the record
is rejected, and SQL*Loader puts it in the bad file. The row may be rejected, for example, because a
key is not unique, because a required field is null, or because the field contains invalid data for the
Oracle datatype.

The bad file is written in the same format as the datafile. So rejected data can be loaded with the
existing control file after necessary corrections are made.

Focus Trainig Services, Pune Page 195


SQL*Loader Discards
As SQL*Loader executes, it may create a file called the discard file. This file is created only when
it is needed, and only if you have specified that a discard file should be enabled. The discard file
contains records that were filtered out of the load because they did not match any record-
selection criteria specified in the control file.
The discard file therefore contains records that were not inserted into any table in the database.
You can specify the maximum number of such records that the discard file can accept. Data
written to any database table is not written to the discard file. The discard file is written in the
same format as the datafile. The discard data can be loaded with the existing control file, after
any necessary editing or correcting.

F. Log File and Logging Information


When SQL*Loader begins execution, it creates a log file. If it cannot create a log file, execution
terminates. The log file contains a detailed summary of the load, including a description of any
errors that occurred during the load.

Conventional Path Load versus Direct Path Load


SQL*Loader provides two methods to load data: Conventional Path, which uses a SQL INSERT
statement with a bind array, and Direct Path, which loads data directly into database. The tables
to be loaded must already exist in the database, SQL*Loader

never creates tables, it loads existing tables. Tables may already contain data, or they may be empty.
The following privileges are required for a load: You must have INSERT privileges on the table to be
loaded. You must have DELETE privilege on the table to be loaded, when using the REPLACE or
TRUNCATE option to empty out the table's old data before loading the new data in its place.

Conventional Path
During conventional path loads, the input records are parsed according to the field specifications,
and each data field is copied to its corresponding bind array. When the bind array is full (or there
is no more data left to read), an array insert is executed. Note that SQL*Loader stores LOB fields
after a bind array insert is done. Thus, if there are any errors in processing the LOB field (for
example, the LOBFILE could not be found), the LOB field is left empty.
There are no special requirements for tables being loaded via the conventional path.

Focus Trainig Services, Pune Page 196


Direct Path
A direct path load parses the input records according to the field specifications, converts the input
field data to the column datatype and builds a column array. The column array is passed to a
block formatter which creates data blocks in Oracle database block format. The newly formatted
database blocks are written directly to the database bypassing most RDBMS processing. Direct
path load is much faster than conventional path load, but entails several restrictions.

G. sqlldr command line options


 userid
 control Name of control file
 log log is captured in this file
 bad data rejected by oracle because of constraint violation
 data file containing the data to be loaded
 discard data discarded because of the WHEN clause
 skip=n skips n header records from data file & loads the remaining
 errors=n stops loading data if n records error out
 rows=n commits after n rows (use larger number for better performance)
only for conventional load
 bindsize=1024 Size of an array in conventional load only. Higher the size
larger number of insert statements in an array
 direct=true Does not create insert statements inside the bind array. Skips
 buffer cache. Data added above HWM. Constraints (PK & FK) are disabled
 during the load. Triggers are not fired during the load. Table and indexes are
 locked while data is being loaded. Constraints could become INVALID if data
 loaded does not meet them. E.g duplicate key is loaded in PK column

H. How to build control file

Delimited File

10001,"Scott Tiger", 1000, 40


10002,"Frank Naude", 500, 20

load data

Focus Trainig Services, Pune Page 197


append
into table emp
fields terminated by "," optionally enclosed by '"'
( empno, empname, sal, deptno )

Fixed length file


10001 Scott Tiger 1000 40
10002 Frank Naude 500 20

load data
replace -- you can use truncate to improve performance
into table departments
( dept position (02:05) char(4),
deptname position (08:27) char(20)
)

How to load
sqlldr userid=shekhar/shekhar control=emp.ctl
data=emp.dat log=emp.log bad=emp.bad reject=emp.reject
direct=true errors=1000 skip=1

How can you skip head records


sqlldr userid=ora_id/ora_passwd control=control_file_name.ctl
skip=4

How can you change/transform data while loading


Append
INTO TABLE modified_data
( rec_no "my_db_sequence.nextval",
region CONSTANT '31',
time_loaded "to_char(SYSDATE, 'HH24:MI')",
data1 POSITION(1:5) ":data1/100",
data2 POSITION(6:15) "upper(:data2)",
data3 POSITION(16:22)"to_date(:data3, 'YYMMDD')"
)
LOAD DATA
APPEND
INTO TABLE mailing_list
FIELDS TERMINATED BY ","
( addr,
city,
state,
zipcode,
mailing_addr "decode(:mailing_addr, null, :addr, :mailing_addr)",
mailing_city "decode(:mailing_city, null, :city, :mailing_city)",
mailing_state
Focus Trainig Services, Pune Page 198
)

How to selectively load data


LOAD DATA
APPEND
INTO TABLE my_selective_table
WHEN (01) <> 'H' and (01) <> 'T' and (30:37) = '20031217'
(
region CONSTANT '31',
service_key POSITION(01:11) INTEGER EXTERNAL,
call_b_no POSITION(12:29) CHAR
)=

Focus Trainig Services, Pune Page 199


Appendix II. OVERVIEW OF ORACLE
ARCHITECTURE

The Oracle Relational Database Management System, or RDBMS, is designed to allow simultaneous
access to large amounts of stored information. The RDBMS consists of the database (the information)
and the instance (the embodiment of the system). The database contains the physical files that
reside on the system and the logical pieces such as the database schema. These database files take
various forms, as described in the following section. The instance is the method used to access the
data and consists of processes and system memory.

A. The Database
The Oracle database has a logical layer and a physical layer. The physical layer consists of the files
that reside on the disk; the components of the logical layer map the data to these physical
components.

The Physical Layer


The physical layer of the database consists of three types of files:
 One or more datafiles--Datafiles store the information contained in the database. You can
have as few as one datafile or as many as hundreds of datafiles. The information for a single
table can span many datafiles or many tables can share a set of datafiles.
 Two or more redo log files--Redo log files hold information used for recovery in the event of a
system failure. Redo log files, known as the redo log, store a log of all changes made to the
database. This information is used in the event of a system failure to reapply changes that
have been made and committed but that might not have been made to the datafiles. The
redo log files must perform well and be protected against hardware failures (through
software or hardware fault tolerance). If redo log information is lost, you cannot recover the
system.
 One or more control files--Control files contain information used to start an instance, such as
the location of datafiles and redo log files; Oracle needs this information to start the database
instance. Control files must be protected. Oracle provides a mechanism for storing multiple
copies of control files.

Focus Trainig Services, Pune Page 200


The Logical Layer
The logical layer of the database consists of the following elements:
 · One or more tablespaces.
 · The database schema, which consists of items such as tables, clusters, indexes, views, stored
procedures, database triggers, sequences, and so on.

B. Tablespaces and Datafiles

The database is divided into one or more logical pieces known as tablespaces. A tablespace is used to
logically group data together. For example, you can create one tablespace for accounting and a
separate tablespace for purchasing. Segmenting groups into different tablespaces simplifies the
administration of these groups. Tablespaces consist of one or more datafiles. By using more than one
datafile per tablespace, you can spread data over many different disks to distribute the I/O load and
improve performance.

Focus Trainig Services, Pune Page 201


C. Segments, Extents, and Data Blocks
Within Oracle, the space used to store data is controlled by the use of logical structures.
These structures consist of the following:
 Data blocks--A block is the smallest unit of storage in an Oracle database. The
database block contains header information concerning the block itself as well as
the data.
 Extents--Extents consist of data blocks.
 Segments--A segment is a set of extents used to store a particular type of data.

Focus Trainig Services, Pune Page 202


Segments
An Oracle database can use four types of segments:
 Data segment--Stores user data within the database.
 Index segment--Stores indexes.
 Rollback segment--Stores rollback information used when data must be rolled back
 Temporary segment--Created when a SQL statement needs a temporary work area; these
segments are destroyed when the SQL statement is finished. These segments are used during
various database operations, such as sorts.

Extents
Extents are the building blocks of segments; in turn, they consist of data blocks. An extent is used to
minimize the amount of wasted (empty) storage. As more and more data is entered into tablespaces
in your database, the extents used to store that data can grow or shrink as necessary. In this manner,
many tablespaces can share the same storage space without preallocating the divisions between
those tablespaces. At tablespace-creation time, you can specify the minimum number of extents to
allocate as well as the number of extents to add at a time when that allocation has been used. This
arrangement gives you efficient control over the space used in your database.

Data Blocks
Data blocks are the smallest pieces of an Oracle database; they are physically stored on disk.
Although the data block in most systems is 2KB (2,048 bytes), you can change this size for efficiency
depending on your application or operating system.

D. The Oracle Instance


The Oracle instance consists of the Oracle processes and shared memory necessary to access
information in the database. The instance is made up of the user processes, the Oracle background
processes, and the shared memory used by these processes.

Focus Trainig Services, Pune Page 203


The Oracle Memory Structure
Oracle uses shared memory for several purposes, including caching of data and indexes as well as
storing shared program code. This shared memory is broken into various pieces, or memory
structures. The basic memory structures associated with Oracle are the System Global Area (SGA)
and the Program Global Area (PGA).

The System Global Area (SGA)


The SGA is a shared memory region that Oracle uses to store data and control information for one
Oracle instance. The SGA is allocated when the Oracle instance starts and deallocated when the
Oracle instance shuts down. Each Oracle instance that starts has its own SGA. The information in the
SGA consists of the following elements, each of which has a fixed size and is created at instance
startup:
 The database buffer cache—This stores the most recently used data blocks. These blocks can
contain modified data that has not yet been written to disk (sometimes known as dirty blocks),
blocks that have not been modified, or blocks that have been written to disk

Focus Trainig Services, Pune Page 204


 since modification (sometimes known as clean blocks). Because the buffer cache keeps blocks
based on a most recently used algorithm, the most active buffers stay in memory to reduce I/O
and improve performance.
 The redo log buffer--This stores redo entries, or a log of changes made to the database. The redo
log buffers are written to the redo log as quickly and efficiently as possible. Remember that the
redo log is used for instance recovery in the event of a system failure.
 The shared pool--This is the area of the SGA that stores shared memory structures such as shared
SQL areas in the library cache and internal information in the data dictionary. The shared pool is
important because an insufficient amount of memory allocated to the shared pool can cause
performance degradation. The shared pool consists of the library cache and the datadictionary
cache.
 The Library Cache
The library cache is used to store shared SQL. Here the parse tree and the execution plan for
every unique SQL statement are cached. If multiple applications issue the same SQL statement,
the shared SQL area can be accessed by each to reduce the amount of memory needed and to
reduce the processing time used for parsing and execution planning.

 The Data-Dictionary Cache


 The data dictionary contains a set of tables and views that Oracle uses as a reference to the
database. Oracle stores information here about the logical and physical structure of the
database. The data dictionary contains information such as the following:
 · User information, such as user privileges
 · Integrity constraints defined for tables in the database
 · Names and data types of all columns in database tables
 · Information on space allocated and used for schema objects

The Program Global Area (PGA)


The PGA is a memory area that contains data and control information for the Oracle server
processes. The size and content of the PGA depends on the Oracle server options you have installed.
This area consists of the following components:
 Stack space--This is the memory that holds the session's variables, arrays, and so on.
 Session information--If you are not running the multithreaded server, the session information
is stored in the PGA. If you are running the multithreaded server, the session information is
stored in the SGA.

Focus Trainig Services, Pune Page 205


 Private SQL area--This is an area in the PGA where information such as binding variables
and runtime buffers is kept.

Processes
In many operating systems, traditional processes have been replaced by threads or lightweight
processes. The term process is used in this book to describe a thread of execution, or a mechanism
that can execute a set of code; process refers to the mechanism of execution and can refer to a
traditional process or a thread.
The Oracle RDBMS uses two types of processes: user processes and Oracle processes (also known as
background processes). In some operating systems (such as Windows NT), these processes are
actually threads; for the sake of consistency, I will refer to them as processes.

User Processes
User, or client, processes are the user's connections to the RDBMS system. The user process
manipulates the user's input and communicates with the Oracle server process through the Oracle
program interface. The user process is also used to display the information requested by the user
and, if necessary, can process this information into a more useful form.

Oracle Processes
Oracle processes perform functions for users. Oracle processes can be split into two groups: server
processes (which perform functions for the invoking process) and background processes (which
perform functions on behalf of the entire RDBMS).

 Server Processes (Shadow Processes)


Server processes, also known as shadow processes communicate with the user and interact with
Oracle to carry out the user's requests. For example, if the user process requests a piece of data not
already in the SGA, the shadow process is responsible for reading the data blocks from the datafiles
into the SGA. There can be a one-to-one correlation between user processes and shadow processes
(as in a dedicated server configuration); although one shadow process can connect to multiple user
processes (as in a multithreaded server configuration), doing so reduces the utilization of system
resources.
 Background Processes
Background processes are used to perform various tasks within the RDBMS system. These tasks vary
from communicating with other Oracle instances and performing system maintenance and cleanup
Focus Trainig Services, Pune Page 206
to writing dirty blocks to disk. Following are brief descriptions of the nine Oracle background
processes:
 DBWR (Database Writer)--DBWR is responsible for writing dirty data blocks from the database block
buffers to disk. When a transaction changes data in a data block, that data block need not be
immediately written to disk. Therefore, the DBWR can write this data to disk in a manner that is
more efficient than writing when each transaction completes.
 LGWR (Log Writer)--The LGWR process is responsible for writing data from the log buffer to the redo
log.
 CKPT (Checkpoint)--The CKPT process is responsible for signaling the DBWR process to perform a
checkpoint and to update all the datafiles and control files for the database to indicate the most
recent checkpoint. A checkpoint is an event in which all modified database buffers are written to the
datafiles by the DBWR. The CKPT process is optional. If the CKPT process is not present, the LGWR
assumes these responsibilities.
 PMON (Process Monitor)--PMON is responsible for keeping track of database processes and cleaning
up if a process prematurely dies (PMON cleans up the cache and frees resources that might still be
allocated).
 SMON (System Monitor)--SMON performs instance recovery at instance startup. This includes
cleaning temporary segments and recovering transactions that have died because of a system crash.
The SMON also defragments the database by coalescing free extents within the database.
 RECO (Recovery)-- RECO is used to clean transactions that were pending in a distributed database.
RECO is responsible for committing or rolling back the local portion of the disputed transactions.
 ARCH (Archiver)-- ARCH is responsible for copying the online redo log files to archival storage when
they become full. ARCH is active only when the RDBMS is operated in ARCHIVELOG mode.
 LCKn (Parallel Server Lock)--Up to 10 LCK processes are used for interinstance locking when the
Oracle Parallel Server option is used.
 Dnnn (Dispatcher)-- When the Multithreaded Server option is used, at least one Dispatcher process
is used for every communications protocol in use. The Dispatcher process is responsible for routing
requests from the user processes to available shared server processes and back

Focus Trainig Services, Pune Page 207


Oracle Database 12c

Oracle Database 12c offers a variety of enhancements to the way you can define and execute PL/SQL
program units. This article covers several new Oracle Database 12c features that enable you to do
the following:

 Optimize invoker rights functions for the RESULT_CACHE clause


 Define and execute PL/SQL functions inside SQL statements
 Restrict access to program units through use of a “whitelist,” specified by the ACCESSIBLE BY
clause
 Fine-tune privileges for a program unit by granting roles to that unit

A. Invoker Rights and the PL/SQL Function Result Cache

Oracle Database 11g introduced the PL/SQL function result cache, which offers a very powerful,
efficient, and easy-to-use caching mechanism. The main objective of this cache is to ensure that if a
row of data hasn’t changed since it was last fetched from the database, no SQL statement needs to
execute for it to be retrieved again.

This holds true across the entire database instance. In other words, suppose a user connected to
schema USER_ONE executes a result-cached function to retrieve the row from the employees table
for employee ID = 100. When a user connected to schema USER_TWO executes the same function
call for the same employee ID, that row of information is retrieved directly from the cache and not by
execution of a SELECT statement.

If you are not already using this feature (and you are using Oracle Database 11g), I strongly
encourage you to investigate it and start applying it—in close collaboration with your DBA so that the
result cache pool is sized properly.

Even in Oracle Database 11g Release 2, however, you could not combine invoker rights (AUTHID
CURRENT_USER clause) with the function result cache (RESULT_CACHE keyword). An attempt to
compile the following function:

CREATE OR REPLACE FUNCTION last_name (


employee_id_in

Focus Trainig Services, Pune Page 208


IN employees.employee_id%TYPE)
RETURN employees.last_name%TYPE
AUTHID CURRENT_USER
RESULT_CACHE
IS
l_return employees.last_name%TYPE;
BEGIN
SELECT last_name
INTO l_return
FROM employees
WHERE employee_id = employee_id_in;

RETURN l_return;
END;
/

results in this compilation error:

PLS-00999: implementation restriction


(may be temporary) RESULT_CACHE is
disallowed on subprograms in
Invoker-Rights modules

The reason for this restriction is the whole point of invoker rights. At runtime the PL/SQL engine uses
the privileges of the current user to resolve references to database objects such as tables and views.
But if such a function was compiled with RESULT_CACHE, then (using the example above) after
USER_ONE executed the function, passing in 100, when USER_TWO makes the same function call,
the body of the function would not be executed and the reference to the EMPLOYEES table would
not be resolved according to USER_TWO’s privilege. This could have caused serious security issues.

Well, the good news is that this restriction was temporary. In Oracle Database 12c, you can now
compile functions such as last_name (above) without error—and Oracle Database 12c does the right
thing, of course.

Behind the scenes, Oracle Database 12c passes the name of the current user as a hidden parameter;
this value is cached along with the values of all the arguments passed to the function. So each time
the last_name function is called, Oracle Database 12c checks to see if that function has been
previously called with both the same employee ID and the same current user.

This means that the result cache for an invoker rights function is (logically) partitioned by the name
of the current user. Consequently, the result cache for an invoker rights function will improve
performance only in situations in which the same user calls the function with the same argument
values repeatedly. Another way of explaining this is to point out that in Oracle Database 11g Release
2, I could have achieved the same effect, but only if I had changed the implementation of the
last_name function, as shown in Listing 1.

“Partitioned” Oracle Database 11g Release 2 invoker’s rights function

CREATE OR REPLACE PACKAGE employee_api

Focus Trainig Services, Pune Page 209


AUTHID CURRENT_USER
IS
FUNCTION last_name (
employee_id_in IN employees.employee_id%TYPE)
RETURN employees.last_name%TYPE;
END;
/

CREATE OR REPLACE PACKAGE BODY employee_api


IS
FUNCTION i_last_name (
employee_id_in IN employees.employee_id%TYPE,
user_in IN VARCHAR2 DEFAULT USER)
RETURN employees.last_name%TYPE
RESULT_CACHE
IS
l_return employees.last_name%TYPE;
BEGIN
SELECT last_name
INTO l_return
FROM employees
WHERE employee_id = employee_id_in;

RETURN l_return;
END;

FUNCTION last_name (
employee_id_in IN employees.employee_id%TYPE)
RETURN employees.last_name%TYPE
IS
l_return employees.last_name%TYPE;
BEGIN
RETURN i_last_name (employee_id_in,
USER);
END;
END;
/

Note that the last_name function is defined in the package specification and is not result-cached.
Instead, that public function (declared in the package specification) merely calls the private/internal
“version” of the function, which has a second parameter: the user.

So each time you call employee_api.last_name, Oracle Database 11g Release 2 adds the name of the
user to the set of values used by the database to determine whether there is a match in the result
cache.

This is no longer necessary; in Oracle Database 12c, you simply need to decide if you think it is worth
adding RESULT_CACHE to invoker rights programs.

Focus Trainig Services, Pune Page 210


B. Define PL/SQL Subprograms in a SQL Statement

Developers have long been able to call their own PL/SQL functions from within a SQL statement.
Suppose, for example, I have created a function named BETWNSTR that returns the substring
between the specified start and end locations:

FUNCTION betwnstr (
string_in IN VARCHAR2
, start_in IN PLS_INTEGER
, end_in IN PLS_INTEGER
)
RETURN VARCHAR2
IS
BEGIN
RETURN ( SUBSTR (
string_in, start_in,
end_in - start_in + 1 ));
END;

I can then use it in a query as follows:

SELECT betwnstr (last_name, 3, 5)


FROM employees

With Oracle Database 12c, you can now define PL/SQL functions and procedures in the WITH clause
of a subquery and then use them as you would any other built-in or user-defined function. This
feature enables me to consolidate the BETWNSTR function and query shown above into a single
statement:

**12c**

WITH
FUNCTION betwnstr (
string_in IN VARCHAR2,
start_in IN PLS_INTEGER,
end_in IN PLS_INTEGER)
RETURN VARCHAR2
IS
BEGIN
RETURN (SUBSTR (
string_in,
start_in,
end_in - start_in + 1));
END;

Focus Trainig Services, Pune Page 211


SELECT betwnstr (last_name, 3, 5)
FROM employees

* The classic workaround to this limitation has been to define a function in the package and then call
the function:

Step1:

SQL> CREATE OR REPLACE PACKAGE pkg


2 IS
3 year_number
CONSTANT INTEGER := 2013;
4 END;
5 /

Package created.

Step2:

SQL> SELECT pkg.year_number


FROM employees
2 WHERE employee_id = 138
3 /

OUTPUT:
SELECT pkg.year_number FROM employees
ERROR at line 1:
ORA-06553: PLS-221: 'YEAR_NUMBER' is not
a procedure or is undefined

The classic workaround to this limitation has been to define a function in the package and then call
the function:

SQL> CREATE OR REPLACE PACKAGE pkg


2 IS
3 FUNCTION year_number
4 RETURN INTEGER;
5 END;
6 /
Package created.
Step3:

Focus Trainig Services, Pune Page 212


SQL> CREATE OR REPLACE PACKAGE BODY pkg
2 IS
3 c_year_number
CONSTANT INTEGER := 2013;
4
5 FUNCTION year_number
6 RETURN INTEGER
7 IS
8 BEGIN
9 RETURN c_year_number;
10 END;
11 END;
12 /
Package body created.

Step4:

SQL> SELECT pkg.year_number


2 FROM employees
3 WHERE employee_id = 138
4 /

YEAR_NUMBER
———————————
2013

That’s a lot of code and effort simply to be able to reference the constant’s value in a SQL statement.
And, with Oracle Database 12c, it is no longer necessary. I can revert to and recompile the original
pkg, containing just a single constant named year_number in the package specification, and create a
function in the WITH clause:

WITH
FUNCTION year_number
RETURN INTEGER
IS
BEGIN
RETURN pkg.year_number;
END;
SELECT year_number
FROM employees
WHERE employee_id = 13

C. Whitelists and the ACCESSIBLE BY Clause


Before Oracle Database 12c, PL/SQL could not prevent a session from using any and all subprograms
in packages to which that session’s schema had been granted EXECUTE authority. As of Oracle

Focus Trainig Services, Pune Page 213


Database 12c, in contrast, all PL/SQL program units have an optional ACCESSIBLE BY clause that
enables you to specify a whitelist of other PL/SQL units that can access the PL/SQL unit you are
creating or altering

CREATE OR REPLACE PACKAGE public_pkg


IS
PROCEDURE do_only_this;
END;
/

Next, I create the specification of my “private” package. The package is private in the sense that I
want to make sure that it can be invoked only from within the public package (public_pkg). So I
add the ACCESSIBLE_BY clause:

CREATE OR REPLACE PACKAGE private_pkg


ACCESSIBLE BY (public_pkg)
IS
PROCEDURE do_this;

PROCEDURE do_that;
END;
/

Now it’s time to implement the package bodies. The public_pkg.do_only_this procedure calls the
private_pkg subprograms:

CREATE OR REPLACE PACKAGE BODY public_pkg


IS
PROCEDURE do_only_this
IS
BEGIN
private_pkg.do_this;
private_pkg.do_that;
END;
END;
/

CREATE OR REPLACE PACKAGE BODY


private_pkg
IS
PROCEDURE do_this
IS
BEGIN
DBMS_OUTPUT.put_line ('THIS');
END;

Focus Trainig Services, Pune Page 214


PROCEDURE do_that
IS
BEGIN
DBMS_OUTPUT.put_line ('THAT');
END;
END;
/

I can now run the public package’s procedure without any problem:

BEGIN
public_pkg.do_only_this;
END;
/

But if I try to call a subprogram in the private package in an anonymous block, I see this error:

BEGIN
private_pkg.do_this;
END;
/

OUTPUT:
ERROR at line 2:
ORA-06550: line 2, column 1:
PLS-00904: insufficient privilege to
access object PRIVATE_PKG
ORA-06550: line 2, column 1:
PL/SQL: Statement ignored

And the same error occurs if I try to compile a program unit that tries to call a subprogram in the
private package:

SQL> CREATE OR REPLACE PROCEDURE


use_private
2 IS
3
BEGIN
4 private_pkg.do_this;
5 END;
6 /

Focus Trainig Services, Pune Page 215


Warning: Procedure created with
compilation errors.

SQL> SHOW ERRORS

Errors for PROCEDURE USE_PRIVATE:

LINE/COL ERROR
———————— ——————————————————————————
4/4 PL/SQL: Statement ignored
4/4 PLS-00904: insufficient
privilege to access object
PRIVATE_PKG

As the “PLS” error indicates, this issue is caught at compilation time. There is no runtime
performance hit for using this feature.

D. Grant Roles to Program Units

Before Oracle Database 12c, a definer’s rights program unit (defined with the AUTHID DEFINER or no
AUTHID clause) always executed with the privileges of the definer of that unit. An invoker’s rights
program unit (defined with the AUTHID CURRENT_USER clause) always executed with the privileges
of the invoker of that unit.

A consequence of these two distinct AUTHID settings is that program units that need to be executed
by all users would have to be created as definer’s rights units. The program units would then execute
with all the privileges of the definer, which might not be optimal from a security standpoint.

As of Oracle Database 12c, you can grant roles to PL/SQL packages and schema-level procedures and
functions. Role-based privileges for program units enable developers to fine-tune the privileges
available to the invoker of a program unit.

You can now define a program unit as having invoker’s rights and then complement the invoker’s
privileges with specific, limited privileges granted through the role.

Let’s walk through an example that shows how to grant roles to program units and the impact it has.
Suppose that the HR schema contains the departments and employees tables, defined and populated
with data as follows:

Step1:

CREATE TABLE departments


(
department_id INTEGER,
department_name VARCHAR2 (100),
staff_freeze CHAR (1)

Focus Trainig Services, Pune Page 216


)
/

Step2:

BEGIN
INSERT INTO departments
VALUES (10, 'IT', 'Y');

INSERT INTO departments


VALUES (20, 'HR', 'N');

COMMIT;
END;
/

Step3:

CREATE TABLE employees


(
employee_id INTEGER,
department_id INTEGER,
last_name VARCHAR2 (100)
)
/

Step4:

BEGIN
DELETE FROM employees;

INSERT INTO employees


VALUES (100, 10, 'Price');

INSERT INTO employees


VALUES (101, 20, 'Sam');

INSERT INTO employees


VALUES (102, 20, 'Joseph');
INSERT INTO employees
VALUES (103, 20, 'Smith');

COMMIT;
END;
/

Focus Trainig Services, Pune Page 217


E. BOOLEAN Types
The following code shows an example of binding a BOOLEAN type as an in parameter to a PL/SQL
function, called in a dynamic SQL statement.

Step1:

CREATE OR REPLACE FUNCTION boolean_test (p_boolean IN BOOLEAN)


RETURN VARCHAR2 AUTHID DEFINER AS
BEGIN
IF p_boolean THEN
RETURN 'TRUE';
ELSE
RETURN 'FALSE';
END IF;
END;
/

SET SERVEROUTPUT ON
DECLARE
l_sql VARCHAR2(32767);
l_boolean BOOLEAN := TRUE;
l_result VARCHAR2(10);
BEGIN
l_sql := 'SELECT boolean_test(:l_boolean) INTO :l_result FROM
dual';
EXECUTE IMMEDIATE l_sql INTO l_result USING l_boolean;
DBMS_OUTPUT.put_line('l_result=' || l_result);
END;

Step2:

OUTPUT:
/

l_result=TRUE

PL/SQL procedure successfully completed.

Notice what happens if we try to substitute the bound BOOLEAN type for a BOOLEAN literal.

DECLARE
l_sql VARCHAR2(32767);
l_result VARCHAR2(10);
BEGIN
l_sql := 'SELECT boolean_test(TRUE) INTO :l_result FROM dual';
EXECUTE IMMEDIATE l_sql INTO l_result;

Focus Trainig Services, Pune Page 218


DBMS_OUTPUT.put_line('l_result=' || l_result);
END;
/

OUTPUT:
ERROR at line 1:
ORA-00904: "TRUE": invalid identifier
ORA-06512: at line 6

F. Record Types

The following code shows an example of binding record types in an anonymous blocked called from
dynamic SQL.

CREATE OR REPLACE PACKAGE test_pkg AUTHID DEFINER AS

TYPE rec_type IS RECORD (id NUMBER, description VARCHAR2(50));

PROCEDURE record_test (p_rec OUT rec_type);

END;
/

CREATE OR REPLACE PACKAGE BODY test_pkg AS

PROCEDURE record_test (p_rec OUT rec_type) AS


BEGIN
p_rec.id := 1;
p_rec.description := 'ONE';
END;

END;
/

SET SERVEROUTPUT ON
DECLARE
l_sql VARCHAR2(32767);
l_record test_pkg.rec_type;
BEGIN
l_sql := 'BEGIN test_pkg.record_test(:l_record); END;';

EXECUTE IMMEDIATE l_sql USING OUT l_record;

DBMS_OUTPUT.PUT_LINE('l_record.id = ' || l_record.id);

Focus Trainig Services, Pune Page 219


DBMS_OUTPUT.PUT_LINE('l_record.description = ' ||
l_record.description);
END;
/

OUTPUT:
l_record.id = 1
l_record.description = ONE

PL/SQL procedure successfully completed.

G. Collections

The following code shows an asociative array being bound. Currently, only associative arrays using
INDEX BY PLS_INTEGER can be bound in this way, not those using INDEX BY VARCHAR2

CREATE OR REPLACE PACKAGE test_pkg AUTHID DEFINER AS

TYPE collection_type IS TABLE OF VARCHAR2(10)


INDEX BY PLS_INTEGER;

FUNCTION display_collection_contents (p_collection IN


collection_type)
RETURN NUMBER;

END;
/

CREATE OR REPLACE PACKAGE BODY test_pkg AS


FUNCTION display_collection_contents (p_collection IN
collection_type)
RETURN NUMBER IS
BEGIN
FOR i IN p_collection.FIRST .. p_collection.LAST LOOP
DBMS_OUTPUT.put_line(i || ' : ' || p_collection(i));
END LOOP;

RETURN p_collection.COUNT;
END;
END;
/

SET SERVEROUTPUT ON
DECLARE
l_sql VARCHAR2(32767);
l_collection test_pkg.collection_type;
l_result NUMBER;
BEGIN

Focus Trainig Services, Pune Page 220


l_collection(1) := 'ONE';
l_collection(2) := 'TWO';
l_collection(3) := 'THREE';

l_sql := 'SELECT
test_pkg.display_collection_contents(:l_collection) INTO :l_result
FROM dual';
EXECUTE IMMEDIATE l_sql INTO l_result USING l_collection;
DBMS_OUTPUT.put_line('l_result=' || l_result);
END;
/

OUTPUT:
1 : ONE
2 : TWO
3 : THREE
l_result=3

PL/SQL procedure successfully completed.

The following example is similar to the previous associative array example, but it uses a nested table
type.

CREATE OR REPLACE PACKAGE test_pkg AUTHID DEFINER AS

TYPE collection_type IS TABLE OF VARCHAR2(10);

FUNCTION display_collection_contents (p_collection IN


collection_type)
RETURN NUMBER;

END;
/

CREATE OR REPLACE PACKAGE BODY test_pkg AS


FUNCTION display_collection_contents (p_collection IN
collection_type)
RETURN NUMBER IS
BEGIN
FOR i IN p_collection.FIRST .. p_collection.LAST LOOP
DBMS_OUTPUT.put_line(i || ' : ' || p_collection(i));
END LOOP;

RETURN p_collection.COUNT;

Focus Trainig Services, Pune Page 221


END;
END;
/

SET SERVEROUTPUT ON
DECLARE
l_sql VARCHAR2(32767);
l_collection test_pkg.collection_type;
l_result NUMBER;
BEGIN
l_collection := test_pkg.collection_type('ONE', 'TWO', 'THREE');

l_sql := 'SELECT
test_pkg.display_collection_contents(:l_collection) INTO :l_result
FROM dual';
EXECUTE IMMEDIATE l_sql INTO l_result USING l_collection;
DBMS_OUTPUT.put_line('l_result=' || l_result);
END;
/

OUTPUT:
1 : ONE
2 : TWO
3 : THREE
l_result=3

PL/SQL procedure successfully completed.

The VARRAY example below is very similar to that for nested tables.

CREATE OR REPLACE PACKAGE test_pkg AUTHID DEFINER AS

TYPE collection_type IS VARRAY(10) OF VARCHAR2(10);

FUNCTION display_collection_contents (p_collection IN


collection_type)
RETURN NUMBER;

END;
/

CREATE OR REPLACE PACKAGE BODY test_pkg AS


FUNCTION display_collection_contents (p_collection IN
collection_type)
RETURN NUMBER IS
BEGIN
FOR i IN p_collection.FIRST .. p_collection.LAST LOOP
Focus Trainig Services, Pune Page 222
DBMS_OUTPUT.put_line(i || ' : ' || p_collection(i));
END LOOP;

RETURN p_collection.COUNT;
END;
END;
/

SET SERVEROUTPUT ON
DECLARE
l_sql VARCHAR2(32767);
l_collection test_pkg.collection_type;
l_result NUMBER;
BEGIN
l_collection := test_pkg.collection_type('ONE', 'TWO', 'THREE');

l_sql := 'SELECT
test_pkg.display_collection_contents(:l_collection) INTO :l_result
FROM dual';
EXECUTE IMMEDIATE l_sql INTO l_result USING l_collection;
DBMS_OUTPUT.put_line('l_result=' || l_result);
END;
/

OUTPUT:
1 : ONE
2 : TWO
3 : THREE
l_result=3

PL/SQL procedure successfully completed.

H. TABLE Operator

The following code defines a pipelined table function that accepts a PL/SQL collection and pipes its
contents out a rows, so it can be queried using the TABLE operator.

Focus Trainig Services, Pune Page 223


CREATE OR REPLACE PACKAGE test_pkg AUTHID DEFINER AS

TYPE collection_type IS TABLE OF VARCHAR2(10);

FUNCTION display_collection_contents (p_collection IN


collection_type)
RETURN collection_type PIPELINED;

END;
/

CREATE OR REPLACE PACKAGE BODY test_pkg AS


FUNCTION display_collection_contents (p_collection IN
collection_type)
RETURN collection_type PIPELINED IS
BEGIN
FOR i IN p_collection.FIRST .. p_collection.LAST LOOP
PIPE ROW (p_collection(i));
END LOOP;

RETURN;
END;
END;
/

SET SERVEROUTPUT ON
DECLARE
l_sql VARCHAR2(32767);
l_collection test_pkg.collection_type;
l_result NUMBER;
BEGIN
l_collection := test_pkg.collection_type('ONE', 'TWO', 'THREE');

l_sql := 'SELECT COUNT(*) INTO :l_result FROM


TABLE(test_pkg.display_collection_contents(:l_collection))';
EXECUTE IMMEDIATE l_sql INTO l_result USING l_collection;
DBMS_OUTPUT.put_line('l_result=' || l_result);
END;
/

OUTPUT:
l_result=3

PL/SQL procedure successfully completed.

Focus Trainig Services, Pune Page 224

You might also like