Professional Documents
Culture Documents
PL - SQL QuickGuide PDF
PL - SQL QuickGuide PDF
PL/SQL - Overview
The PL/SQL programming language was developed by Oracle Corporation in the late 1980s as procedural
extension language for SQL and the Oracle relational database. Following are certain notable facts about
PL/SQL −
● PL/SQL can also directly be called from the command-line SQL*Plus interface.
● Direct call can also be made from external programming language calls to database.
● PL/SQL's general syntax is based on that of ADA and Pascal programming language.
● Apart from Oracle, PL/SQL is available in TimesTen in-memory database and IBM DB2.
Features of PL/SQL
PL/SQL has the following features −
Advantages of PL/SQL
PL/SQL has the following advantages −
● SQL is the standard database language and PL/SQL is strongly integrated with SQL. PL/SQL supports both static and
dynamic SQL. Static SQL supports DML operations and transaction control from PL/SQL block. In Dynamic SQL, SQL
allows embedding DDL statements in PL/SQL blocks.
● PL/SQL allows sending an entire block of statements to the database at one time. This reduces network traffic and
provides high performance for the applications.
● PL/SQL gives high productivity to programmers as it can query, transform, and update data in a database.
● PL/SQL saves time on design and debugging by strong features, such as exception handling, encapsulation, data
hiding, and object-oriented data types.
● PL/SQL provides support for developing Web Applications and Server Pages.
To run PL/SQL programs, you should have the Oracle RDBMS Server installed in your machine. This will take
care of the execution of the SQL commands. The most recent version of Oracle RDBMS is 11g. You can
download a trial version of Oracle 11g from the following link −
You will have to download either the 32-bit or the 64-bit version of the installation as per your operating
system. Usually there are two files. We have downloaded the 64-bit version. You will also use similar steps on
your operating system, does not matter if it is Linux or Solaris.
● win64_11gR2_database_1of2.zip
● win64_11gR2_database_2of2.zip
After downloading the above two files, you will need to unzip them in a single directory database and under
that you will find the following sub-directories −
Step 1
Let us now launch the Oracle Database Installer using the setup file. Following is the first screen. You can
provide your email ID and check the checkbox as shown in the following screenshot. Click the Next button.
Step 2
You will be directed to the following screen; uncheck the checkbox and click the Continue button to proceed.
Step 3
Just select the first option Create and Configure Database using the radio button and click the Next button to
proceed.
Step 4
We assume you are installing Oracle for the basic purpose of learning and that you are installing it on your PC
or Laptop. Thus, select the Desktop Class option and click the Next button to proceed.
Step 5
Provide a location, where you will install the Oracle Server. Just modify the Oracle Base and the other
locations will set automatically. You will also have to provide a password; this will be used by the system DBA.
Once you provide the required information, click the Next button to proceed.
Step 6
Again, click the Next button to proceed.
Step 7
Click the Finish button to proceed; this will start the actual server installation.
Step 8
This will take a few moments, until Oracle starts performing the required configuration.
Step 9
Here, Oracle installation will copy the required configuration files. This should take a moment −
Step 10
Once the database files are copied, you will have the following dialogue box. Just click the OK button and
come out.
Step 11
Upon installation, you will have the following final window.
Final Step
It is now time to verify your installation. At the command prompt, use the following command if you are
using Windows −
● Type your code in a text editor, like Notepad, Notepad+, or EditPlus, etc.
● Save the file with the .sql extension in the home directory.
● Launch the SQL*Plus command prompt from the directory where you created your PL/SQL file.
If you are not using a file to execute the PL/SQL scripts, then simply copy your PL/SQL code and right-click on
the black window that displays the SQL prompt; use the paste option to paste the complete code at the
command prompt. Finally, just press Enter to execute the code, if it is not already executed.
Declarations
1
This section starts with the keyword DECLARE. It is an optional section and defines all
variables, cursors, subprograms, and other elements to be used in the program.
Executable Commands
This section is enclosed between the keywords BEGIN and END and it is a mandatory
2
section. It consists of the executable PL/SQL statements of the program. It should have at
least one executable line of code, which may be just a NULL command to indicate that
nothing should be executed.
Exception Handling
3
This section starts with the keyword EXCEPTION. This optional section
contains exception(s) that handle errors in the program.
Every PL/SQL statement ends with a semicolon (;). PL/SQL blocks can be nested within other PL/SQL blocks
using BEGIN and END. Following is the basic structure of a PL/SQL block −
DECLARE
<declarations section>
BEGIN
<executable command(s)>
EXCEPTION
<exception handling>
END;
The end; line signals the end of the PL/SQL block. To run the code from the SQL command line, you may need
to type / at the beginning of the first blank line after the last line of the code. When the above code is
executed at the SQL prompt, it produces the following result −
Hello World
By default, identifiers are not case-sensitive. So you can use integer or INTEGER to represent a numeric
value. You cannot use a reserved keyword as an identifier.
Delimiter Description
% Attribute indicator
. Component selector
, Item separator
= Relational operator
; Statement terminator
:= Assignment operator
|| Concatenation operator
** Exponentiation operator
.. Range operator
The PL/SQL supports single-line and multi-line comments. All characters available inside any comment are
ignored by the PL/SQL compiler. The PL/SQL single-line comments start with the delimiter -- (double hyphen)
and multi-line comments are enclosed by /* and */.
DECLARE
-- variable declaration
message varchar2(20):= 'Hello, World!';
BEGIN
/*
* PL/SQL executable statement(s)
*/
dbms_output.put_line(message);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Hello World
● PL/SQL block
● Function
● Package
● Package body
● Procedure
● Trigger
● Type
● Type body
Each of these units will be discussed in the following chapters.
Scalar
1
Single values with no internal components, such as a NUMBER, DATE, or BOOLEAN.
Composite
3
Data items that have internal components that can be accessed individually. For example,
collections and records.
Reference
4
Pointers to other data items.
Numeric
1
Numeric values on which arithmetic operations are performed.
Character
2
Alphanumeric values that represent single characters or strings of characters.
Boolean
3
Logical values on which logical operations are performed.
Datetime
4
Dates and times.
PL/SQL provides subtypes of data types. For example, the data type NUMBER has a subtype called INTEGER.
You can use the subtypes in your PL/SQL program to make the data types compatible with data types in other
programs while embedding the PL/SQL code in another program, such as a Java program.
PLS_INTEGER
1
Signed integer in range -2,147,483,648 through 2,147,483,647, represented in 32 bits
BINARY_INTEGER
2
Signed integer in range -2,147,483,648 through 2,147,483,647, represented in 32 bits
BINARY_FLOAT
3
Single-precision IEEE 754-format floating-point number
BINARY_DOUBLE
4
Double-precision IEEE 754-format floating-point number
NUMBER(prec, scale)
5
Fixed-point or floating-point number with absolute value in range 1E-130 to (but not
including) 1.0E126. A NUMBER variable can also represent 0
DEC(prec, scale)
6
ANSI specific fixed-point type with maximum precision of 38 decimal digits
DECIMAL(prec, scale)
7
IBM specific fixed-point type with maximum precision of 38 decimal digits
NUMERIC(pre, secale)
8
Floating type with maximum precision of 38 decimal digits
DOUBLE PRECISION
9
ANSI specific floating-point type with maximum precision of 126 binary digits (approximately
38 decimal digits)
FLOAT
10
ANSI and IBM specific floating-point type with maximum precision of 126 binary digits
(approximately 38 decimal digits)
INT
11
ANSI specific integer type with maximum precision of 38 decimal digits
INTEGER
12
ANSI and IBM specific integer type with maximum precision of 38 decimal digits
SMALLINT
13
ANSI and IBM specific integer type with maximum precision of 38 decimal digits
REAL
14
Floating-point type with maximum precision of 63 binary digits (approximately 18 decimal
digits)
DECLARE
num1 INTEGER;
num2 REAL;
num3 DOUBLE PRECISION;
BEGIN
null;
END;
/
When the above code is compiled and executed, it produces the following result −
CHAR
1
Fixed-length character string with maximum size of 32,767 bytes
VARCHAR2
2
Variable-length character string with maximum size of 32,767 bytes
RAW
3
Variable-length binary or byte string with maximum size of 32,767 bytes, not interpreted by
PL/SQL
NCHAR
4
Fixed-length national character string with maximum size of 32,767 bytes
NVARCHAR2
5
Variable-length national character string with maximum size of 32,767 bytes
LONG
6
Variable-length character string with maximum size of 32,760 bytes
LONG RAW
7
Variable-length binary or byte string with maximum size of 32,760 bytes, not interpreted by
PL/SQL
ROWID
8
Physical row identifier, the address of a row in an ordinary table
UROWID
9
Universal row identifier (physical, logical, or foreign row identifier)
● SQL statements
The default date format is set by the Oracle initialization parameter NLS_DATE_FORMAT. For example, the
default might be 'DD-MON-YY', which includes a two-digit number for the day of the month, an abbreviation
of the month name, and the last two digits of the year. For example, 01-OCT-12.
Each DATE includes the century, year, month, day, hour, minute, and second. The following table shows the
valid values for each field −
MONTH 01 to 12 0 to 11
HOUR 00 to 23 0 to 23
MINUTE 00 to 59 0 to 59
PL/SQL predefines several subtypes in package STANDARD. For example, PL/SQL predefines the
subtypes CHARACTER and INTEGER as follows −
DECLARE
SUBTYPE name IS char(20);
SUBTYPE message IS varchar2(100);
salutation name;
greetings message;
BEGIN
salutation := 'Reader ';
greetings := 'Welcome to the World of PL/SQL';
dbms_output.put_line('Hello ' || salutation || greetings);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
NULLs in PL/SQL
PL/SQL NULL values represent missing or unknown data and they are not an integer, a character, or any
other specific data type. Note that NULL is not the same as an empty data string or the null character
value '\0'. A null can be assigned but it cannot be equated with anything, including itself.
PL/SQL - Variables
In this chapter, we will discuss Variables in Pl/SQL. A variable is nothing but a name given to a storage area
that our programs can manipulate. Each variable in PL/SQL has a specific data type, which determines the size
and the layout of the variable's memory; the range of values that can be stored within that memory and the
set of operations that can be applied to the variable.
The name of a PL/SQL variable consists of a letter optionally followed by more letters, numerals, dollar signs,
underscores, and number signs and should not exceed 30 characters. By default, variable names are not
case-sensitive. You cannot use a reserved PL/SQL keyword as a variable name.
PL/SQL programming language allows to define various types of variables, such as date time data types,
records, collections, etc. which we will cover in subsequent chapters. For this chapter, let us study only basic
variable types.
For example −
counter binary_integer := 0;
greetings varchar2(20) DEFAULT 'Have a Good Day';
You can also specify that a variable should not have a NULL value using the NOT NULL constraint. If you use
the NOT NULL constraint, you must explicitly assign an initial value for that variable.
It is a good programming practice to initialize variables properly otherwise, sometimes programs would
produce unexpected results. Try the following example which makes use of various types of variables −
DECLARE
a integer := 10;
b integer := 20;
c integer;
f real;
BEGIN
c := a + b;
dbms_output.put_line('Value of c: ' || c);
f := 70.0/3.0;
dbms_output.put_line('Value of f: ' || f);
END;
/
Value of c: 30
Value of f: 23.333333333333333333
● Local variables − Variables declared in an inner block and not accessible to outer blocks.
Following example shows the usage of Local and Global variables in its simple form −
DECLARE
-- Global variables
num1 number := 95;
num2 number := 85;
BEGIN
dbms_output.put_line('Outer Variable num1: ' || num1);
dbms_output.put_line('Outer Variable num2: ' || num2);
DECLARE
-- Local variables
num1 number := 195;
num2 number := 185;
BEGIN
dbms_output.put_line('Inner Variable num1: ' || num1);
dbms_output.put_line('Inner Variable num2: ' || num2);
END;
END;
/
Table Created
The following program assigns values from the above table to PL/SQL variables using the SELECT INTO
clause of SQL −
DECLARE
c_id customers.id%type := 1;
c_name customerS.No.ame%type;
c_addr customers.address%type;
c_sal customers.salary%type;
BEGIN
SELECT name, address, salary INTO c_name, c_addr, c_sal
FROM customers
WHERE id = c_id;
dbms_output.put_line
('Customer ' ||c_name || ' from ' || c_addr || ' earns ' || c_sal);
END;
/
Declaring a Constant
A constant is declared using the CONSTANT keyword. It requires an initial value and does not allow that value
to be changed. For example −
When the above code is executed at the SQL prompt, it produces the following result −
Radius: 9.5
Diameter: 19
Circumference: 59.69
Area: 283.53
● Numeric Literals
● Character Literals
● String Literals
● BOOLEAN Literals
Numeric Literals
Character Literals
2
'A' '%' '9' ' ' 'z' '('
String Literals
'Hello, world!'
3
'Tutorials Point'
'19-NOV-12'
BOOLEAN Literals
4
TRUE, FALSE, and NULL.
5 DATE '1978-12-25';
To embed single quotes within a string literal, place two single quotes next to each other as shown in the
following program −
DECLARE
message varchar2(30):= 'That''s Zarantech.com!';
BEGIN
dbms_output.put_line(message);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
That's Zarantech.com!
PL/SQL - Operators
In this chapter, we will discuss operators in PL/SQL. An operator is a symbol that tells the compiler to perform
specific mathematical or logical manipulation. PL/SQL language is rich in built-in operators and provides the
following types of operators −
● Arithmetic operators
● Relational operators
● Comparison operators
● Logical operators
● String operators
Here, we will understand the arithmetic, relational, comparison and logical operators one by one. The String
operators will be discussed in a later chapter − PL/SQL - Strings.
Arithmetic Operators
Following table shows all the arithmetic operators supported by PL/SQL. Let us assume variable A holds 10
and variable B holds 5, then −
Show Examples
** Exponentiation operator, raises one operand to the power of A ** B will give 100000
other
Relational Operators
Relational operators compare two expressions or values and return a Boolean result. Following table shows
all the relational operators supported by PL/SQL. Let us assume variable A holds 10 and variable B holds 20,
then −
Show Examples
Checks if the values of two operands are equal or not, if yes then (A = B) is not
=
condition becomes true. true.
!=
Checks if the values of two operands are equal or not, if values are
<> (A != B) is true.
not equal then condition becomes true.
~=
Checks if the value of left operand is greater than the value of right (A > B) is not
>
operand, if yes then condition becomes true. true.
Checks if the value of left operand is less than the value of right (A < B) is true.
<
operand, if yes then condition becomes true.
Checks if the value of left operand is greater than or equal to the (A >= B) is not
>=
value of right operand, if yes then condition becomes true. true.
Checks if the value of left operand is less than or equal to the value (A <= B) is true
<=
of right operand, if yes then condition becomes true.
Comparison Operators
Comparison operators are used for comparing one expression to another. The result is always either TRUE,
FALSE or NULL.
Show Examples
The LIKE operator compares a character, string, If 'Zara Ali' like 'Z% A_i' returns a
or CLOB value to a pattern and returns TRUE if Boolean true, whereas, 'Nuha Ali'
LIKE
the value matches the pattern and FALSE if it like 'Z% A_i' returns a Boolean false.
does not.
The IN operator tests set membership. x IN (set) If x = 'm' then, x in ('a', 'b', 'c')
IN means that x is equal to any member of set. returns Boolean false but x in ('m',
'n', 'o') returns Boolean true.
Logical Operators
Following table shows the Logical operators supported by PL/SQL. All these operators work on Boolean
operands and produce Boolean results. Let us assume variable A holds true and variable B holds false, then −
Show Examples
Called the logical AND operator. If both the operands are true then (A and B) is false.
and
condition becomes true.
Called the logical OR Operator. If any of the two operands is true (A or B) is true.
or
then condition becomes true.
Called the logical NOT Operator. Used to reverse the logical state of not (A and B) is
not its operand. If a condition is true then Logical NOT operator will true.
make it false.
For example, x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher precedence than +, so
it first gets multiplied with 3*2 and then adds into 7.
Here, operators with the highest precedence appear at the top of the table, those with the lowest appear at
the bottom. Within an expression, higher precedence operators will be evaluated first.
The precedence of operators goes as follows: =, <, >, <=, >=, <>, !=, ~=, ^=, IS NULL, LIKE, BETWEEN, IN.
Show Examples
Operator Operation
** exponentiation
+, - identity, negation
*, / multiplication, division
AND conjunction
OR inclusion
PL/SQL - Conditions
In this chapter, we will discuss conditions in PL/SQL. Decision-making structures require that the programmer
specify one or more conditions to be evaluated or tested by the program, along with a statement or
statements to be executed if the condition is determined to be true, and optionally, other statements to be
executed if the condition is determined to be false.
Following is the general form of a typical conditional (i.e., decision making) structure found in most of the
programming languages −
PL/SQL programming language provides following types of decision-making statements. Click the following
links to check their detail.
IF - THEN statement
1
The IF statement associates a condition with a sequence of statements enclosed by the
keywords THEN and END IF. If the condition is true, the statements get executed and if the
condition is false or NULL then the IF statement does nothing.
IF-THEN-ELSE statement
IF-THEN-ELSIF statement
3
It allows you to choose between several alternatives.
Case statement
Like the IF statement, the CASE statement selects one sequence of statements to execute.
4
However, to select the sequence, the CASE statement uses a selector rather than multiple
Boolean expressions. A selector is an expression whose value is used to select one of several
alternatives.
nested IF-THEN-ELSE
6
You can use one IF-THEN or IF-THEN-ELSIF statement inside
another IF-THEN or IF-THEN-ELSIF statement(s).
PL/SQL - Loops
In this chapter, we will discuss Loops in PL/SQL. There may be a situation when you need to execute a block
of code several number of times. In general, statements are executed sequentially: The first statement in a
function is executed first, followed by the second, and so on.
Programming languages provide various control structures that allow for more complicated execution paths.
A loop statement allows us to execute a statement or group of statements multiple times and following is the
general form of a loop statement in most of the programming languages −
PL/SQL provides the following types of loop to handle the looping requirements. Click the following links to
check their detail.
1 In this loop structure, sequence of statements is enclosed between the LOOP and the END
LOOP statements. At each iteration, the sequence of statements is executed and then
control resumes at the top of the loop.
DECLARE
i number(1);
j number(1);
BEGIN
<< outer_loop >>
FOR i IN 1..3 LOOP
<< inner_loop >>
FOR j IN 1..3 LOOP
dbms_output.put_line('i is: '|| i || ' and j is: ' || j);
END loop inner_loop;
END loop outer_loop;
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
PL/SQL supports the following control statements. Labeling loops also help in taking the control outside a
loop. Click the following links to check their details.
EXIT statement
1
The Exit statement completes the loop and control passes to the statement immediately
after the END LOOP.
CONTINUE statement
2
Causes the loop to skip the remainder of its body and immediately retest its condition prior
to reiterating.
GOTO statement
3
Transfers control to the labeled statement. Though it is not advised to use the GOTO
statement in your program.
PL/SQL - Strings
The string in PL/SQL is actually a sequence of characters with an optional size specification. The characters
could be numeric, letters, blank, special characters or a combination of all. PL/SQL offers three kinds of
strings −
● Fixed-length strings − In such strings, programmers specify the length while declaring the string. The string is
right-padded with spaces to the length so specified.
● Variable-length strings − In such strings, a maximum length up to 32,767, for the string is specified and no padding
takes place.
● Character large objects (CLOBs) − These are variable-length strings that can be up to 128 terabytes.
PL/SQL strings could be either variables or literals. A string literal is enclosed within quotation marks. For
example,
If you need to declare a variable-length string, you must provide the maximum length of that string. For
example, the VARCHAR2 data type. The following example illustrates declaring and using some string
variables −
DECLARE
name varchar2(20);
company varchar2(30);
introduction clob;
choice char(1);
BEGIN
name := 'John Smith';
company := 'Infotech';
introduction := ' Hello! I''m John Smith from Infotech.';
choice := 'y';
IF choice = 'y' THEN
dbms_output.put_line(name);
dbms_output.put_line(company);
dbms_output.put_line(introduction);
END IF;
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
John Smith
Infotech Corporation
Hello! I'm John Smith from Infotech.
ASCII(x);
1
Returns the ASCII value of the character x.
CHR(x);
2
Returns the character with the ASCII value of x.
CONCAT(x, y);
3
Concatenates the strings x and y and returns the appended string.
INITCAP(x);
4
Converts the initial letter of each word in x to uppercase and returns that string.
INSTRB(x);
6
Returns the location of a string within another string, but returns the value in bytes.
LENGTH(x);
7
Returns the number of characters in x.
LENGTHB(x);
8
Returns the length of a character string in bytes for single byte character set.
LOWER(x);
9
Converts the letters in x to lowercase and returns that string.
LTRIM(x [, trim_string]);
11
Trims characters from the left of x.
NANVL(x, value);
12
Returns value if x matches the NaN special value (not a number), otherwise x is returned.
NLS_INITCAP(x);
13
Same as the INITCAP function except that it can use a different sort method as specified by
NLSSORT.
NLS_LOWER(x) ;
14
Same as the LOWER function except that it can use a different sort method as specified by
NLSSORT.
NLS_UPPER(x);
15
Same as the UPPER function except that it can use a different sort method as specified by
NLSSORT.
NLSSORT(x);
16
Changes the method of sorting the characters. Must be specified before any NLS function;
otherwise, the default sort will be used.
NVL(x, value);
17
Returns value if x is null; otherwise, x is returned.
RTRIM(x [, trim_string]);
21
Trims x from the right.
SOUNDEX(x) ;
22
Returns a string containing the phonetic representation of x.
SUBSTRB(x);
24
Same as SUBSTR except that the parameters are expressed in bytes instead of characters for
the single-byte character systems.
UPPER(x);
26
Converts the letters in x to uppercase and returns that string.
Example 1
DECLARE
greetings varchar2(11) := 'hello world';
BEGIN
dbms_output.put_line(UPPER(greetings));
dbms_output.put_line(LOWER(greetings));
dbms_output.put_line(INITCAP(greetings));
When the above code is executed at the SQL prompt, it produces the following result −
HELLO WORLD
hello world
Hello World
h
d
World
ello World
2
Example 2
DECLARE
greetings varchar2(30) := '......Hello World.....';
BEGIN
dbms_output.put_line(RTRIM(greetings,'.'));
dbms_output.put_line(LTRIM(greetings, ' .'));
dbms_output.put_line(TRIM( '.' from greetings));
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
......Hello World
Hello World.....
Hello World
PL/SQL - Arrays
In this chapter, we will discuss arrays in PL/SQL. The PL/SQL programming language provides a data structure
called the VARRAY, which can store a fixed-size sequential collection of elements of the same type. A varray
is used to store an ordered collection of data, however it is often better to think of an array as a collection of
variables of the same type.
All varrays consist of contiguous memory locations. The lowest address corresponds to the first element and
the highest address to the last element.
An array is a part of collection type data and it stands for variable-size arrays. We will study other collection
types in a later chapter 'PL/SQL Collections'.
Each element in a varray has an index associated with it. It also has a maximum size that can be changed
dynamically.
Creating a Varray Type
A varray type is created with the CREATE TYPE statement. You must specify the maximum size and the type
of elements stored in the varray.
The basic syntax for creating a VARRAY type at the schema level is −
For example,
Type created.
The basic syntax for creating a VARRAY type within a PL/SQL block is −
Example 1
The following program illustrates the use of varrays −
DECLARE
type namesarray IS VARRAY(5) OF VARCHAR2(10);
type grades IS VARRAY(5) OF INTEGER;
names namesarray;
marks grades;
total integer;
BEGIN
names := namesarray('Kavita', 'Pritam', ' Ayan', 'Rishav', 'Aziz');
marks:= grades(98, 97, 78, 87, 92);
total := names.count;
dbms_output.put_line('Total '|| total || ' Students');
FOR i in 1 .. total LOOP
dbms_output.put_line('Student: ' || names(i) || '
Marks: ' || marks(i));
END LOOP;
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Total 5 Students
Student: Kavita Marks: 98
Student: Pritam Marks: 97
Student: Ayan Marks: 78
Student: Rishav Marks: 87
Student: Aziz Marks: 92
● You can initialize the varray elements using the constructor method of the varray type, which has the same name as
the varray.
● A varray is automatically NULL when it is declared and must be initialized before its elements can be referenced.
Example 2
Elements of a varray could also be a %ROWTYPE of any database table or %TYPE of any database table field.
The following example illustrates the concept.
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
+----+----------+-----+-----------+----------+
Following example makes the use of cursor, which you will study in detail in a separate chapter.
DECLARE
CURSOR c_customers is
SELECT name FROM customers;
type c_list is varray (6) of customerS.No.ame%type;
name_list c_list := c_list();
counter integer :=0;
BEGIN
FOR n IN c_customers LOOP
counter := counter + 1;
name_list.extend;
name_list(counter) := n.name;
dbms_output.put_line('Customer('||counter ||'):'||name_list(counter));
END LOOP;
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal
PL/SQL - Procedures
In this chapter, we will discuss Procedures in PL/SQL. A subprogram is a program unit/module that performs
a particular task. These subprograms are combined to form larger programs. This is basically called the
'Modular design'. A subprogram can be invoked by another subprogram or program which is called the calling
program.
● Inside a package
PL/SQL subprograms are named PL/SQL blocks that can be invoked with a set of parameters. PL/SQL provides
two kinds of subprograms −
● Functions − These subprograms return a single value; mainly used to compute and return a value.
● Procedures − These subprograms do not return a value directly; mainly used to perform an action.
This chapter is going to cover important aspects of a PL/SQL procedure. We will discuss PL/SQL function in
the next chapter.
Declarative Part
1 It is an optional part. However, the declarative part for a subprogram does not start with the
DECLARE keyword. It contains declarations of types, cursors, constants, variables,
exceptions, and nested subprograms. These items are local to the subprogram and cease to
exist when the subprogram completes execution.
Executable Part
2
This is a mandatory part and contains statements that perform the designated action.
Exception-handling
3
This is again an optional part. It contains the code that handles run-time errors.
Creating a Procedure
A procedure is created with the CREATE OR REPLACE PROCEDURE statement. The simplified syntax for the
CREATE OR REPLACE PROCEDURE statement is as follows −
Where,
● The optional parameter list contains name, mode and types of the parameters. IN represents the value that will be
passed from outside and OUT represents the parameter that will be used to return a value outside of the procedure.
● The AS keyword is used instead of the IS keyword for creating a standalone procedure.
Example
The following example creates a simple procedure that displays the string 'Hello World!' on the screen when
executed.
When the above code is executed using the SQL prompt, it will produce the following result −
Procedure created.
The above procedure named 'greetings' can be called with the EXECUTE keyword as −
EXECUTE greetings;
The above call will display −
Hello World
BEGIN
greetings;
END;
/
Hello World
IN
An IN parameter lets you pass a value to the subprogram. It is a read-only parameter. Inside
1 the subprogram, an IN parameter acts like a constant. It cannot be assigned a value. You can
pass a constant, literal, initialized variable, or expression as an IN parameter. You can also
initialize it to a default value; however, in that case, it is omitted from the subprogram call. It
is the default mode of parameter passing. Parameters are passed by reference.
OUT
2 An OUT parameter returns a value to the calling program. Inside the subprogram, an OUT
parameter acts like a variable. You can change its value and reference the value after
assigning it. The actual parameter must be variable and it is passed by value.
IN OUT
An IN OUT parameter passes an initial value to a subprogram and returns an updated value
to the caller. It can be assigned a value and the value can be read.
3
The actual parameter corresponding to an IN OUT formal parameter must be a variable, not
a constant or an expression. Formal parameter must be assigned a value. Actual parameter
is passed by value.
DECLARE
a number;
b number;
c number;
PROCEDURE findMin(x IN number, y IN number, z OUT number) IS
BEGIN
IF x < y THEN
z:= x;
ELSE
z:= y;
END IF;
END;
BEGIN
a:= 23;
b:= 45;
findMin(a, b, c);
dbms_output.put_line(' Minimum of (23, 45) : ' || c);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
DECLARE
a number;
PROCEDURE squareNum(x IN OUT number) IS
BEGIN
x := x * x;
END;
BEGIN
a:= 23;
squareNum(a);
dbms_output.put_line(' Square of (23): ' || a);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
● Positional notation
● Named notation
● Mixed notation
Positional Notation
In positional notation, you can call the procedure as −
findMin(a, b, c, d);
In positional notation, the first actual parameter is substituted for the first formal parameter; the second
actual parameter is substituted for the second formal parameter, and so on. So, a is substituted for x, b is
substituted for y, c is substituted for z and d is substituted for m.
Named Notation
In named notation, the actual parameter is associated with the formal parameter using the arrow symbol (
=> ). The procedure call will be like the following −
Mixed Notation
In mixed notation, you can mix both notations in procedure call; however, the positional notation should
precede the named notation.
PL/SQL - Functions
In this chapter, we will discuss the functions in PL/SQL. A function is same as a procedure except that it
returns a value. Therefore, all the discussions of the previous chapter are true for functions too.
Creating a Function
A standalone function is created using the CREATE FUNCTION statement. The simplified syntax for
the CREATE OR REPLACE PROCEDURE statement is as follows −
● The optional parameter list contains name, mode and types of the parameters. IN represents the value that will be
passed from outside and OUT represents the parameter that will be used to return a value outside of the procedure.
● The RETURN clause specifies the data type you are going to return from the function.
● The AS keyword is used instead of the IS keyword for creating a standalone function.
Example
The following example illustrates how to create and call a standalone function. This function returns the total
number of CUSTOMERS in the customers table.
We will use the CUSTOMERS table, which we had created in the PL/SQL Variables chapter −
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
+----+----------+-----+-----------+----------+
CREATE OR REPLACE FUNCTION totalCustomers
RETURN number IS
total number(2) := 0;
BEGIN
SELECT count(*) into total
FROM customers;
RETURN total;
END;
/
When the above code is executed using the SQL prompt, it will produce the following result −
Function created.
Calling a Function
While creating a function, you give a definition of what the function has to do. To use a function, you will
have to call that function to perform the defined task. When a program calls a function, the program control
is transferred to the called function.
A called function performs the defined task and when its return statement is executed or when the last end
statement is reached, it returns the program control back to the main program.
To call a function, you simply need to pass the required parameters along with the function name and if the
function returns a value, then you can store the returned value. Following program calls the
function totalCustomers from an anonymous block −
DECLARE
c number(2);
BEGIN
c := totalCustomers();
dbms_output.put_line('Total no. of Customers: ' || c);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Example
The following example demonstrates Declaring, Defining, and Invoking a Simple PL/SQL Function that
computes and returns the maximum of two values.
DECLARE
a number;
b number;
c number;
FUNCTION findMax(x IN number, y IN number)
RETURN number
IS
z number;
BEGIN
IF x > y THEN
z:= x;
ELSE
Z:= y;
END IF;
RETURN z;
END;
BEGIN
a:= 23;
b:= 45;
c := findMax(a, b);
dbms_output.put_line(' Maximum of (23,45): ' || c);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Maximum of (23,45): 45
To illustrate the concept, let us calculate the factorial of a number. Factorial of a number n is defined as −
n! = n*(n-1)!
= n*(n-1)*(n-2)!
...
= n*(n-1)*(n-2)*(n-3)... 1
The following program calculates the factorial of a given number by calling itself recursively −
DECLARE
num number;
factorial number;
BEGIN
num:= 6;
factorial := fact(num);
dbms_output.put_line(' Factorial '|| num || ' is ' || factorial);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Factorial 6 is 720
PL/SQL - Cursors
In this chapter, we will discuss the cursors in PL/SQL. Oracle creates a memory area, known as the context
area, for processing an SQL statement, which contains all the information needed for processing the
statement; for example, the number of rows processed, etc.
A cursor is a pointer to this context area. PL/SQL controls the context area through a cursor. A cursor holds
the rows (one or more) returned by a SQL statement. The set of rows the cursor holds is referred to as
the active set.
You can name a cursor so that it could be referred to in a program to fetch and process the rows returned by
the SQL statement, one at a time. There are two types of cursors −
● Implicit cursors
● Explicit cursors
Implicit Cursors
Implicit cursors are automatically created by Oracle whenever an SQL statement is executed, when there is
no explicit cursor for the statement. Programmers cannot control the implicit cursors and the information in
it.
Whenever a DML statement (INSERT, UPDATE and DELETE) is issued, an implicit cursor is associated with this
statement. For INSERT operations, the cursor holds the data that needs to be inserted. For UPDATE and
DELETE operations, the cursor identifies the rows that would be affected.
In PL/SQL, you can refer to the most recent implicit cursor as the SQL cursor, which always has attributes
such as %FOUND, %ISOPEN, %NOTFOUND, and %ROWCOUNT. The SQL cursor has additional
attributes, %BULK_ROWCOUNT and %BULK_EXCEPTIONS, designed for use with the FORALL statement. The
following table provides the description of the most used attributes −
%FOUND
1
Returns TRUE if an INSERT, UPDATE, or DELETE statement affected one or more rows or a
SELECT INTO statement returned one or more rows. Otherwise, it returns FALSE.
%NOTFOUND
2 The logical opposite of %FOUND. It returns TRUE if an INSERT, UPDATE, or DELETE statement
affected no rows, or a SELECT INTO statement returned no rows. Otherwise, it returns
FALSE.
%ISOPEN
3
Always returns FALSE for implicit cursors, because Oracle closes the SQL cursor automatically
after executing its associated SQL statement.
%ROWCOUNT
4
Returns the number of rows affected by an INSERT, UPDATE, or DELETE statement, or
returned by a SELECT INTO statement.
Any SQL cursor attribute will be accessed as sql%attribute_name as shown below in the example.
Example
We will be using the CUSTOMERS table we had created and used in the previous chapters.
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
+----+----------+-----+-----------+----------+
The following program will update the table and increase the salary of each customer by 500 and use
the SQL%ROWCOUNT attribute to determine the number of rows affected −
DECLARE
total_rows number(2);
BEGIN
UPDATE customers
SET salary = salary + 500;
IF sql%notfound THEN
dbms_output.put_line('no customers selected');
ELSIF sql%found THEN
total_rows := sql%rowcount;
dbms_output.put_line( total_rows || ' customers selected ');
END IF;
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
6 customers selected
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2500.00 |
| 2 | Khilan | 25 | Delhi | 2000.00 |
| 3 | kaushik | 23 | Kota | 2500.00 |
| 4 | Chaitali | 25 | Mumbai | 7000.00 |
| 5 | Hardik | 27 | Bhopal | 9000.00 |
| 6 | Komal | 22 | MP | 5000.00 |
+----+----------+-----+-----------+----------+
Explicit Cursors
Explicit cursors are programmer-defined cursors for gaining more control over the context area. An explicit
cursor should be defined in the declaration section of the PL/SQL Block. It is created on a SELECT Statement
which returns more than one row.
CURSOR c_customers IS
SELECT id, name, address FROM customers;
OPEN c_customers;
CLOSE c_customers;
Example
Following is a complete example to illustrate the concepts of explicit cursors &minua;
DECLARE
c_id customers.id%type;
c_name customerS.No.ame%type;
c_addr customers.address%type;
CURSOR c_customers is
SELECT id, name, address FROM customers;
BEGIN
OPEN c_customers;
LOOP
FETCH c_customers into c_id, c_name, c_addr;
EXIT WHEN c_customers%notfound;
dbms_output.put_line(c_id || ' ' || c_name || ' ' || c_addr);
END LOOP;
CLOSE c_customers;
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
1 Ramesh Ahmedabad
2 Khilan Delhi
3 kaushik Kota
4 Chaitali Mumbai
5 Hardik Bhopal
6 Komal MP
PL/SQL - Records
In this chapter, we will discuss Records in PL/SQL. A record is a data structure that can hold data items of
different kinds. Records consist of different fields, similar to a row of a database table.
For example, you want to keep track of your books in a library. You might want to track the following
attributes about each book, such as Title, Author, Subject, Book ID. A record containing a field for each of
these items allows treating a BOOK as a logical unit and allows you to organize and represent its information
in a better way.
● Table-based
● Cursor-based records
● User-defined records
Table-Based Records
The %ROWTYPE attribute enables a programmer to create table-based and cursorbased records.
The following example illustrates the concept of table-based records. We will be using the CUSTOMERS table
we had created and used in the previous chapters −
DECLARE
customer_rec customers%rowtype;
BEGIN
SELECT * into customer_rec
FROM customers
WHERE id = 5;
dbms_output.put_line('Customer ID: ' | | customer_rec.id);
dbms_output.put_line('Customer Name: ' | | customer_rec.name);
dbms_output.put_line('Customer Address: ' || customer_rec.address);
dbms_output.put_line('Customer Salary: ' || customer_rec.salary);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Customer ID: 5
Customer Name: Hardik
Customer Address: Bhopal
Customer Salary: 9000
Cursor-Based Records
The following example illustrates the concept of cursor-based records. We will be using the CUSTOMERS
table we had created and used in the previous chapters −
DECLARE
CURSOR customer_cur is
SELECT id, name, address
FROM customers;
customer_rec customer_cur%rowtype;
BEGIN
OPEN customer_cur;
LOOP
FETCH customer_cur into customer_rec;
EXIT WHEN customer_cur%notfound;
DBMS_OUTPUT.put_line(customer_rec.id | | ' ' || customer_rec.name);
END LOOP;
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
1 Ramesh
2 Khilan
3 kaushik
4 Chaitali
5 Hardik
6 Komal
● Title
● Author
● Subject
● Book ID
Defining a Record
The record type is defined as −
TYPE
type_name IS RECORD
( field_name1 datatype1 [NOT NULL] [:= DEFAULT EXPRESSION],
field_name2 datatype2 [NOT NULL] [:= DEFAULT EXPRESSION],
...
field_nameN datatypeN [NOT NULL] [:= DEFAULT EXPRESSION);
record-name type_name;
The Book record is declared in the following way −
DECLARE
TYPE books IS RECORD
(title varchar(50),
author varchar(50),
subject varchar(100),
book_id number);
book1 books;
book2 books;
Accessing Fields
To access any field of a record, we use the dot (.) operator. The member access operator is coded as a period
between the record variable name and the field that we wish to access. Following is an example to explain
the usage of record −
DECLARE
type books is record
(title varchar(50),
author varchar(50),
subject varchar(100),
book_id number);
book1 books;
book2 books;
BEGIN
-- Book 1 specification
book1.title := 'C Programming';
book1.author := 'Nuha Ali ';
book1.subject := 'C Programming Tutorial';
book1.book_id := 6495407;
-- Book 2 specification
book2.title := 'Telecom Billing';
book2.author := 'Zara Ali';
book2.subject := 'Telecom Billing Tutorial';
book2.book_id := 6495700;
When the above code is executed at the SQL prompt, it produces the following result −
DECLARE
type books is record
(title varchar(50),
author varchar(50),
subject varchar(100),
book_id number);
book1 books;
book2 books;
PROCEDURE printbook (book books) IS
BEGIN
dbms_output.put_line ('Book title : ' | | book.title);
dbms_output.put_line('Book author : ' || book.author);
dbms_output.put_line( 'Book subject : ' || book.subject);
dbms_output.put_line( 'Book book_id : ' || book.book_id);
END;
BEGIN
-- Book 1 specification
book1.title := 'C Programming';
book1.author := 'Nuha Ali ';
book1.subject := 'C Programming Tutorial';
book1.book_id := 6495407;
PL/SQL - Exceptions
In this chapter, we will discuss Exceptions in PL/SQL. An exception is an error condition during a program
execution. PL/SQL supports programmers to catch such conditions using EXCEPTION block in the program
and an appropriate action is taken against the error condition. There are two types of exceptions −
● System-defined exceptions
● User-defined exceptions
DECLARE
<declarations section>
BEGIN
<executable command(s)>
EXCEPTION
<exception handling goes here >
WHEN exception1 THEN
exception1-handling-statements
WHEN exception2 THEN
exception2-handling-statements
WHEN exception3 THEN
exception3-handling-statements
........
WHEN others THEN
exception3-handling-statements
END;
Example
Let us write a code to illustrate the concept. We will be using the CUSTOMERS table we had created and used
in the previous chapters −
DECLARE
c_id customers.id%type := 8;
c_name customerS.No.ame%type;
c_addr customers.address%type;
BEGIN
SELECT name, address INTO c_name, c_addr
FROM customers
WHERE id = c_id;
DBMS_OUTPUT.PUT_LINE ('Name: '|| c_name);
DBMS_OUTPUT.PUT_LINE ('Address: ' || c_addr);
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('No such customer!');
WHEN others THEN
dbms_output.put_line('Error!');
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
No such customer!
Raising Exceptions
Exceptions are raised by the database server automatically whenever there is any internal database error, but
exceptions can be raised explicitly by the programmer by using the command RAISE. Following is the simple
syntax for raising an exception −
DECLARE
exception_name EXCEPTION;
BEGIN
IF condition THEN
RAISE exception_name;
END IF;
EXCEPTION
WHEN exception_name THEN
statement;
END;
You can use the above syntax in raising the Oracle standard exception or any user-defined exception. In the
next section, we will give you an example on raising a user-defined exception. You can raise the Oracle
standard exceptions in a similar way.
User-defined Exceptions
PL/SQL allows you to define your own exceptions according to the need of your program. A user-defined
exception must be declared and then raised explicitly, using either a RAISE statement or the
procedure DBMS_STANDARD.RAISE_APPLICATION_ERROR.
DECLARE
my-exception EXCEPTION;
Example
The following example illustrates the concept. This program asks for a customer ID, when the user enters an
invalid ID, the exception invalid_id is raised.
DECLARE
c_id customers.id%type := &cc_id;
c_name customerS.No.ame%type;
c_addr customers.address%type;
-- user defined exception
ex_invalid_id EXCEPTION;
BEGIN
IF c_id <= 0 THEN
RAISE ex_invalid_id;
ELSE
SELECT name, address INTO c_name, c_addr
FROM customers
WHERE id = c_id;
DBMS_OUTPUT.PUT_LINE ('Name: '|| c_name);
DBMS_OUTPUT.PUT_LINE ('Address: ' || c_addr);
END IF;
EXCEPTION
WHEN ex_invalid_id THEN
dbms_output.put_line('ID must be greater than zero!');
WHEN no_data_found THEN
dbms_output.put_line('No such customer!');
WHEN others THEN
dbms_output.put_line('Error!');
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Pre-defined Exceptions
PL/SQL provides many pre-defined exceptions, which are executed when any database rule is violated by a
program. For example, the predefined exception NO_DATA_FOUND is raised when a SELECT INTO statement
returns no rows. The following table lists few of the important pre-defined exceptions −
Oracle
Exception SQLCODE Description
Error
PL/SQL - Triggers
In this chapter, we will discuss Triggers in PL/SQL. Triggers are stored programs, which are automatically
executed or fired when some events occur. Triggers are, in fact, written to be executed in response to any of
the following events −
Triggers can be defined on the table, view, schema, or database with which the event is associated.
Benefits of Triggers
Triggers can be written for the following purposes −
● Auditing
Creating Triggers
The syntax for creating a trigger is −
Where,
● CREATE [OR REPLACE] TRIGGER trigger_name − Creates or replaces an existing trigger with the trigger_name.
● {BEFORE | AFTER | INSTEAD OF} − This specifies when the trigger will be executed. The INSTEAD OF clause is used
for creating trigger on a view.
● {INSERT [OR] | UPDATE [OR] | DELETE} − This specifies the DML operation.
● [OF col_name] − This specifies the column name that will be updated.
● [ON table_name] − This specifies the name of the table associated with the trigger.
● [REFERENCING OLD AS o NEW AS n] − This allows you to refer new and old values for various DML statements, such
as INSERT, UPDATE, and DELETE.
● [FOR EACH ROW] − This specifies a row-level trigger, i.e., the trigger will be executed for each row being affected.
Otherwise the trigger will execute just once when the SQL statement is executed, which is called a table level trigger.
● WHEN (condition) − This provides a condition for rows for which the trigger would fire. This clause is valid only for
row-level triggers.
Example
To start with, we will be using the CUSTOMERS table we had created and used in the previous chapters −
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
+----+----------+-----+-----------+----------+
The following program creates a row-level trigger for the customers table that would fire for INSERT or
UPDATE or DELETE operations performed on the CUSTOMERS table. This trigger will display the salary
difference between the old values and new values −
When the above code is executed at the SQL prompt, it produces the following result −
Trigger created.
The following points need to be considered here −
● OLD and NEW references are not available for table-level triggers, rather you can use them for record-level triggers.
● If you want to query the table in the same trigger, then you should use the AFTER keyword, because triggers can
query the table or change it again only after the initial changes are applied and the table is back in a consistent state.
● The above trigger has been written in such a way that it will fire before any DELETE or INSERT or UPDATE operation
on the table, but you can write your trigger on a single or multiple operations, for example BEFORE DELETE, which
will fire whenever a record will be deleted using the DELETE operation on the table.
Triggering a Trigger
Let us perform some DML operations on the CUSTOMERS table. Here is one INSERT statement, which will
create a new record in the table −
When a record is created in the CUSTOMERS table, the above create trigger, display_salary_changes will be
fired and it will display the following result −
Old salary:
New salary: 7500
Salary difference:
Because this is a new record, old salary is not available and the above result comes as null. Let us now
perform one more DML operation on the CUSTOMERS table. The UPDATE statement will update an existing
record in the table −
UPDATE customers
SET salary = salary + 500
WHERE id = 2;
When a record is updated in the CUSTOMERS table, the above create trigger, display_salary_changes will be
fired and it will display the following result −
Old salary: 1500
New salary: 2000
Salary difference: 500
PL/SQL - Packages
In this chapter, we will discuss the Packages in PL/SQL. Packages are schema objects that groups logically
related PL/SQL types, variables, and subprograms.
● Package specification
Package Specification
The specification is the interface to the package. It just DECLARES the types, variables, constants, exceptions,
cursors, and subprograms that can be referenced from outside the package. In other words, it contains all
information about the content of the package, but excludes the code for the subprograms.
All objects placed in the specification are called public objects. Any subprogram not in the package
specification but coded in the package body is called a private object.
The following code snippet shows a package specification having a single procedure. You can have many
global variables defined and multiple procedures or functions inside a package.
When the above code is executed at the SQL prompt, it produces the following result −
Package created.
Package Body
The package body has the codes for various methods declared in the package specification and other private
declarations, which are hidden from the code outside the package.
The CREATE PACKAGE BODY Statement is used for creating the package body. The following code snippet
shows the package body declaration for the cust_sal package created above. I assumed that we already have
CUSTOMERS table created in our database as mentioned in the PL/SQL - Variableschapter.
When the above code is executed at the SQL prompt, it produces the following result −
package_name.element_name;
Consider, we already have created the above package in our database schema, the following program uses
the find_sal method of the cust_sal package −
DECLARE
code customers.id%type := &cc_id;
BEGIN
cust_sal.find_sal(code);
END;
/
When the above code is executed at the SQL prompt, it prompts to enter the customer ID and when you
enter an ID, it displays the corresponding salary as follows −
Example
The following program provides a more complete package. We will use the CUSTOMERS table stored in our
database with the following records −
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 3000.00 |
| 2 | Khilan | 25 | Delhi | 3000.00 |
| 3 | kaushik | 23 | Kota | 3000.00 |
| 4 | Chaitali | 25 | Mumbai | 7500.00 |
| 5 | Hardik | 27 | Bhopal | 9500.00 |
| 6 | Komal | 22 | MP | 5500.00 |
+----+----------+-----+-----------+----------+
END c_package;
/
When the above code is executed at the SQL prompt, it creates the above package and displays the following
result −
Package created.
PROCEDURE listCustomer IS
CURSOR c_customers is
SELECT name FROM customers;
TYPE c_list is TABLE OF customerS.No.ame%type;
name_list c_list := c_list();
counter integer :=0;
BEGIN
FOR n IN c_customers LOOP
counter := counter +1;
name_list.extend;
name_list(counter) := n.name;
dbms_output.put_line('Customer(' ||counter|| ')'||name_list(counter));
END LOOP;
END listCustomer;
END c_package;
/
The above example makes use of the nested table. We will discuss the concept of nested table in the next
chapter.
When the above code is executed at the SQL prompt, it produces the following result −
DECLARE
code customers.id%type:= 8;
BEGIN
c_package.addcustomer(7, 'Rajnish', 25, 'Chennai', 3500);
c_package.addcustomer(8, 'Subham', 32, 'Delhi', 7500);
c_package.listcustomer;
c_package.delcustomer(code);
c_package.listcustomer;
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal
Customer(7): Rajnish
Customer(8): Subham
Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal
Customer(7): Rajnish
PL/SQL - Collections
In this chapter, we will discuss the Collections in PL/SQL. A collection is an ordered group of elements having
the same data type. Each element is identified by a unique subscript that represents its position in the
collection.
● Nested table
Starts Either in
dense, can PL/SQL block
Nested table Unbounded Integer Yes
become or at schema
sparse level
We have already discussed varray in the chapter 'PL/SQL arrays'. In this chapter, we will discuss the PL/SQL
tables.
Both types of PL/SQL tables, i.e., the index-by tables and the nested tables have the same structure and their
rows are accessed using the subscript notation. However, these two types of tables differ in one aspect; the
nested tables can be stored in a database column and the index-by tables cannot.
Index-By Table
An index-by table (also called an associative array) is a set of key-value pairs. Each key is unique and is used
to locate the corresponding value. The key can be either an integer or a string.
An index-by table is created using the following syntax. Here, we are creating an index-by table
named table_name, the keys of which will be of the subscript_type and associated values will be of
the element_type
table_name type_name;
Example
Following example shows how to create a table to store integer values along with names and later it prints
the same list of names.
DECLARE
TYPE salary IS TABLE OF NUMBER INDEX BY VARCHAR2(20);
salary_list salary;
name VARCHAR2(20);
BEGIN
-- adding elements to the table
salary_list('Rajnish') := 62000;
salary_list('Minakshi') := 75000;
salary_list('Martin') := 100000;
salary_list('James') := 78000;
When the above code is executed at the SQL prompt, it produces the following result −
Example
Elements of an index-by table could also be a %ROWTYPE of any database table or %TYPE of any database
table field. The following example illustrates the concept. We will use the CUSTOMERS table stored in our
database as −
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
+----+----------+-----+-----------+----------+
DECLARE
CURSOR c_customers is
select name from customers;
When the above code is executed at the SQL prompt, it produces the following result −
Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal
Nested Tables
A nested table is like a one-dimensional array with an arbitrary number of elements. However, a nested table
differs from an array in the following aspects −
● An array has a declared number of elements, but a nested table does not. The size of a nested table can increase
dynamically.
● An array is always dense, i.e., it always has consecutive subscripts. A nested array is dense initially, but it can become
sparse when elements are deleted from it.
table_name type_name;
This declaration is similar to the declaration of an index-by table, but there is no INDEX BY clause.
A nested table can be stored in a database column. It can further be used for simplifying SQL operations
where you join a single-column table with a larger table. An associative array cannot be stored in the
database.
Example
The following examples illustrate the use of nested table −
DECLARE
TYPE names_table IS TABLE OF VARCHAR2(10);
TYPE grades IS TABLE OF INTEGER;
names names_table;
marks grades;
total integer;
BEGIN
names := names_table('Kavita', 'Pritam', 'Ayan', 'Rishav', 'Aziz');
marks:= grades(98, 97, 78, 87, 92);
total := names.count;
dbms_output.put_line('Total '|| total || ' Students');
FOR i IN 1 .. total LOOP
dbms_output.put_line('Student:'||names(i)||', Marks:' || marks(i));
end loop;
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Total 5 Students
Student:Kavita, Marks:98
Student:Pritam, Marks:97
Student:Ayan, Marks:78
Student:Rishav, Marks:87
Student:Aziz, Marks:92
Example
Elements of a nested table can also be a %ROWTYPE of any database table or %TYPE of any database table
field. The following example illustrates the concept. We will use the CUSTOMERS table stored in our database
as −
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
+----+----------+-----+-----------+----------+
DECLARE
CURSOR c_customers is
SELECT name FROM customers;
TYPE c_list IS TABLE of customerS.No.ame%type;
name_list c_list := c_list();
counter integer :=0;
BEGIN
FOR n IN c_customers LOOP
counter := counter +1;
name_list.extend;
name_list(counter) := n.name;
dbms_output.put_line('Customer('||counter||'):'||name_list(counter));
END LOOP;
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal
Collection Methods
PL/SQL provides the built-in collection methods that make collections easier to use. The following table lists
the methods and their purpose −
EXISTS(n)
1
Returns TRUE if the nth element in a collection exists; otherwise returns FALSE.
COUNT
2
Returns the number of elements that a collection currently contains.
LIMIT
3
Checks the maximum size of a collection.
FIRST
4
Returns the first (smallest) index numbers in a collection that uses the integer subscripts.
LAST
5
Returns the last (largest) index numbers in a collection that uses the integer subscripts.
PRIOR(n)
6
Returns the index number that precedes index n in a collection.
NEXT(n)
7
Returns the index number that succeeds index n.
EXTEND
8
Appends one null element to a collection.
EXTEND(n)
9
Appends n null elements to a collection.
EXTEND(n,i)
10
Appends n copies of the ith element to a collection.
TRIM
11
Removes one element from the end of a collection.
TRIM(n)
12
Removes n elements from the end of a collection.
DELETE
13
Removes all elements from a collection, setting COUNT to 0.
DELETE(n)
14 Removes the nth element from an associative array with a numeric key or a nested table. If
the associative array has a string key, the element corresponding to the key value is deleted.
If n is null, DELETE(n) does nothing.
DELETE(m,n)
15
Removes all elements in the range m..n from an associative array or nested table. If m is
larger than n or if m or n is null, DELETE(m,n) does nothing.
Collection Exceptions
The following table provides the collection exceptions and when they are raised −
PL/SQL - Transactions
In this chapter, we will discuss the transactions in PL/SQL. A database transaction is an atomic unit of work
that may consist of one or more related SQL statements. It is called atomic because the database
modifications brought about by the SQL statements that constitute a transaction can collectively be either
committed, i.e., made permanent to the database or rolled back (undone) from the database.
A successfully executed SQL statement and a committed transaction are not same. Even if an SQL statement
is executed successfully, unless the transaction containing the statement is committed, it can be rolled back
and all changes made by the statement(s) can be undone.
● A DDL statement, such as CREATE TABLE statement, is issued; because in that case a COMMIT is automatically
performed.
● A DCL statement, such as a GRANT statement, is issued; because in that case a COMMIT is automatically performed.
● User exits from SQL*PLUS by issuing the EXIT command, a COMMIT is automatically performed.
● A DML statement fails; in that case a ROLLBACK is automatically performed for undoing that DML statement.
Committing a Transaction
A transaction is made permanent by issuing the SQL command COMMIT. The general syntax for the COMMIT
command is −
COMMIT;
For example,
INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (1, 'Ramesh', 32, 'Ahmedabad', 2000.00 );
COMMIT;
ROLLBACK;
Savepoints
Savepoints are sort of markers that help in splitting a long transaction into smaller units by setting some
checkpoints. By setting savepoints within a long transaction, you can roll back to a checkpoint if required. This
is done by issuing the SAVEPOINT command.
UPDATE CUSTOMERS
SET SALARY = SALARY + 1000;
ROLLBACK TO sav1;
UPDATE CUSTOMERS
SET SALARY = SALARY + 1000
WHERE ID = 7;
UPDATE CUSTOMERS
SET SALARY = SALARY + 1000
WHERE ID = 8;
COMMIT;
ROLLBACK TO sav1 − This statement rolls back all the changes up to the point, where you had marked
savepoint sav1.
After that, the new changes that you make will start.
● DATE
● TIMESTAMP
MONTH 01 to 12 0 to 11
HOUR 00 to 23 0 to 23
MINUTE 00 to 59 0 to 59
DATE
It stores date and time information in both character and number datatypes. It is made of information on
century, year, month, date, hour, minute, and second. It is specified as −
TIMESTAMP
It is an extension of the DATE data type. It stores the year, month, and day of the DATE datatype, along with
hour, minute, and second values. It is useful for storing precise time values.
Following table provides the Datetime functions (where, x has the datetime value) −
ADD_MONTHS(x, y);
1
Adds y months to x.
LAST_DAY(x);
2
Returns the last day of the month.
MONTHS_BETWEEN(x, y);
3
Returns the number of months between x and y.
NEXT_DAY(x, day);
4
Returns the datetime of the next day after x.
NEW_TIME;
5
Returns the time/day value from a time zone specified by the user.
ROUND(x [, unit]);
6
Rounds x.
SYSDATE();
7
Returns the current datetime.
TRUNC(x [, unit]);
8
Truncates x.
CURRENT_TIMESTAMP();
1
Returns a TIMESTAMP WITH TIME ZONE containing the current session time along with the
session time zone.
FROM_TZ(x, time_zone);
3
Converts the TIMESTAMP x and the time zone specified by time_zone to a TIMESTAMP WITH
TIMEZONE.
LOCALTIMESTAMP();
4
Returns a TIMESTAMP containing the local time in the session time zone.
SYSTIMESTAMP();
5
Returns a TIMESTAMP WITH TIME ZONE containing the current database time along with the
database time zone.
SYS_EXTRACT_UTC(x);
6
Converts the TIMESTAMP WITH TIMEZONE x to a TIMESTAMP containing the date and time
in UTC.
TO_TIMESTAMP(x, [format]);
7
Converts the string x to a TIMESTAMP.
TO_TIMESTAMP_TZ(x, [format]);
8
Converts the string x to a TIMESTAMP WITH TIMEZONE.
Examples
The following code snippets illustrate the use of the above functions −
Example 1
Output −
08/31/2012 5:25:34 PM
Example 2
Output −
31-08-2012 05:26:14
Example 3
Output −
01/31/2013 5:26:31 PM
Example 4
Output −
8/31/2012 5:26:55.347000 PM
The Interval Data Types and Functions
Following are the Interval data types −
● IINTERVAL YEAR TO MONTH − It stores a period of time using the YEAR and MONTH datetime fields.
● INTERVAL DAY TO SECOND − It stores a period of time in terms of days, hours, minutes, and seconds.
Interval Functions
S.No Function Name & Description
NUMTODSINTERVAL(x, interval_unit);
1
Converts the number x to an INTERVAL DAY TO SECOND.
NUMTOYMINTERVAL(x, interval_unit);
2
Converts the number x to an INTERVAL YEAR TO MONTH.
TO_DSINTERVAL(x);
3
Converts the string x to an INTERVAL DAY TO SECOND.
TO_YMINTERVAL(x);
4
Converts the string x to an INTERVAL YEAR TO MONTH.
Let us look at a small code snippet that will display all the user tables in the database. Try it in your database
to list down all the table names −
BEGIN
dbms_output.put_line (user || ' Tables in the database:');
FOR t IN (SELECT table_name FROM user_tables)
LOOP
dbms_output.put_line(t.table_name);
END LOOP;
END;
/
DBMS_OUTPUT Subprograms
The DBMS_OUTPUT package has the following subprograms −
DBMS_OUTPUT.DISABLE;
1
Disables message output.
DBMS_OUTPUT.NEW_LINE;
5
Puts an end-of-line marker.
DBMS_OUTPUT.PUT(item IN VARCHAR2);
6
Places a partial line in the buffer.
DBMS_OUTPUT.PUT_LINE(item IN VARCHAR2);
7
Places a line in the buffer.
Example
DECLARE
lines dbms_output.chararr;
num_lines number;
BEGIN
-- enable the buffer with default size 20000
dbms_output.enable;
dbms_output.put_line('Hello Reader!');
dbms_output.put_line('Hope you have enjoyed the tutorials!');
dbms_output.put_line('Have a great time exploring pl/sql!');
dbms_output.get_lines(lines, num_lines);
When the above code is executed at the SQL prompt, it produces the following result −
Hello Reader!
Hope you have enjoyed the tutorials!
Have a great time exploring pl/sql!
Objects are created using the CREATE [OR REPLACE] TYPE statement. Following is an example to create a
simple address object consisting of few attributes −
When the above code is executed at the SQL prompt, it produces the following result −
Type created.
Let's create one more object customer where we will wrap attributes and methods together to have
object-oriented feeling −
When the above code is executed at the SQL prompt, it produces the following result −
Type created.
Instantiating an Object
Defining an object type provides a blueprint for the object. To use this object, you need to create instances of
this object. You can access the attributes and methods of the object using the instance name and the access
operator (.) as follows −
DECLARE
residence address;
BEGIN
residence := address('103A', 'M.G.Road', 'Jaipur', 'Rajasthan','201301');
dbms_output.put_line('House No: '|| residence.house_no);
dbms_output.put_line('Street: '|| residence.street);
dbms_output.put_line('City: '|| residence.city);
dbms_output.put_line('State: '|| residence.state);
dbms_output.put_line('Pincode: '|| residence.pincode);
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Member Methods
Member methods are used for manipulating the attributes of the object. You provide the declaration of a
member method while declaring the object type. The object body defines the code for the member methods.
The object body is created using the CREATE TYPE BODY statement.
Constructors are functions that return a new object as its value. Every object has a system defined
constructor method. The name of the constructor is same as the object type. For example −
The comparison methods are used for comparing objects. There are two ways to compare objects −
Map method
The Map method is a function implemented in such a way that its value depends upon the value of the
attributes. For example, for a customer object, if the customer code is same for two customers, both
customers could be the same. So the relationship between these two objects would depend upon the value
of code.
Order method
The Order method implements some internal logic for comparing two objects. For example, for a rectangle
object, a rectangle is bigger than another rectangle if both its sides are bigger.
When the above code is executed at the SQL prompt, it produces the following result −
Type created.
Creating the type body −
When the above code is executed at the SQL prompt, it produces the following result −
DECLARE
r1 rectangle;
r2 rectangle;
r3 rectangle;
inc_factor number := 5;
BEGIN
r1 := rectangle(3, 4);
r2 := rectangle(5, 7);
r3 := r1.enlarge(inc_factor);
r3.display;
IF (r1 > r2) THEN -- calling measure function
r1.display;
ELSE
r2.display;
END IF;
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Length: 8
Width: 9
Length: 5
Width: 7
When the above code is executed at the SQL prompt, it produces the following result −
Type created.
Creating the type body −
When the above code is executed at the SQL prompt, it produces the following result −
When the above code is executed at the SQL prompt, it produces the following result −
Length: 23
Width: 44
Length: 15
Width: 17
Length: 23
Width: 44
The following programs illustrate the inheritance in PL/SQL Objects. Let us create another object
named TableTop, this is inherited from the Rectangle object. For this, we need to create the
base rectangle object −
When the above code is executed at the SQL prompt, it produces the following result −
Type created.
Creating the base type body −
When the above code is executed at the SQL prompt, it produces the following result −
When the above code is executed at the SQL prompt, it produces the following result −
Type created.
Creating the type body for the child object tabletop
When the above code is executed at the SQL prompt, it produces the following result −
DECLARE
t1 tabletop;
t2 tabletop;
BEGIN
t1:= tabletop(20, 10, 'Wood');
t2 := tabletop(50, 30, 'Steel');
t1.display;
t2.display;
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
Length: 20
Width: 10
Material: Wood
Length: 50
Width: 30
Material: Steel
For example,
Type created.