0% found this document useful (0 votes)
14 views

PLSQL P

Plsql prepared notes

Uploaded by

Hussain Akhil
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views

PLSQL P

Plsql prepared notes

Uploaded by

Hussain Akhil
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 98

PL/SQL

PL/SQL stands for procedural language-standard query language. It is a significant member of Oracle programming tool set
which is extensively used to code server side programming. Similar to SQL language PL/SQL is also a case-
insensitive programming language.

1.Blocks
Generally a program written in PL/SQL language is divided into blocks. We can say blocks are basic
programming units in PL/SQL programming language.

PL/SQL Blocks contain set of instructions for oracle to execute, display information to the screen, write data to
file, call other programs, manipulate data and many more.

Does Blocks supports DDL statements?


Yes, PL/SQL blocks support all DML statements and using Native Dynamic SQL (NDS) or they can run DDL
statements using the build in DBMS_SQL package.

Types of PL/SQL Blocks


There are two types of blocks in PL/SQL

1. Anonymous Block
2. Named Block

Anonymous Block
As the title suggests these anonymous blocks do not have any names as a result they cannot be stored in
database and referenced later.

Named Block
On the other hand Named PL/SQL blocks are the one that have names and are used when creating subroutines
such as procedures, functions and packages. These subroutines then can be stored in the database and
referenced by their name later.

Both type of PL/SQL blocks are further divided into 3 different sections which are:

1. The Declaration Section


2. The Execution Section and
3. The Exception-handling Section
The Execution Section is the only mandatory section of block whereas Declaration and Exception Handling
sections are optional.
Basic prototype of Anonymous PL/SQL Block
DECLARE
Declaration Statements
BEGIN
Executable statements
Exception
Exception handling statements
END;

Declaration Section
This is the first section of PL/SQL block which contains definition of PL/SQL identifiers such as variables,
Constants, cursors and so on. You can say this is the place where all local variables used in the program are
defined and documented.

DECLARE
Var_first_name VARCHAR2(30);
Var_last_name VARCHAR2(30);
Con_flag CONSTANT NUMBER:=0;

The above example shows declaration section of an anonymous block. It begins with keyword declare and
contains two variables var_first_name and var_last_name and one constant con_flag. Notice that semicolon
terminates each declaration.

Execution Section
This section contains executable statements that allow you to manipulate the variables that have been declared
in the declaration section. The content of this section must be complete to allow the block to compile. By
complete I mean complete set of instruction for the PL/SQL engine must be between BEGIN and END
keyword.

The execution Section of any PL/SQL block always begins with the Keyword BEGIN and ends with the
Keyword END.

This is the only mandatory section in PL/SQL block. This section supports all DML commands and
SQL*PLUS built-in functions and using Native Dynamic SQL (NDS) or using DMBS_SQL built-in package it
also supports DDL commands.

BEGIN
SELECT first_name, last_name INTO var_first_name,
var_last_name
FROM employees WHERE employee_id =100;
DBMS_OUTPUT.PUT_LINE
(‘Employee Name ’||var_first_name||’ ‘||var_last_name);
END;

This is very simple program where I fetched the value of first name and last name column from employees
table where employee id is 100 and stored it into the variable var_first_name and var_last_name which we
declared in our first example.

Exception-Handling Section
This is the last section of PL/SQL block which is optional like the declaration block. This section contains
statements that are executed when a runtime error occurs within the block.

Runtime error occurs while the program is running and cannot be detected by the PL/SQL compiler. When a
runtime error occurs, controlled is pass to the exception handling section of the block the error is evaluated and
specific exception is raised.

EXCEPTION
WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE (‘No Employee Found with ’||
employee_id);

Example : 1

CREATE BELOW TABLE FOR PRACTICE

CREATE TABLE employees(

employee_id NUMBER,

first_name VARCHAR2(30),

last_name VARCHAR2(30));

SELECT * FROM EMPLOYEES;

INSERT INTO EMPLOYEES VALUES (100,'MAHAMMAD','HUSSAIN');

INSERT INTO EMPLOYEES VALUES (200,'MAHAMMAD','SHAFI');

INSERT INTO EMPLOYEES VALUES (300,'IMAM','HUSSAIN');

PL/SQL SIMPLE BLOCK

SET SERVEROUTPUT ON;


DECLARE
Var_first_name VARCHAR2(30);
Var_last_name VARCHAR2(30);
Var_employee_id NUMBER;
BEGIN
SELECT first_name, last_name ,employee_id
INTO Var_first_name, Var_last_name , Var_employee_id
FROM employees
WHERE employee_id = 100;
DBMS_OUTPUT.PUT_LINE('Full Name: ' || Var_first_name || ' ' || Var_last_name ||' '|| ' AND EMPLOYEE ID IS
' || var_employee_id);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No Employee Found with givem Employee ID' );
END;

Full Name: MAHAMMAD HUSSAIN AND EMPLOYEE ID IS 100


PL/SQL procedure successfully completed.

SET SERVEROUTPUT ON;


DECLARE
Var_first_name VARCHAR2(30);
Var_last_name VARCHAR2(30);
Var_employee_id NUMBER;
BEGIN
SELECT first_name, last_name ,employee_id
INTO Var_first_name, Var_last_name , Var_employee_id
FROM employees
WHERE employee_id = 400;
DBMS_OUTPUT.PUT_LINE('Full Name: ' || Var_first_name || ' ' || Var_last_name ||' '|| ' AND EMPLOYEE ID IS
' || var_employee_id);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No Employee Found with givem Employee ID' );
END;

No Employee Found with givem Employee ID


PL/SQL procedure successfully completed.

2.Variables Declaration Initialization In PL/SQL


Variables are place holders in the computer’s main memory which hold some data. Every variable has a name
which is user defined, also a data type that defines the nature of data a variable can hold and the total amount of
space they can have in main memory along with some value. Like every other programming language in
PL/SQL also we first need to declare a variable before using it.

Variable Declaration
All the variable declaration must be done in Declare Section of the PL/SQL block. As soon as you declare a
variable, the compiler will allocate the memory according to the data type to that variable. Though you can
assign value to the variable either in declare section or in execution section of your PL/SQL block but
the declaration must be done in declare section.

Here is a simple program to understand this.

SET SERVEROUTPUT ON;


DECLARE
Test_var1 NUMBER; — Declaring variable Test_var
BEGIN
Test_var1:= 10;
DBMS_OUTPUT.PUT_LINE (Test_var1);
END;

10
PL/SQL procedure successfully completed.

This is a very simple program in which I first declared a variable by the name of test_var1 which has data
type number in declaration section and later in execution section I initialized it and assigned a numeric value 10
and then using DBMS_OUTPUT statement I displayed the value of this variable.

Assignment Operator (:=)


If you have noticed in the above program that unlike conventional assignment operators in other programming
language which is Equal to (=) operator, here we used colon ( : ) with equal to (=) operator for assigning the
value to the variable.

Yes in PL/SQL the combo of colon and equal to operator (:=) works as assignment operator which is very
different from the other programming languages.

Note: There is no space between colon and equal to operator.

Variable Initialization
1. Where can we initialize the variables:-

Though it’s mandatory to declare all the variables of your programs in declaration section of your PL/SQL
block but initializing them and assigning them some value in execution section is not mandatory.

You can initialize a variable in declaration section while creating it or you can initialize the variable in
execution section

2. Different ways of initializing variables in PL/SQL program:-

Variable initialization means assigning some value to the variable which you previously declared. There are
two ways of assigning value to the variable.

First is the direct way of giving value to the variable or assigning value in declaration section(above
example)

DECLARE
var_test1 VARCHAR2(30) := ‘hussain mahammad’; --Declare & initialize the variable at same time
BEGIN
DBMS_OUTPUT.PUT_LINE(var_test1);
END;

hussain mahammad
PL/SQL procedure successfully completed.

Second way is by fetching value from the column of a row of a table and assigning that value to the
variable.

SET SERVEROUTPUT ON;


DECLARE
Var_first_name VARCHAR2(30);
Var_last_name VARCHAR2(30);
Var_employee_id NUMBER;
BEGIN
SELECT first_name, last_name ,employee_id
INTO Var_first_name, Var_last_name , Var_employee_id
FROM employees
WHERE employee_id = 100;
DBMS_OUTPUT.PUT_LINE('Full Name: ' || Var_first_name || ' ' || Var_last_name ||' '|| ' --AND
EMPLOYEE ID IS ' || var_employee_id);
end;

Full Name: MAHAMMAD HUSSAIN AND EMPLOYEE ID IS 100


PL/SQL procedure successfully completed.
3.SELECT INTO Statement In PL/SQL
The SELECT INTO statement retrieves data from one or more database tables, and assigns the selected values to
variables or collections.

Syntax
SELECT column1, column2…. Column n INTO variable1, variable2… Variable n FROM table_name
WHERE <expression>;

DECLARE
v_salary NUMBER(8);

every variable must be declared prior to its use and we can only declare a variable in declaration section of
PL/SQL block. In the above demonstration I declared a variable by the name of v_salary which has data type
NUMBER and Data width 8.

One thing must take care while declaring variable here is that the data type and data width of your variable and
the column whose value you want to fetch must match.

BEGIN
SELECT salary INTO v_salary FROM employees
WHERE employee_id = 100;
DBMS_OUTPUT.PUT_LINE (v_salary);
END;

This is the execution section of our anonymous block. This section contains our select statement. This select
statement is retrieving salary of the employee whose employee id is 100 from employees table and storing it
into the variable v_salary.

The variable v_salary which we declare above in the declaration section is capable of holding single data at a
time thus make sure your select statement must return only single data. This you can ensure by using WHERE
clause of your SELECT statement as I did in this example.

Let’s put all the parts together and see the complete anonymous block.

SET SERVEROUTPUT ON;


DECLARE
v_salary NUMBER(8);
BEGIN
SELECT salary INTO v_salary FROM employees
WHERE employee_id = 100;
DBMS_OUTPUT.PUT_LINE (v_salary);
END;

24000
PL/SQL procedure successfully completed.

Fetch data from multiple column and store it into multiple variables

SET SERVEROUTPUT ON;


DECLARE
v_salary NUMBER(8);
v_fname VARCHAR2 (20);
BEGIN
SELECT first_name, salary INTO v_fname, v_salary FROM employees
WHERE employee_id =100;
DBMS_OUTPUT.PUT_LINE(v_fname||'has salary '||v_salary);
END;
Stevenhas salary 24000
PL/SQL procedure successfully completed.

Exception-Handling Section:-
This is the last section of PL/SQL block which is optional like the declaration block. This section contains
statements that are executed when a runtime error occurs within the block.

Runtime error occurs while the program is running and cannot be detected by the PL/SQL compiler. When a
runtime error occurs, controlled is pass to the exception handling section of the block the error is evaluated and
specific exception is raised.

We can add below exception if the given employee id is not present in the table then it will execute below
statement

EXCEPTION
WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE ('No Employee Found with given
employee id');
end;

No Employee Found with given employee id


PL/SQL procedure successfully completed.

4.ANCHORED Datatype In PL/SQL


Anchored data types are those data type which you assign to a variable based on a database object. They are
called anchored data type because unlike the variable data type it is not dependent on that of any underlying
object.

Syntax
variable_name typed-attribute%type

typed-attribute = tablename.columnname

Where variable name is user defined name given to a variable and type attribute can be anything such as
previously declared PL/SQL variable or column of a table. And at the end %type is the direct reference to the
underlying database object.

How to Declare a variable with Anchored Datatype


Now we will write an anonymous block where we will declare a variable with anchored data type and then
initialize that variable by fetching value from EMPLOYEES table.

SET SERVEROUTPUT ON;


DECLARE
V1 EMPLOYEES.FIRST_NAME%TYPE;
V2 EMPLOYEES.LAST_NAME%TYPE;
BEGIN
SELECT first_name, last_name INTO V1,V2
FROM employees WHERE EMPLOYEE_ID = 100;
DBMS_OUTPUT.PUT_LINE('Full Name: ' || V1 || ' ' || V2);
END;

Full Name: MAHAMMAD HUSSAIN


PL/SQL procedure successfully completed.

NEED OF ANCHORED DATA TYPE :- if we declare a variable with particular data type and size based on
the column that we are going to initialize the value like below example

SET SERVEROUTPUT ON;


DECLARE
Var_first_name VARCHAR2(30);
Var_last_name VARCHAR2(30);
Var_employee_id NUMBER;
BEGIN
SELECT first_name, last_name ,employee_id
INTO Var_first_name, Var_last_name , Var_employee_id
FROM employees
WHERE employee_id = 100;
DBMS_OUTPUT.PUT_LINE('Full Name: ' || Var_first_name || ' ' || Var_last_name ||' '|| ' --AND
EMPLOYEE ID IS ' || var_employee_id);
end;

suppose in future some one has changed the column definition to varchar(40) then we will get error because our
variable data type and column data types will be different. To overcome this issue we will use anchored data
type

5.Constants In PL/SQL:-
Like several other programming languages, the constant in PL/SQL is also a user defined identifier whose
value remains unchanged throughout the program. Like variables in PL/SQL constants also need to be
declared prior to their use. Furthermore you can only declare them in the declaration section of your PL/SQL
block.

Syntax
constant_name CONSTANT datatype (data-width) := value;

First you need to give a valid name to your constant followed by keyword CONSTANT that indicates the
declaration of a constant in your program. Then you have to specify the data type and data width for your
constant followed by the assignment operator and the value which you want to assign to your constant.

Note:-
You must initialize a constant at its declaration. You have to initialize your constant at the time of its creation
in declaration section of your PL/SQL block. You cannot initialize it anywhere else.

Example

SET SERVEROUTPUT ON;


DECLARE
PI CONSTANT NUMBER(7,6) := 3.1415926;
BEGIN
DBMS_OUTPUT.PUT_LINE(PI);
END;
/
3.141593
PL/SQL procedure successfully completed.

This is a simple example of Constant declaration and initialization. Here in declaration section I have declared
a constant v_pi and initialized it with the approximate value of pi. In the execution section we have our DBMS
output statement which is displaying the value stored into our constant.

This is the proper way of declaring and initializing a constant in PL/SQL. We have two more attributes of
PL/SQL constants to discuss which are “DEFAULT” and “NOT NULL”.

DEFAULT
You can use default keyword instead of assignment operator to initialize the constant in PL/SQL. Let’s do an
example and see how to initialize a constant using DEFAULT keyword.

SET SERVEROUTPUT ON;


DECLARE
PI CONSTANT NUMBER(7,6) DEFAULT 3.1415926;
BEGIN
DBMS_OUTPUT.PUT_LINE(PI);
END;
/

3.141593
PL/SQL procedure successfully completed.

Same code just this time I used keyword DEFAULT instead of assignment operator for initializing the constant

NOT NULL
Next attribute is NOT NULL. Using this attribute you can impose NOT NULL constraint while declaring
constants as well as variables. This will prevent you from assigning NULL values to your constants or
variables.

To impose not null constraint simply write NOT NULL keyword before the Keyword default or before
assignment operator in case you have used it.

SET SERVEROUTPUT ON;


DECLARE
PI CONSTANT NUMBER(7,6) NOT NULL DEFAULT 3.1415926;
BEGIN
DBMS_OUTPUT.PUT_LINE(PI);
END;

3.141593
PL/SQL procedure successfully completed.

NOTE:-
In PL/SQL, you cannot explicitly declare variables as NOT NULL like you can with table columns in SQL.
Variables in PL/SQL are always nullable by default, and there is no direct syntax to enforce the NOT NULL
constraint on variables.

6.Bind Variables In PL/SQL


There are two types of variables in Oracle database.

1. User variables. Discussed in Section 2


2. Bind variables a.k.a Host variables.

Unlike user variables which can only be declared inside the declaration section of PL/SQL block you can
declare bind variable anywhere in the host environment and that is the reason why we also refer bind variables
as host variable.
[In PL/SQL, bind variables are used to improve the performance, security, and maintainability of SQL statements,
especially when executing them multiple times. Instead of embedding literal values directly in the SQL statement,
bind variables are used to hold the values separately.]

How To Declare a Bind Variable (Variable command)


Let’s see how to create or say declare a bind variable. We can declare a bind variable using VARIABLE
command. Variable command declares the bind variable which we can refer in PL/SQL. Also as I said earlier
in this tutorial that in order to declare bind variables we do not need to write any PL/SQL block or section.

VARIABLE v_bind1 VARCHAR2 (10);

See how easy it is to declare a bind variable in oracle database! You simply have to write a command which starts
with keyword VARIABLE followed by the name of your bind variable which is completely user defined along with
the data type and data width. That’s how we declare a bind variable in Oracle database.

Did you notice that I didn’t write any PL/SQL block or section here to declare this bind variable which is very
unlike the user variable.

Other Uses of Variable Command.

Declaring the bind variable is the first use of this variable command there are few other uses of it also. Let’s see
what those are

 List all the bind variables declared in the session.


Yes using Variable command you can display the list of all the bind variables you have declared in the session. To
display the list of all the bind variables you simply have to write the keyword variable and execute. Doing so will
return list of all the bind variables.

VARIABLE;

Execute the above command and that will show you the list of all the bind variables that you have declared in your
session.

 See the definition of bind variable.


Variable command can also show you the definition of any bind variable created in the session. By definition I mean
the data type and data width of the variable. To see the definition of the bind variable you have to write the keyword
VARIABLE followed by the name of the bind variable in question.

Let’s do an example and see the definition of this bind variable v_Bind2.

Variable v_bind2;
Execution of above command will show you the definition of bind variable RebellionRider.

Initialize the Bind Variable


As we have now declared the bind variable next we have to initialize it. We have several different ways of
initializing the bind variable.

 You can initialize the bind variable using “Execute” command.


Execute command is like a wrapper which works as an execution section of PL/SQL block. Let’s see how it works.
Let’s initialize our bind variable v_bind1 with a string RebellionRider.

Exec :v_bind1 := ‘Rebellion Rider’; ( IT WILL NOT WORK IN SOME EDITIORS)

This statement starts with keyword Exec which is the starting 4 alphabets of Keyword Execute. You can either
write whole keyword Execute or just the starting 4 alphabets “Exec” both will work fine. This is followed by the
name of our bind variable which is v_bind1. After that we have assignment operator followed by the string
Rebellion Rider, as it’s a string thus it’s enclosed in single quotes.

 Initialize the bind variable by explicitly writing execution section of


PL/SQL block.
If you do not like shortcuts and are willing to do some hard work of writing a few extra lines of code then this is for
you.

SET SERVEROUTPUT ON;


BEGIN
:v_bind1 := ‘hussain mahammad’;
END;
/

This is a simple execution block where I initialized the bind variable v_bind1 with the string Manish Sharma.
That is how we initialize the bind variable in Oracle Database or in PL/SQL.

Referencing the Bind Variable


In above example we can see that WE put the colon sign (:) before the name of bind variable (:v_bind1) while
initializing it. Unlike user variables which you can access simply by writing their name in your code, you use colon
before the name of bind variable to access them or in other words you can reference bind variable in PL/SQL by
using a colon (:) followed immediately by the name of the variable as I did in the previous section.

Display The Bind variable.


There are 3 ways of displaying the value held by bind variable in PL/SQL or say in Oracle Database.

1. Using DBMS OUTPUT package.


2. Using Print command
3. Setting Auto print parameter on
 Using DBMS_OUTPUT Package
This is the simplest way of displaying the value held by any variable in PL/SQL. To display the value held by your
bind variable you simply have to pass the name of your bind variable as a parameter to the PUT_LINE procedure of
DBMS_OUTPUT package. Let’s see an example

BEGIN
:v_bind1 := ‘RebellionRider’;
DBMS_OUTPUT.PUT_LINE(:v_bind1);
END;
/

Things you must take care of here are:

1. PUT_LINE is an executable statement which will require the execution section of PL/SQL block for its execution.
In simple words you can only execute this statement in execution section of PL/SQL block otherwise you will get an
error.
2. To see the output returned from this statement you have set the serveroutput on. You can do that by simply writing
and executing

SET SERVEROUTPUT ON;

 Using PRINT command


Like DBMS_OUTPUT statement print command also displays the current value of the bind variable except that you
can write this command in host environment rather than inside any PL/SQL block or section. Yes similar to variable
command, print command does not require any PL/SQL block for execution.

Suppose you want to see the current value of bind variable v_bind1 for that simply write the print command in your
SQL*PLUS

Print :v_bind1;
Or
Print v_bind1;

Writing keyword PRINT without any argument will display you the current values of all the bind variables with
their names in the session.

 Setting Auto print parameter on


The last way of displaying the current value of a bind variable is by setting a session based parameter AUTOPRINT
on. Doing so will display you the value of all the bind variables without the use of any specific commands such as
Print or DBMS_OUTPUT which we just saw.

To set this parameter you simply have to write

SET AUTOPRINT ON;

[SET AUTOPRINT ON;


VARIABLE V_BIND3 VARCHAR2(20);
BEGIN
:v_bind3 := 'HUSSAIN MAHAMMAD';
END;]

And this command will set AutoPrint parameter on for the session which will automatically print the values of bind
variable.
[ NORMAL VARIABLES NEED TO BE DECLARE INSIDE DECLARATION SECTION SECTION ONLY,
COMING TO BIND VARIABLE WE CAN DECLARE OUT SIDE OF PL/SQL BLCOK ALSO]

7.Conditional Control Statements In PL/SQL


Conditional control statements are those which allow you to control the execution flow of the program depending on
a condition. In other words the statements in the program are not necessarily executed in a sequence rather one or
other group of statements are executed depending on the evaluation of a condition.

Types Of Conditional Control Statement in PL/SQL


In Oracle PL/SQL we have two types of conditional control statements which are

1. IF statements and
2. CASE statements

Both these statements can be further divided into different forms.

IF statements has 3 different forms

1. IF THEN
2. IF THEN ELSE
3. IF THEN ELSEIF
CASE statement has 2 different forms such as

1. SIMPLE CASE and


2. SEARCHED CASE
8.IF-THEN Conditional Control Statements In PL/SQL
IF-THEN is the most basic kind of conditional statements in PL/SQL that enables you to specify only a single
group of action to be taken. You can also say that this specific group of action is taken only when a condition is
evaluated to be true.

IF-THEN Structure

IF condition THEN
Statement1;

Statement N;
END IF;

In the starting we have the keyword IF which marks the beginning of IF-THEN block followed by a valid
condition or a valid expression which will get evaluated followed by another keyword THEN. Similarly the
reserved phrase END IF marks the ending of IF-THEN block. In between we have a sequence of executable
statements which will get executed only if the condition evaluated to be true otherwise the whole IF-THEN
block will be skipped.

Working
When an IF-THEN statement is executed a condition is evaluated to either True or False. If the condition
evaluates to true, control is passed to the first executable statement of the IF-THEN construct. If the condition
evaluates to false, control is passed to the first executable statement after the END-IF statement.

Examples:
SET SERVEROUTPUT ON;
DECLARE
v_num NUMBER := 9;
BEGIN
IF v_num < 10 THEN
DBMS_OUTPUT.PUT_LINE(‘Inside The IF’);
END IF;
DBMS_OUTPUT.PUT_LINE(‘outside The IF’);
END;
/

Inside The IF
outside The IF

PL/SQL procedure successfully completed.

This is a very simple PL/SQL anonymous block. In the declaration section I have declared a variable v_num with
data type NUMBER and initialized it with integer 9. Let’s come to our execution section. Here as you can see we
have 2 DBMS_OUTPUT statements one is inside the IF-THEN block and another is outside it. The first
DBMS_OUTPUT statement will execute only if the condition of our IF-THEN block is evaluated as true otherwise
it will be skipped but the 2nd DBMS_OUTPUT statement which is outside the IF-THEN block will execute every
time you execute this PL/SQL block.
This means that if the condition is true then both the string INSDIE THE IF and OUTSIDE THE IF will be printed
otherwise only OUTSIDE THE IF will be printed
SET SERVEROUTPUT ON;

DECLARE
V1 VARCHAR(30):= 'MAHAMMAD HUSSAIN';
V2 VARCHAR2(30):= 'WORKS AT TCS';
BEGIN
IF V1 = 'MAHAMMAD HUSSAIN' AND V2 = 'WORKS AT TCS' THEN
DBMS_OUTPUT.PUT_LINE('Everything is Awesome');
END IF;
DBMS_OUTPUT.PUT_LINE('OUT SIDE IF THEN CLAUSE');
END;
/

Everything is Awesome
OUT SIDE IF THEN CLAUSE

PL/SQL procedure successfully completed.

This one is slightly different than the previous example. Here we used logical AND operator in the condition. If this
condition is evaluated to be true then both strings from both DBMS_OUTPUT statements will be printed otherwise
only the string from 2nd DBMS_OUTPUT statement will be displayed back to you.
This example is for showing how you can check multiple conditions in a single go using logical operator. You can
even use logical OR instead of logical AND operator.

9.IF-THEN-ELSE Conditional Control Statement In


PL/SQL
In previous section we saw that that a simple IF-THEN statement enables us to specify the sequence of statements to
be executed only if the condition is evaluated to be true. In case this condition is evaluated to be false then no special
action is to be taken except to proceed with execution of the program.

To overcome this drawback in oracle PL/SQL we have IF-THEN-ELSE statement widely pronounced as IF-ELSE
statement.

With IF-THEN-ELSE in PL/SQL we have two groups of executable statements, one which gets executed if the
condition is evaluated to be true and another group gets executed if the condition is evaluated to be false. Once the
IF-THEN-ELSE construct gets completed the next statement right after IF-THEN-ELSE block is executed.
Syntax
IF condition THEN
Statement 1;
ELSE
Statement 2;
END IF;
Statement 3

In the syntax we can see that IF-THEN-ELSE construct starts with the keyword IF and ends with the reserved phrase
END IF. Followed by IF keyword we have to specify a valid condition which will get evaluated. If this condition is
evaluated to be TRUE then control is passed to the statement 1, and if this condition is evaluated to be false then
control will jump over to statement 2. Once the construct is completed then statement 3 is executed.

Example
Here in this example we will take a numeric input from the user and will check whether a user has entered an even
number or an odd number using IF THEN ELSE statement. This is going to be a very easy example.

'&'
The '&' symbol is used as a substitution variable in PL/SQL. It is mainly used for accepting user input during
runtime. When you use '&' followed by a variable name, PL/SQL prompts the user to enter a value for that
variable when the code is executed. It allows users to provide dynamic input to a program, making it more
interactive

v_NUMBER NUMBER := &PLEASE_ENTER_A_NUMBER;

‘MOD’
In PL/SQL, 'mod' is an arithmetic operator used for performing the modulo operation. The syntax is as
follows:

result := number1 mod number2;


or
result :=MOD(V_NUMBER,2)

SET SERVEROUTPUT ON;


DECLARE
v_NUMBER NUMBER := &PLEASE_ENTER_A_NUMBER;
BEGIN
IF MOD(V_NUMBER,2)=0 THEN
DBMS_OUTPUT.PUT_LINE(V_NUMBER||' IS A EVEN NUMBER ');
ELSE
DBMS_OUTPUT.PUT_LINE(V_NUMBER||' IS A ODD NUMBER ');
END IF;
DBMS_OUTPUT.PUT_LINE (' IF THEN ELSE Construct complete ');
END;
/

Output when input number is 4


4 IS A EVEN NUMBER
IF THEN ELSE Construct complete
PL/SQL procedure successfully completed.

Output when input number is 5

5 IS A ODD NUMBER
IF THEN ELSE Construct complete
PL/SQL procedure successfully completed.

10.IF-THEN-ELSIF Conditional Control Statement In


PL/SQL
In the previous section we saw that IF ELSE condition gives us the provision of executing statements not only when
the condition is evaluated to be true but also when the condition is evaluated to be false. But using IF ELSE
statement we can only check one condition at a time, there is no provision for checking multiple conditions. This
becomes its major drawback.

To overcome this we have IF THEN ELSIF condition in Oracle PL/SQL. Using this statement you can check
multiple conditions

Syntax
IF CONDITION 1 THEN
STATEMENT 1;
ELSIF CONDITION 2 THEN
STATEMENT 2;
ELSIF CONDITION 3 THEN
STATEMENT 3;

ELSE
STATEMENT N; END IF;

Example
SET SERVEROUTPUT ON;
DECLARE
V_MARKS NUMBER := &PLEASE_ENTER_YOUR_MARKS;
V_GRADE VARCHAR2(30);
BEGIN
IF V_MARKS >=91 THEN
V_GRADE := 'A';
ELSIF V_MARKS >=81 THEN
V_GRADE := 'B';
ELSIF V_MARKS >=71 THEN
V_GRADE := 'C';
ELSIF V_MARKS >=61 THEN
V_GRADE := 'D';
ELSIF V_MARKS >=51 THEN
V_GRADE := 'E';
ELSIF V_MARKS >=35 THEN
V_GRADE := 'F';

ELSE V_GRADE := 'FAIL';

END IF;
DBMS_OUTPUT.PUT_LINE('Your grade is: ' || v_GRADE);
END;
/

Output when given input V_MARKS are 92

Your grade is: A


PL/SQL procedure successfully completed.

Output when given input V_MARKS are 59

Your grade is: E


PL/SQL procedure successfully completed.

Output when given input V_MARKS are 32

Your grade is: FAIL


PL/SQL procedure successfully completed.

Simple Case Expression In Oracle Database


Using Case expression you can achieve the IF-THEN-ELSE logic in Oracle SQL that too without invoking
any kind of SQL procedures.

CASE expression can do all the work of a DECODE expression. Several books recommend using CASE
over DECODE because

 CASE expressions are easier to read in comparison to DECODE expression and


 CASE expression is ANSI-compliant and forms part of the SQL/92 standard.
In Oracle there are two types of CASE expressions

 Simple case expressions


 Searched case expressions
Simple Case Expression

As the name suggests it is the simplest version of CASE expression in other words we can say that it is a
flexible and easiest version of DECODE expression.

The syntax of “Simple Case Expression” is

CASE expression
WHEN value1 THEN result1
WHEN value2 THEN result2
...
ELSE default_result
END
Where

The case expression evaluates the given expression and checks it against each WHEN clause in order. When
a match is found, it returns the corresponding result. If no match is found, it returns the default_result
(optional).

The Simple Case Expression uses search expression to determine the return value. Means simple case
expression evaluates all the input expressions against the search expression. Once a match is found the
corresponding result is returned otherwise Else result is displayed. Furthermore the Else statement is
optional so in case you omit it then Null is displayed when the simple case expression cannot find a match.

Points to remember

 The data type of all the input expressions must match with the data type of search expression.
Means data type of search expression and input expression must be the same.
 The datatype of all the output results must match with Else result means the data type of output
result along with else result must be the same.

The maximum number of arguments in a CASE expression is 255. All expressions count toward this limit,
including the initial expression of a simple CASE expression and the optional ELSE expression. Each
WHEN … THEN pair counts as two arguments. To avoid exceeding this limit, you can nest CASE
expressions so that the output_result itself is a CASE expression.

Example:
Suppose we have a table "employees" with the columns "employee_id," "first_name," and "salary." We
want to categorize employees based on their salary ranges. We can use a simple case expression to achieve
this:
SELECT
employee_id,
first_name,
salary,
CASE
WHEN salary >= 15000 THEN 'high Earner'
WHEN salary >= 10000 THEN 'Medium Earner'
ELSE 'Low Earner'
END AS salary_category
FROM employees where employee_id between 100 and 150;

Searched Case Expression In Oracle Database


In Oracle Database, a searched case expression is a conditional expression that allows you to evaluate
multiple conditions and return different results based on those conditions. It differs from the simple case
expression in that it does not rely on a single expression to compare against specific values. Instead, each
condition is specified individually using boolean expressions, and the first matching condition's result is
returned.

The syntax for a searched case expression is as follows:

CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
...
ELSE default_result
END
Here:

condition1, condition2, etc.: These are boolean expressions that are evaluated to true or false.
result1, result2, etc.: These are the values returned when the corresponding condition is true.
default_result (optional): If none of the conditions are true, this value is returned.
Example:
Let's consider a table "employees" with columns "employee_id," "first_name," and "salary." We want to
categorize employees based on their salary ranges into three categories: "High Earner," "Medium Earner,"
and "Low Earner."

SELECT
employee_id,
first_name,
salary,
CASE
WHEN salary >= 100000 THEN 'High Earner'
WHEN salary >= 50000 THEN 'Medium Earner'
ELSE 'Low Earner'
END AS salary_category
FROM employees;

In this example, we use a searched case expression to categorize employees based on their salary. If the
salary is greater than or equal to 100,000, the employee is labeled as "High Earner." If the salary is greater
than or equal to 50,000, the employee is labeled as "Medium Earner." If the salary is below 50,000, the
employee is labeled as "Low Earner."

The output of this query will include the employee details along with the computed "salary_category"
column indicating their respective salary category based on the searched case expression.

Searched case expressions are very flexible as they allow you to specify complex conditions, making them
suitable for various scenarios where you need to evaluate multiple condition

11.What Are Loops & Simple Loops In PL/SQL


Iterative statements famously known as Loops in Programming language. It executes block of statements or a part of
a program several times.

Types of Loops in Oracle PL/SQL


There are 4 types of Loops in Oracle PL/SQL

Simple Loop
While Loop
Numeric For Loop and
Cursor For loop

Simple Loop
Simple loop is the most basic loop in Oracle PL/SQL

Syntax
LOOP
Statement 1;
Statement 2;

Statement 3;
END LOOP;

Here keyword LOOP marks the beginning and phrase END LOOP marks the ending of the loop. In between we
have a sequence of executable statements.
As you can see in this syntax that unlike conventional loops here we do not have update statements or for that matter
exist conditions which will terminate the loop. May be that is why we call this a simple loop.

In Above syntax as you can see we do not have any exit statement to terminate the loop. This means that if we
execute this program then the execution will keep on printing till we halt it manually.

In this case Oracle PL/SQL gives us two clauses to terminate the loop

1. Exit
2. Exit When

1. Exit
Exit clause will terminate the loop when Exit condition is evaluated to be true. The exit condition is evaluated with
the help of Simple IF THEN condition which we discussed in PL/SQL section 8

SET SERVEROUTPUT ON;


DECLARE
V_NUMBER NUMBER :=0;
V_RESULT NUMBER;
BEGIN
LOOP
V_NUMBER :=V_NUMBER +1;
V_RESULT :=19*V_NUMBER;
DBMS_OUTPUT.PUT_LINE('19'||' x '||V_NUMBER||' = '|| V_RESULT);
IF V_NUMBER >= 10 THEN
EXIT;
END IF;
END LOOP;
END;
/

19 x 1 = 19
19 x 2 = 38
19 x 3 = 57
19 x 4 = 76
19 x 5 = 95
19 x 6 = 114
19 x 7 = 133
19 x 8 = 152
19 x 9 = 171
19 x 10 = 190

PL/SQL procedure successfully completed.

You simply have to add this IF THEN block either right above the phrase END LOOP or immediately below the
keyword loop. What this IF THEN block will do? This block will keep an eye on your counter and will tell the
control to exit the loop when counter either becomes greater than or equal to 10. Which means loop will execute for
10 times.

2. EXIT WHEN

Second way of terminating the loop is by using EXIT WHEN clause. Using this clause you can replace this whole IF
THEN block with a simple single statement.

EXIT WHEN CONDITION;


SET SERVEROUTPUT ON;
DECLARE
V_NUMBER NUMBER :=0;
V_RESULT NUMBER;
BEGIN
LOOP
V_NUMBER :=V_NUMBER +1;
V_RESULT :=19*V_NUMBER;
DBMS_OUTPUT.PUT_LINE('19'||' x '||V_NUMBER||' = '|| V_RESULT);
EXIT WHEN V_NUMBER =10;
END LOOP;
END;
/

19 x 1 = 19
19 x 2 = 38
19 x 3 = 57
19 x 4 = 76
19 x 5 = 95
19 x 6 = 114
19 x 7 = 133
19 x 8 = 152
19 x 9 = 171
19 x 10 = 190

PL/SQL procedure successfully completed.

12.WHILE Loop In PL/SQL


It also executes block of statements several times but this loop is best usable when number of iterations to be
performed are unknown.

Syntax
WHILE condition LOOP
Statement 1;
Statement 2;

Statement 3;
END LOOP;

The keyword WHILE marks the beginning of the loop followed by word CONDITION which will serve your test
condition. This will get evaluated either to be true or to be false and at the end of our first line we have another
keyword which is LOOP. The statements 1 through N are sequence of executable statements which define the body
of the loop. And at the end we have a reserved phrase END LOOP which indicates the ending of the while loop.

In order to execute the body of the loop the test condition needs to be true. If this condition is evaluated to be true
then the control will jump inside the loop and execute whatever statements it has. This iteration will continue until
the test condition becomes false. As soon as the test condition is evaluated to be false the control will come out of
the loop and execute the statement which immediately follows the loop.

Examples
SET SERVEROUTPUT ON;
DECLARE
V_NUMBER NUMBER := 0;
V_RESULT NUMBER;
BEGIN
WHILE V_NUMBER <10 LOOP
V_NUMBER := V_NUMBER+1;
V_RESULT := 18*V_NUMBER;
DBMS_OUTPUT.PUT_LINE(18||'X'||V_NUMBER||'='||V_RESULT);
END LOOP;
END;
/

18X1=18
18X2=36
18X3=54
18X4=72
18X5=90
18X6=108
18X7=126
18X8=144
18X9=162
18X10=180

PL/SQL procedure successfully completed.

In this example we have declared two variables – V_NUMBER which will serve as a counter and variable
V_RESULT which will hold the result of multiplication.

Down in the execution section we have our while loop. The first statement inside the loop body is an arithmetic
expression which will perform the multiplication of our table and will store the result in V_RESULT variable.

2nd Statement is an output statement which will print the result of the multiplication in a formatted manner.

And the third statement is an update statement which will update the counter with each iteration.

This while loop will keep on iterating until the counter is less than 10. Once the value of the counter becomes 10 the
while loop will terminate and execute the first statement immediately outside the loop body.

Example 2 Boolean Expression

SET SERVEROUTPUT ON;


DECLARE
V_TEST BOOLEAN := TRUE;
V_NUMBER NUMBER :=0;
BEGIN
WHILE V_TEST LOOP
V_NUMBER := V_NUMBER +1;
DBMS_OUTPUT.PUT_LINE(V_NUMBER);
IF V_NUMBER = 10 THEN
V_TEST := FALSE;
END IF;
END LOOP;
END;
/

1
2
3
4
5
6
7
8
9
10

PL/SQL procedure successfully completed.

With the Boolean expression in loop we have to write the code which will change its value to false and terminate the
loop. Failing to do so can make your loop an infinity loop. In the above program the simple IF THEN block inside
the loop body will change the value of the Boolean expression V_TEST and set it on false when V_NUMBER
becomes equal to 10 this will terminate the loop and bring the V_NUMBER over the first statement immediately
outside the loop body.

SET SERVEROUTPUT ON;


DECLARE
V_TEST BOOLEAN := TRUE;
V_NUMBER NUMBER :=0;
V_RESULT NUMBER;
BEGIN
WHILE V_TEST LOOP
V_NUMBER := V_NUMBER +1;
V_RESULT := 17*V_NUMBER;
DBMS_OUTPUT.PUT_LINE(17||'X'||V_NUMBER||'='||V_RESULT);
IF V_NUMBER = 10 THEN
V_TEST := FALSE;
END IF;
END LOOP;
END;
/

17X1=17
17X2=34
17X3=51
17X4=68
17X5=85
17X6=102
17X7=119
17X8=136
17X9=153
17X10=170

PL/SQL procedure successfully completed.

13.Numeric FOR Loop In PL/SQL


The simplicity and easy to use behavior of FOR loop has won the hearts of millions and has become the most widely
used loop in programming. In PL/SQL we have two types of FOR loops:

1. Numeric FOR loop and


2. Cursor FOR loop.
3.
FOR loop allows you to execute the block of statements repeatedly for a fixed number of time whereas WHILE loop
is better suited when the number of iterations are unknown.
This section will concentrate on Numeric “FOR LOOP”. We’ll leave the Cursor FOR loop for the future when we
will learn the concepts of Cursor.

Syntax
FOR loop_counter IN [REVERSE] lower_bound..upper_bound LOOP
-- Loop body statements
END LOOP;

Counter Variable: The loop_counter variable is used to control the iteration of the loop. It is automatically initialized
to the lower_bound value and increments (or decrements, if the loop is defined as REVERSE) by 1 in each iteration.
The loop terminates when the loop_counter reaches the upper_bound.

Loop Range: The lower_bound and upper_bound define the range of values that the loop counter will take. The loop
will execute the loop body statements for each value of the loop counter within this range.

REVERSE Keyword: The optional REVERSE keyword can be used to execute the FOR loop in the reverse
direction (i.e., from upper_bound to lower_bound).

Example 1: FOR loop


SET SERVEROUTPUT ON;
BEGIN
FOR v_counter IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(v_counter );
END LOOP;
END;
/

1
2
3
4
5
6
7
8
9
10

PL/SQL procedure successfully completed.

Here we only have the execution section and inside that we have our FOR loop which will print the value of
v_counter variable from 1 to 10.

Have you noticed that we didn’t declare the v_counter variable anywhere in the program? Even we don’t have the
declaration section here in this code. This is because variable v_counter is an implicit index integer variable which
gets declared automatically with the definition of FOR loop. Moreover the variable v_counter will increment by 1
with each iteration automatically by FOR loop construct thus you do not need to write update statement
(v_counter := v_counter +1) explicitly. As a matter of fact if you will try to write the update statement in the “FOR
loop” then you will get an error.

Example 2: FOR Loop with IN REVERSE keyword.


Now suppose you want to print the counting, same as we did in the previous example but this time in reverse order.
To do so you don’t have to change the loop definition or even you don’t have to add any extra line of codes,
PL/SQL block will be same as of the previous example. You just have to add one keyword REVERSE immediately
after IN keyword in FOR LOOP definition. Rest of the code will remain the same as that of the previous example.

BEGIN
FOR v_counter IN REVERSE 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(v_counter);
END LOOP;
END;
/

10
9
8
7
6
5
4
3
2
1

PL/SQL procedure successfully completed.

Example 3: Multiplication Table using Numeric FOR loop


SET SERVEROUTPUT ON;
DECLARE
V_RESULT NUMBER;
BEGIN
FOR V_NUMBER IN 1..10 LOOP
V_RESULT :=16*V_NUMBER;
DBMS_OUTPUT.PUT_LINE(16||'X'||V_NUMBER||'='||V_RESULT);
END LOOP;
END;
/

16X1=16
16X2=32
16X3=48
16X4=64
16X5=80
16X6=96
16X7=112
16X8=128
16X9=144
16X10=160

PL/SQL procedure successfully completed.

In this example we need one extra variable to store the result of the multiplication thus we declared a variable
V_RESULT with NUMBER data type. In the execution section we have our “FOR loop” and this time inside the
loop we have only two statements. First is an arithmetic expression which will perform the multiplication of our
table and will store the result in V_RESULT variable. Second is the output statement which will display you the
result in a formatted manner.
14.Database Triggers In PL/SQL
Triggers are named PL/SQL blocks which are stored in the database. We can also say that they are specialized
stored programs which execute implicitly when a triggering event occurs. This means we cannot call and execute
them directly instead they only get triggered by events in the database.

Events Which Fires the Database Triggers

These events can be anything such as

1. A DML Statement – An Update, Insert or Delete statement executing on any table of your database. You can
program your trigger to execute either BEFORE or AFTER executing your DML statement. For example, you can
create a trigger which will get fired Before the Update. Similarly, you can create a trigger which will get triggered
after the execution of your INSERT DML statement.
2. A DDL Statement – Next type of triggering statement can be a DDL Statement such as CREATE or ALTER. These
triggers can also be executed either BEFORE or AFTER the execution of your DDL statement. These triggers are
generally used by DBAs for auditing purposes. And they really come in handy when you want to keep an eye on the
various changes on your schema. For instance, who created the object or which user. Just like some cool spy tricks.
3. A system event. – Yes, you can create a trigger on a system event. And by a system event, I mean shut down or
startup of your database.
4. A User Events – Another type of triggering event can be User Events such as log off or log on onto your database.
You can create a trigger which will either execute before or after the event. Furthermore, it will record the
information such as time of event occur, the username who created it.

Types of Database Triggers


There are 5 types of triggers in the Oracle database. 3 of them are based on the triggering event which are discussed
in the previous section.

1. Data Manipulation Language Triggers or DML triggers

As the name suggests these are the triggers which depend on DML statements such as Update, Insert or Delete. They
get fired either before or after them. Using DML trigger you can control the behavior of your DML statements. You
can audit, check, replace or save values before they are changed. Automatic Increment of your Numeric primary key
is one of the most frequent tasks of these types of triggers.

2. Data Definition Language Triggers or DDL triggers.

Again as the name suggests these are the type of triggers which are created over DDL statements such as CREATE
or ALTER. They get fired either before or after the execution of your DDL statements. Using this type of trigger you
can monitor the behavior and force rules on your DDL statements.
3. System or Database Event triggers.

Third type of triggers is system or database triggers. These are the type of triggers which come into action when
some system event occurs such as database log on or log off. You can use these triggers for auditing purposes. For
example, keeping an eye on information of system access like say who connects with your database and when. Most
of the time System or Database Event triggers work as Swiss Knife for DBAs and help them in increasing the
security of the data.

4. Instead-of Trigger

This is a type of trigger which enables you to stop and redirect the performance of a DML statement. Often this type
of trigger helps you in managing the way you write to non-updatable views. You can also see the application of
business rules by INSTEAD OF triggers where they insert, update or delete rows directly in tables that are defining
updatable views. Alternatively, sometimes the INSTEAD OF triggers are also seen inserting, updating or deleting
rows in designated tables that are otherwise unrelated to the view.

5. Compound triggers

These are multi-tasking triggers that act as both statement as well as row-level triggers when the data is inserted,
updated or deleted from a table. You can capture information at four timing points using this trigger:

 before the firing statement;


 prior to the change of each row from the firing statement;
 post each row changes from the firing statement;
 after the firing statement.
All these types of triggers can be used to audit, check, save and replace the values. Even before they are changed
right when there is a need to take action at the statement as well as at row event levels.

Syntax
CREATE [OR REPLACE] TRIGGER Ttrigger_name
{BEFORE|AFTER} Triggering_event ON table_name
[FOR EACH ROW]
[FOLLOWS another_trigger_name]
[ENABLE/DISABLE]
[WHEN condition]
DECLARE
declaration statements
BEGIN
executable statements
EXCEPTION
exception-handling statements
END;

Uses of Database triggers.


1. Using database triggers we can enforce business rules that can’t be defined by using integrity constants.
2. Using triggers we can gain strong control over the security.
3. We can also collect statistical information on the table access.
4. We can automatically generate values for derived columns such as auto increment numeric primary key.
5. Using database triggers we can prevent the invalid transactions.
Restriction on The Database Triggers
1. The maximum size of the database trigger body must not exceed 32,760 bytes. This is because triggers’ bodies are
stored in LONG datatypes columns.
2. A trigger may not issue transaction control statements or TCL statements such as COMMIT, ROLLBACK or
SAVEPOINT. All operations performed when the trigger fires, become part of a transaction. Therefore whenever
this transaction is rolled back or committed it leads to the respective rolling back or committing of the operations
performed.
3. Any function or procedure called by a database trigger may not issue a transactional control statement. That is unless
it contains an autonomous transaction.
4. Declaring LONG or LONG RAW variable is not permissible in the body of the trigger.

15.DML Triggers In PL/SQL


As the name suggests these are the triggers which execute on DML events or say depend on DML statements such
as Update, Insert or Delete. Using DML trigger you can control the behavior of your DML statements.

Examples
In order to demonstrate the creation process of DML trigger we need to first create a table.

CREATE TABLE superheroes (


sh_name VARCHAR2 (15)
);

I have created this table with the name SUPERHEROES which has only one column sh_name with data type
varchar2 and data width 15. Now I will write a DML trigger which will work on this table.

So the table is created. Now let’s do some examples which will help you in understanding the concepts more clearly.

Example 1. Before Insert Trigger


In the first example we will see how to create a trigger over Insert DML. This trigger will print a user defined
message every time a user inserts a new row in the superheroes table.

CREATE OR REPLACE TRIGGER bi_Superheroes


BEFORE INSERT ON superheroes
FOR EACH ROW
ENABLE
DECLARE
v_user VARCHAR2 (15);
BEGIN
SELECT user INTO v_user FROM dual;
DBMS_OUTPUT.PUT_LINE('You Just Inserted a Row Mr.'|| v_user);
END;
/
On successfully compiling, this trigger will show you a string along with the user name who performed the “Insert”
DML on superheroes table. Thus you check this trigger by Inserting a row in Superheroes table.

INSERT INTO superheroes VALUES ('Ironman');

You Just Inserted a Row Mr.SYSTEM

1 row inserted.

Example 2: Before Update Trigger.


Update Trigger is the one which will execute either before or after Update DML. The creation process of an Update
trigger is the same as that of Insert Trigger. You just have to replace Keyword INSERT with UPDATE in the 2nd
Line of the above example.

CREATE OR REPLACE TRIGGER bu_Superheroes


BEFORE UPDATE ON superheroes
FOR EACH ROW
ENABLE
DECLARE
v_user VARCHAR2 (15);
BEGIN
SELECT user INTO v_user FROM dual;
DBMS_OUTPUT.PUT_LINE('You Just Updated a Row Mr.'|| v_user);
END;
/
On successfully compiling, this trigger will print a user defined string with the username of the user who updated the
row. You can check this trigger by writing an update DML on the superheroes table.

UPDATE superheroes SET SH_NAME = ‘Superman’ WHERE SH_NAME='Ironman';

You Just Inserted a Row Mr.SYSTE


1 row inserted

Example 3: Before Delete Trigger


Similar to Insert and Update DML you can write a trigger over Delete DML. This trigger will execute either before
or after a user deletes a row from the underlying table.

CREATE OR REPLACE TRIGGER bu_Superheroes


BEFORE DELETE ON superheroes
FOR EACH ROW
ENABLE
DECLARE
v_user VARCHAR2 (15);
BEGIN
SELECT user INTO v_user FROM dual;
DBMS_OUTPUT.PUT_LINE('You Just Deleted a Row Mr.'|| v_user);
END;
/
You can check the working of this trigger by executing a DELETE DML on underlying table which is superheroes.

DELETE FROM superheroes WHERE sh_name = 'Superman';

You Just Deleted a Row Mr.SYSTEM


1 row deleted.

Above three examples showed you 3 different triggers for 3 different DML events on one table. Don’t you think that
if we can cover all these 3 events in just 1 trigger then it will be a great relief? If you think so then my dear friend I
have some good news for you. Let me show you how we can achieve this feat.

In PL/SQL, Data Definition Language (DDL) triggers are used to respond to changes in the database
schema. These triggers are fired automatically when specific DDL statements (e.g., CREATE, ALTER,
DROP) are executed. DDL triggers allow developers to define custom actions that should be taken before
or after DDL statements, such as deleting, inserting, or updating keywords.

Here's a brief overview of how you can handle deleting, inserting, or updating keywords in DDL triggers:

1. Deleting Keywords:
When a DDL trigger is fired due to a DELETE operation on a database object (e.g., dropping a table), you
can use the trigger to perform specific actions before or after the deletion. For instance, you might want to
log the event, prevent certain objects from being deleted, or perform additional cleanup tasks before the
object is removed from the schema.
2. Inserting Keywords:
If a DDL trigger is triggered by an INSERT operation on a database object (e.g., creating a new table or
index), you can utilize the trigger to perform actions related to the newly created object. For example, you
could set default values for specific columns, apply naming conventions, or grant permissions to certain
users after the object is created.

3. Updating Keywords:
When a DDL trigger is invoked by an UPDATE operation on a database object (e.g., modifying a table's
structure), you can leverage the trigger to carry out tasks before or after the update. For instance, you
might want to enforce specific constraints, synchronize related objects, or log the changes made during the
update process.

It's important to note that while DDL triggers can be powerful tools for managing database schema
changes, they should be used judiciously. Careful consideration of the potential impact on the database
and the necessity of the triggered actions is essential to avoid unintended consequences.

Example 4: INSERT, UPDATE, DELETE All in One DML Trigger Using IF-THEN-
ELSIF
CREATE OR REPLACE TRIGGER tr_superheroes
BEFORE INSERT OR DELETE OR UPDATE ON superheroes
FOR EACH ROW
ENABLE
DECLARE
v_user VARCHAR2(15);
BEGIN
SELECT
user INTO v_user FROM dual;
IF INSERTING THEN
DBMS_OUTPUT.PUT_LINE('one line inserted by '||v_user);
ELSIF DELETING THEN
DBMS_OUTPUT.PUT_LINE('one line Deleted by '||v_user);
ELSIF UPDATING THEN
DBMS_OUTPUT.PUT_LINE('one line Updated by '||v_user);
END IF;
END;
/
Using this one trigger you can achieve the same results as that of the above three triggers.

EXAMPLE:-
CREATE TABLE VEHICLES_LOGS(
LOG_USER VARCHAR2(30),
LOG_MESSAGE VARCHAR(30),
LOG_DATE DATE);

TRIGGER 1
SET SERVEROUTPUT ON;
CREATE OR REPLACE TRIGGER before_insert_trigger
BEFORE INSERT ON VEHICLES
FOR EACH ROW
BEGIN
INSERT INTO VEHICLES_LOGS(LOG_USER, LOG_MESSAGE, LOG_DATE)
VALUES(USER, 'Vehicles log updated before insert', SYSTIMESTAMP);
END;
/

TRIGGER 2
SET SERVEROUTPUT ON;
CREATE OR REPLACE TRIGGER after_insert_trigger
AFTER INSERT ON VEHICLES
FOR EACH ROW
BEGIN
INSERT INTO VEHICLES_LOGS(LOG_USER, LOG_MESSAGE, LOG_DATE)
VALUES(USER, 'Vehicles log updated After insert', SYSTIMESTAMP);
END;
/

When ever we insert a new row both the triggeres get fired and we can see the data in VEHICLES_LOG table.

SYSTEM Vehicles log updated before insert 31-JUL-23


SYSTEM Vehicles log updated After insert 31-JUL-23
In PL/SQL triggers, the NEW and OLD keywords are used to reference the new and old values of the
rows being affected by a DML (Data Manipulation Language) trigger, such as an INSERT, UPDATE, or
DELETE operation. These keywords are especially useful in "row-level" triggers, which are triggered for
each affected row.

Here's a brief explanation of the NEW and OLD keywords in triggers:

NEW:

The NEW keyword represents the new values that will be inserted or updated into the table after the DML
operation.

 In an INSERT trigger, the NEW keyword refers to the values being inserted into the table.
 In an UPDATE trigger, the NEW keyword represents the new values that will replace the existing
values in the table.
 In a DELETE trigger, the NEW keyword is not applicable since there are no new values being
added.

OLD:

The OLD keyword represents the existing values of the rows before the DML operation.

 In an UPDATE trigger, the OLD keyword refers to the old values that are currently in the table,
before any updates take place.
 In a DELETE trigger, the OLD keyword represents the values that are being removed from the
table.
 In an INSERT trigger, the OLD keyword is not applicable since there are no old values.

By using the NEW and OLD keywords in triggers, you can perform actions based on the values of the
affected rows before and after a DML operation. These keywords add flexibility and control to your
trigger logic, allowing you to enforce business rules, perform audits, and take various actions based on
the data changes.

EXAPLES OF NEW AND OLD KEYWORDS


CREATE TABLE VEHICLES(
V_NAMES VARCHAR2(30),
V_AGES NUMBER);

CREATE TABLE VEHICLES_AUDIT_LOG(


USER_NAME VARCHAR(50),
NEW_V_NAME VARCHAR(30),
NEW_V_AGE NUMBER,
TIME_STAMP TIMESTAMP);

:NEW

->INSERT
SET SERVEROUTPUT ON;
CREATE OR REPLACE TRIGGER VEHICLES_TABLE_AUDIT
AFTER INSERT ON VEHICLES
FOR EACH ROW
BEGIN
INSERT INTO VEHICLES_AUDIT_LOG (USER_NAME, NEW_V_NAME, NEW_V_AGE,
TIME_STAMP)
VALUES (USER, :NEW.V_NAMES, :NEW.V_AGES, SYSTIMESTAMP);
END;
/

INSERT INTO VEHICLES VALUES('AIRPLAIN TOY',11);

INSERT INTO VEHICLES VALUES('TOY CYCLE',2);

SELECT * FROM VEHICLES_AUDIT_LOG;


SYSTEM TOY CYCLE 2 01-AUG-23 08.27.17.023000000 AM
SYSTEM AIRPLAIN TOY 11 01-AUG-23 09.24.45.554000000 AM

-> UPDATE

SET SERVEROUTPUT ON;


CREATE OR REPLACE TRIGGER UPDATE_VEHICLES_TABLE_AUDIT
AFTER UPDATE ON VEHICLES
FOR EACH ROW
BEGIN
INSERT INTO VEHICLES_AUDIT_LOG (USER_NAME, NEW_V_NAME, NEW_V_AGE,
TIME_STAMP)
VALUES (USER, :NEW.V_NAMES, :NEW.V_AGES, SYSTIMESTAMP);
END;
/

UPDATE VEHICLES
SET V_NAMES = 'BIKE'
WHERE V_NAMES ='AIRPLAIN TOY';

SELECT * FROM VEHICLES_AUDIT_LOG;


SYSTEM TOY CYCLE 2 01-AUG-23 08.27.17.023000000 AM
SYSTEM AIRPLAIN TOY 11 01-AUG-23 09.24.45.554000000 AM
SYSTEM BIKE 11 01-AUG-23 09.34.51.651000000 AM

:OLD

-> UPDATE
SET SERVEROUTPUT ON;
CREATE OR REPLACE TRIGGER TRG_VEHICLES_AUDIT_OLD
AFTER UPDATE ON VEHICLES
FOR EACH ROW
BEGIN
INSERT INTO VEHICLES_AUDIT_LOG (USER_NAME, NEW_V_NAME, NEW_V_AGE,
TIME_STAMP)
VALUES (USER, :OLD.V_NAMES, :OLD.V_AGES, SYSTIMESTAMP);
END;
/

UPDATE VEHICLES
SET V_NAMES = 'HUSSAIN CYCLE'
WHERE V_NAMES ='CYCLE';

SELECT * FROM VEHICLES_AUDIT_LOG;


SYSTEM CYCLE 16 01-AUG-23 09.50.34.017000000 AM
SYSTEM HUSSAIN CYCLE 16 01-AUG-23 09.50.34.017000000 AM
SYSTEM CYCLE 16 01-AUG-23 09.50.34.017000000 AM
SYSTEM HUSSAIN CYCLE 16 01-AUG-23 09.50.34.017000000 AM
SYSTEM CYCLE 16 01-AUG-23 09.50.34.017000000 AM
SYSTEM HUSSAIN CYCLE 16 01-AUG-23 09.50.34.017000000 AM

-> DELETE
SET SERVEROUTPUT ON;
CREATE OR REPLACE TRIGGER DEL_VEHICLES_AUDIT_OLD
AFTER DELETE ON VEHICLES
FOR EACH ROW
BEGIN
INSERT INTO VEHICLES_AUDIT_LOG (USER_NAME, NEW_V_NAME, NEW_V_AGE,
TIME_STAMP)
VALUES (USER, :OLD.V_NAMES, :OLD.V_AGES, SYSTIMESTAMP);
END;
/

DELETE FROM VEHICLES WHERE v_ages = 4;

SELECT * FROM VEHICLES_AUDIT_LOG;


SYSTEM BIKE 4 01-AUG-23 09.55.33.886000000 AM
SYSTEM BIKE 4 01-AUG-23 09.55.33.886000000 AM

16.Table Auditing Using DML Triggers In Oracle PL/SQL


Table Auditing
Table auditing means keeping a track of all the dml activities performed on a specific table of the database for
example which user Inserted, updated or deleted a row from the table and when. It is like spying on the users who
are messing your table’s data.

Example
For the demonstration we will use the table ‘Superheroes’ which we created in the previous tutorial.

Suppose you want to keep an eye on the users who are inserting, updating or deleting data from the ‘Superheroes’
table. Let’s see how we can achieve this. To do so we will need another table in which we can journal the auditing
data entries.

CREATE TABLE SUPERHEROES(


SH_NAME VARCHAR2(15));

CREATE TABLE sh_audit(


new_name varchar2(30),
old_name varchar2(30),
user_name varchar2(30),
entry_date varchar2(30),
operation varchar2(30)
);

This table sh_audit has 5 columns which will store the auditing information such as the new data inserted or
updated, old data which is updated or deleted from the table, name of the user who did it along with the date and
time, also the type of DML operation performed.

Next we will write a trigger on the source table superheroes and will store the data into the auditing table sh_audit.

CREATE OR REPLACE trigger superheroes_audit


BEFORE INSERT OR DELETE OR UPDATE ON superheroes
FOR EACH ROW
ENABLE
DECLARE
v_user varchar2 (30);
v_date varchar2(30);
BEGIN
SELECT user, TO_CHAR(sysdate, 'DD/MON/YYYY HH24:MI:SS') INTO v_user, v_date FROM dual;
IF INSERTING THEN
INSERT INTO sh_audit (new_name,old_name, user_name, entry_date, operation)
VALUES(:NEW.SH_NAME, Null , v_user, v_date, 'Insert');
ELSIF DELETING THEN
INSERT INTO sh_audit (new_name,old_name, user_name, entry_date, operation)
VALUES(NULL,:OLD.SH_NAME, v_user, v_date, 'Delete');
ELSIF UPDATING THEN
INSERT INTO sh_audit (new_name,old_name, user_name, entry_date, operation)
VALUES(:NEW.SH_NAME, :OLD.SH_NAME, v_user, v_date,'Update');
END IF;
END;
/
I would highly suggest you to watch the YouTube Video Tutorial on the same topic since there I have explained the
working of this particular trigger line by line in detail.

On successful compilation this trigger will insert a row containing auditing data such as the data inserted, updated
and deleted from the source table superheroes along with the username who tampered the data as well as the date
and time when it was done and also the name of DML statement executed by user to tamper the data of your table.

Pseudo Records (New/Old)


If you will carefully see the Insert statements used in the IF-THEN-ELSIF statements in the above code, we used
some Pseudo Records such as ‘:New’ or ‘:Old’ followed by the name of the column of our source table sh_name.

These Psuedo Records helps us in fetching data from the sh_name column of the underlying source table
‘Superheroes’ and storing it into the audit table sh_audit.

Pseudo Record ‘: NEW’, allows you to access a row currently being processed. In other words, when a row is being
inserted or updated into the superheroes table. Whereas Pseudo Record ‘: OLD’ allows you to access a row which is
already being either Updated or Deleted from the superheroes table.
In order to fetch the data from the source table, you have to first write the proper Pseudo Record (New/Old)
followed by dot (.) and the name of the column of the source table whose value you want to fetch. For example in
our case we want to fetch the data from sh_name column which belongs to our source table superheroes. Thus we
will write “: New. sh_name” for fetching the current value and to fetch the previously stored value we will write “:
OLD. sh_name”. Once the values are fetched the INSERT dml will store these values into the respective columns of
the audit table.

Restriction on Pseudo Record


 For an INSERT trigger, OLD contain no values, and NEW contain the new values.
 For an UPDATE trigger, OLD contain the old values, and NEW contain the new values.
 For a DELETE trigger, OLD contain the old values, and NEW contain no values.

Once you execute and compile this trigger then you can take it on a test run by writing DML statements on the
underlying source table ‘Superheroes’. For example you can try Inserting a row in superheroes table and then check
the audit table whether there is some data or not.
INSERT INTO SUPERHEROES VALUES('SPYDER MAN');

UPDATE SUPERHEROES SET SH_NAME ='BAT MAN' WHERE SH_NAME='SPYDER MAN';

DELETE FROM SUPERHEROES WHERE SH_NAME ='BAT MAN';

As soon as you execute any of these DML statements on the underlying table superheroes, the trigger will execute in
the background and insert the audit data into the audit table sh_audit.

SELECT * FROM SUPERHEROES;


SPYDER MAN (NULL) SYSTEM 01-08-2023 11:43:14 AM INSERT
BAT MAN SPYDER MAN SYSTEM 01-08-2023 11:46:15 AM UPDATE
( NULL) BAT MAN SYSTEM 01-08-2023 11:47:59 AM DELETE

17.How To Create Synchronized Table Backup Using


DML Trigger In Oracle PL/SQL
By synchronized backup copy means the backup table gets automatically populated or updated with the main table
simultaneously.

For the demonstration we will require two identical tables; one which will serve as your main table that will accept
the data from your database user and the second which will be your backup table
To create a table for backup, you can use the CREATE TABLE statement in SQL. The new table will have
the same structure as the original table from which you want to create a backup. Here's the SQL query to
create a backup table.

SYNTAX

CREATE TABLE BACK_UP_TABLE_NAME AS


SELECT * FROM ORIGINAL_TABLE_NAME WHERE 1=0;

In this Syntax:

“CREATE TABLE BACK_UP_TABLE_NAME “ specifies the name of the new table you want to create and
“AS SELECT * FROM ORIGINAL_TABLE_NAME WHERE 1=0” is a subquery that selects no rows
(WHERE 1=0 which is evaluated as false) from the original table. By doing this, you create an empty table
with the same structure but without any data.

If we provide the WHERE clause as (WHERE 1=1) when creating the backup table, it will copy all the data
from the original table to the backup table. The condition 1=1 always evaluates to true, so the SELECT query
will fetch all the rows from the original table.

Copy Table With or Without Data Using Create Table


As Statement
“Create Table As” is a DDL command which lets you create an exact copy of a table of your database with or
without the data

Syntax:

CREATE TABLE table_name_1


AS
SELECT [*]/column_name(s) FROM table_name_2 WHERE expression;

Syntax is pretty simple CREATE TABLE is oracle reserved phrase followed by the user defined name of the
table ‘table_name_1’ with which you want to create your new table then we have mandatory keyword ‘AS’
followed by a simple SELECT DML statement.

Table_name_2 is the name of the table whose copy you want to make and table_name_1 is the name of your
new table.

Examples:
For the demonstration we will use the Employees table of HR sample schema of the Oracle Database.

Suggested Tutorial: How to connect with the HR user of your database.

E.g. 1: How to copy both the structure and data of a table.


Suppose you want to make an exact copy of employees table of HR schema and by exact copy I mean
copying the whole structure along with the data of employees table.

Copying the exact structure and data of the employees table can be done by writing a very simple Create table
statement. That statement will be

CREATE TABLE employees_copy


AS
SELECT * FROM employees;

Successful execution of the above command will create the employees_copy which will be having the same
structure and data as of the Employees table of HR schema.
E.g. 2. How to copy specific columns of a table along with their data.
Now suppose you want to copy only first_name, last_name or email columns with data of employees table in
this case CREATE TABLE statement will be.

CREATE TABLE employees_copy


AS
SELECT first_name, last_name, email FROM employees;

Successful execution of the above command will create the table employees_copy this time with only column
first_name, last_name and email and the data.

E.g. 3. How to copy only structure of the table without the data.
Sometimes you might be required to copy only the structure of the table sans the data. In this case what you
can do is copy the whole table as shown in above examples and then truncate it later but this will need two
operations or two different commands to execute for a single task: Such a waste of time & resources when
you can accomplish the same just by writing a simple “Create Table As command”.

The Create Table command will remain the same as shown in above examples. You just need to add a where
clause which will never set to be true or always false for example where clause such as ‘Cats’ = ‘Dog’ or 0=1.
Let’s see how

CREATE TABLE employees_copy


AS
SELECT first_name, last_name, email FROM employees WHERE 1=0;

CREATE TABLE EMPLOYEES(


EMP_ID NUMBER,
EMP_NAME VARCHAR(50),
EMP_ROLE VARCHAR(50),
EMP_SALARY NUMBER);

Next we will have to create an identical table to this one which will work as our backup table.

CREATE TABLE EMPLOYEES_BACKUP AS SELECT * FROM EMPLOYEES WHERE 1=2;

Next we have to write the trigger which will insert, update or delete the rows from the backup table when someone
does the same with our main table.

SET SERVEROUTPUT ON;


CREATE OR REPLACE TRIGGER EMP_BACKUP
BEFORE INSERT OR UPDATE OR DELETE ON EMPLOYEES
FOR EACH ROW
ENABLE
BEGIN

IF INSERTING THEN

INSERT INTO EMPLOYEES_BACKUP(EMP_ID,EMP_NAME,EMP_ROLE,EMP_SALARY)


VALUES
(:NEW.EMP_ID,:NEW.EMP_NAME,:NEW.EMP_ROLE,:NEW.EMP_SALARY);

ELSIF UPDATING THEN

UPDATE EMPLOYEES_BACKUP
SET
EMP_ID = :NEW.EMP_ID,
EMP_NAME = :NEW.EMP_NAME,
EMP_ROLE = :NEW.EMP_ROLE,
EMP_SALARY = :NEW.EMP_SALARY
WHERE
EMP_ID = :OLD.EMP_ID;

ELSIF DELETING THEN

DELETE FROM EMPLOYEES_BACKUP


WHERE
EMP_ID = :OLD.EMP_ID;

END IF;
END;
/

After successful execution of the trigger, changes from the main table will get reflected on the backup table
too.

Verification
INSERT INTO EMPLOYEES VALUES(1,'MAHAMMAD HUSSAIN','SYSTEM ENGINEER',374000);
INSERT INTO EMPLOYEES VALUES(2,'VAMSI','SYSTEM ENGINEER',376000);
INSERT INTO EMPLOYEES VALUES(3,'GIRISH','DEVELOPER',402000);

Same data is inserted into both tables

SELECT * FROM EMPLOYEES;

1 MAHAMMAD HUSSAIN SYSTEM ENGINEER 374000


2 VAMSI SYSTEM ENGINEER 376000
3 GIRISH DEVELOPER 402000

SELECT * FROM EMPLOYEES_BACKUP ;

1 MAHAMMAD HUSSAIN SYSTEM ENGINEER 374000


2 VAMSI SYSTEM ENGINEER 376000
3 GIRISH DEVELOPER 402000

UPDATE EMPLOYEES SET EMP_SALARY =368000 WHERE EMP_ID =1;

Data updated in both tables

SELECT * FROM EMPLOYEES;

1 MAHAMMAD HUSSAIN SYSTEM ENGINEER 368000

SELECT * FROM EMPLOYEES_BACKUP ;

1 MAHAMMAD HUSSAIN SYSTEM ENGINEER 368000


18.Schema & Database Auditing Using DDL Trigger In
PL/SQL

In Oracle SQL, there is a one-to-one relationship between a user account and a schema. This means that each
user account is associated with a single schema, and the name of the user account is the same as the name of
the schema it owns. When a user is created, a schema with the same name is automatically created for that
user.

The relationship between a user account and a schema can be summarized as follows:

User Account:
A user account is an entity used to connect to the Oracle database. It is identified by a unique username and
is associated with a password. When a user account connects to the database, it gains access to its associated
schema and the objects (tables, views, procedures, etc.) within that schema.

Schema:
A schema in Oracle is a logical container for database objects. It is associated with a specific user account,
and its name is the same as the username of that user. Any objects created by the user account are
automatically created within its associated schema. The schema provides a namespace for organizing and
managing database objects owned by that user.

For example, if you have a user account with the username "john," there will also be a schema named
"john" associated with that user. Any tables, views, or other objects created by the user account "john" will
be stored in the "john" schema.

This one-to-one relationship between user accounts and schemas simplifies the management of database
objects and access control, making it easier to control who can access and modify specific objects within the
database. However, it is essential to grant the appropriate privileges to users to ensure proper data security
and access control.

DDL triggers are the triggers which are created over DDL statements such as CREATE, DROP or ALTER. Using
this type of trigger you can monitor the behavior and force rules on your DDL statements.

In order to proceed ahead and start writing the trigger first we need a table in which we can journal the auditing
information created by the trigger.

CREATE TABLE schema_audit


(
ddl_date DATE,
ddl_user VARCHAR2(15),
object_created VARCHAR2(15),
object_name VARCHAR2(15),
ddl_operation VARCHAR2(15)
);

In case of schema/user auditing using DDL trigger creates this table in the same schema which you are auditing and
in case of Database auditing using DDL trigger create this table in sys or system schema (sys or system both
schemas can be used to perform database auditing).

DDL Trigger for Schema Auditing

sysdate: This is a built-in Oracle function that returns the current date and time.

sys_context('USERENV','CURRENT_USER'): This is another Oracle function called sys_context,


which is used to retrieve the value of a session parameter. In this case, it is used to get the name of the current
user who is executing the statement.

The sys_context function is used to access various session-specific and system-related information within
Oracle databases. It takes two arguments:

The first argument represents the namespace of the context item you want to retrieve. In this case, 'USERENV'
is the namespace used to access user environment-related information.

The second argument specifies the parameter name or context item within the namespace. For the current user's
name, we use 'CURRENT_USER' as the parameter name.

ora_dict_obj_type: This is a placeholder for a value that represents the type of the object involved in the
operation that triggered the trigger (assuming this is part of a trigger definition). The value will depend on the
type of the object (e.g., TABLE, VIEW, TRIGGER, etc.).

ora_dict_obj_name: Similar to the previous one, this is a placeholder for a value that represents the name of
the object involved in the operation.

ora_sysevent: This is another placeholder for a value that represents the type of event (e.g., INSERT,
UPDATE, DELETE) that triggered the trigger (again, assuming this is part of a trigger definition).

CREATE OR REPLACE TRIGGER hr_audit_tr


AFTER DDL ON SCHEMA
BEGIN
INSERT INTO schema_audit VALUES (
sysdate,
sys_context('USERENV','CURRENT_USER'),
ora_dict_obj_type,
ora_dict_obj_name,
ora_sysevent);
END;
/

If you will notice carefully the second line of the code (“AFTER DDL ON SCHEMA”) indicates that this trigger
will work on the schema in which it is created. On successful compilation this trigger will insert the respective
information such as the date when the DDL is executed, username who executed the DDL, type of database object
created, name of the object given by the user at the time of its creation and the type of DDL into the table which we
created earlier.

DDL Trigger for Database Auditing.


Similar to the schema auditing with some minor changes in the above trigger you can audit your database too. But
for that first you need to logon to the database using either SYS user or SYSTEM user.

database is a physical container that holds data, while a schema is a logical container within that database that
defines the structure and organization of the data. The database contains multiple schemas, and each schema
contains various database objects related to a specific part of the application or system.

the main difference is that a DDL trigger for schema auditing is limited to capturing changes within a
specific schema, while a DDL trigger for database auditing captures changes across the entire database.

CREATE OR REPLACE TRIGGER db_audit_tr


AFTER DDL ON DATABASE
BEGIN
INSERT INTO schema_audit VALUES (
sysdate,
sys_context('USERENV','CURRENT_USER'),
ora_dict_obj_type,
ora_dict_obj_name,
ora_sysevent);
END;
/

select * from schema_audit;


02-AUG-23SYSTEM TABLE HUSSAIN CREATE
02-AUG-23SYSTEM TABLE HUSSAIN DROP
02-AUG-23SYSTEM TABLE HUSSAIN CREATE
02-AUG-23SYSTEM TABLE HUSSAIN ALTER
02-AUG-23SYSTEM TRIGGER DB_AUDIT_TR CREATE
02-AUG-23SYSTEM TABLE SHAFI CREATE
02-AUG-23SYSTEM TABLE SHAFI CREATE

19. Schema Level Database LOGON Trigger In PL/SQL

**Database in SQL:**

A database in SQL (Structured Query Language) is a collection of organized data that is stored, managed,
and accessed electronically. It is designed to efficiently store and retrieve data to support various applications
and processes. Databases consist of tables, which are structured collections of data with rows and columns.

**Schema in SQL:**

A schema in SQL is a logical container or namespace within a database. It defines the structure of the
database by describing how the data is organized and the relationships between different elements, such as
tables, views, procedures, and functions. A schema acts as a blueprint for organizing and accessing the data
within a database.

**Difference between Database and Schema:**

1. **Scope:**
- A database is the top-level container that holds all the data and information for a specific application or
domain.
- A schema, on the other hand, is a subset of a database and represents a specific part or logical grouping of
the database objects.

2. **Organization:**
- In a database, multiple schemas can exist to organize data and objects efficiently. Each schema can have
its own tables, views, and other database objects.
- A schema defines the structure and layout of these objects, specifying their names, datatypes, and
relationships.

**Example:**
Let's consider a scenario of an e-commerce website:

**Database:** The e-commerce website's database contains all the data related to customers, products,
orders, etc. It is the entire collection of data.

**Schema:** Within the database, we can have multiple schemas to segregate the data for different aspects
of the website. For example, we can have separate schemas for 'Customers', 'Products', and 'Orders'. Each
schema will contain tables specific to its purpose.

**Customers Schema:**
```
Tables:
1. customer_info
- customer_id (Primary Key)
- name
- email
- address

2. customer_orders
- order_id (Primary Key)
- customer_id (Foreign Key)
- order_date
- total_amount
```

**Products Schema:**
```
Tables:
1. product_info
- product_id (Primary Key)
- name
- price
- description

2. product_stock
- product_id (Foreign Key)
- available_quantity
```

**Orders Schema:**
```
Tables:
1. order_items
- order_item_id (Primary Key)
- order_id (Foreign Key)
- product_id (Foreign Key)
- quantity
- subtotal
```

In this example, we have one database (the e-commerce website's database) with three schemas ('Customers',
'Products', and 'Orders'), each containing tables specific to their respective data types. The schema helps
organize the data and maintain the relationships between different entities more effectively.

Database event triggers also known as system event triggers come into action when some system event occurs such
as database log on, log off, start up or shut down. These types of triggers are majorly used for monitoring activity of
the system events and have been proved quite a powerful tool for a DBA.

Types of Database Event Triggers.


1. Schema Level Event Triggers
2. Database Level Event Triggers
3.
Schema level event triggers can work on some specific schemas while the database event triggers have database
wide scope. In other words database event triggers can be created to monitor the system event activities of either a
specific user/schema or the whole database.
Object/System Privileges
Schema level event triggers can be created by any user of your database who has CREATE TRIGGER system
privilege while the database event trigger can only be created by privileged user such as SYS or SYSTEM who has
‘Administrative Database Trigger’ System Privileges.

Syntax

CREATE OR REPLACE TRIGGER trigger_name


BEFORE | AFTER database_event ON database/schema
BEGIN
PL/SQL Code
END;

Example :- Schema Level Event Trigger.

Suppose user HR is a control freak and wants to monitor its every log on and log off activity. In this case what HR
can do is, create event triggers on Log on and log off database event in its own schema.

Step 1: Connect to the database

Connect to the database using the user/schema in which you want to create the trigger. For the demonstration I will
connect using my HR user.

Connect hr;

Or Connect with connections in sql developer

Step 2: Create a Table

Next you will need a table to store the logon and logoff data.

CREATE TABLE hr_evnt_audit(


event_type VARCHAR2(30),
logon_date DATE,
logon_time VARCHAR2(15),
logof_date DATE,
logof_time VARCHAR2(15));

Step3: Write the trigger Logon Schema Event Trigger.

Now you are connected to the database using the desired user and also have the table ready to store the data. The
only thing which is left is the trigger.

This trigger will fire every time HR user logs on to the database and respective values will be stored into the table
which we just created in the step 2.

CREATE OR REPLACE TRIGGER hr_lgon_audit


AFTER LOGON ON SCHEMA
BEGIN
INSERT INTO hr_evnt_audit VALUES(
ora_sysevent,
sysdate,
TO_CHAR(sysdate, 'hh24:mi:ss'),
NULL,
NULL
);
COMMIT;
END;
/

That is how we create a LogOn event trigger in Oracle Database.

20.What Is LogOff Database Event Trigger In Oracle


PL/SQL
Unlike logon database event trigger which fires after a valid logon attempt by a user on the database, logoff triggers
execute before the user logs off from the database. Logoff trigger can be proved as a versatile tool for a DBA as well
as for a database user.

Schema Level Logoff System Event Trigger


As I explained in the previous tutorial that a schema level trigger is one which worked only for a specific schema in
which it is created or designed to work for. Any user of the database who has “Create Trigger” system privilege can
design and create this trigger.

Example

Let’s write a trigger to audit the logoff

Step 1: Logon to the database

Logon to the database using any user such as HR or any other you want.

Step 2: Create a table.

Create a table to dump the data generated by your schema level logoff trigger.

CREATE TABLE hr_evnt_audit


(
event_type VARCHAR2(30),
logon_date DATE,
logon_time VARCHAR2(15),
logof_date DATE,
logof_time VARCHAR2(15)
);

Step 3: Write the trigger.

Below written trigger will execute every time user HR logs off from the database.

CREATE OR REPLACE TRIGGER log_off_audit


BEFORE LOGOFF ON SCHEMA
BEGIN
INSERT INTO hr_evnt_audit VALUES(
ora_sysevent,
NULL,
NULL,
SYSDATE,
TO_CHAR(sysdate, 'hh24:mi:ss')
);
COMMIT;
END;
/

On successful compilation this trigger will fire every time the user, using which it was created, logs off from the
database and that user in our case is HR.

As I said above that this trigger is bound to work only for the user in which it is created. What if we want to keep
track of all the logoff activities of all the users of the database? In such a scenario we can write a database level
system event trigger.

Database Level System/Database Event Trigger.


An often asked question in the interview is what are the differences between Schema Level and Database Level
system Event triggers? There can be variety of answers for this question but major differences are as follows.

As the name suggests Database event trigger fires for the entire database or you can say that it fires for all the
schemas created under the database in which these triggers are created which is unlike Schema Level System Event
trigger which runs for a specific schema only.

Also database level system event trigger can only be created by high privileged users such as sys or system or any
user who has ADMINISTER DATABASE TRIGGER system privilege where Schema level system event trigger
can be created by any user of the database on its own schema which has Create Trigger System Privilege.

Example: How To Create Database Level Logoff event Trigger In Oracle PL/SQL

Database Level Logoff Event Trigger is pretty similar to the trigger which we just saw for schema

Step 1: Logon to the database

As only the user with ADMINISTER DATABASE TRIGGER system privilege can create a database level event
trigger thus we need to make sure that this time we should log on to the database using one of these users.

Step 2: Create a Table

Again in order to store the audit data we need to create a table where this trigger will journal the entries of all the
users. The structure of the table will be pretty similar to the above one except one extra column for storing the
username with the help of which we can clearly identify the details and avoid the confusion.

CREATE TABLE db_evnt_audit


(
User_name VARCHAR2(15),
event_type VARCHAR2(30),
logon_date DATE,
logon_time VARCHAR2(15),
logof_date DATE,
logof_time VARCHAR2(15)
);

Step 3: Write the Database Level logoff system event trigger.

Following Trigger will keep an eye on the logoff activity of the user of the database.
CREATE OR REPLACE TRIGGER db_lgof_audit
BEFORE LOGOFF ON DATABASE
BEGIN
INSERT INTO db_evnt_audit
VALUES(
user,
ora_sysevent,
NULL,
NULL,
SYSDATE,
TO_CHAR(sysdate, 'hh24:mi:ss')
);
END;
/

Code is very similar to the previous one except that this time this trigger will execute for all the users of the
database. This we are making sure by using the keyword DATABASE instead of SCHEMA in the second line of the
trigger unlike the previous trigger.

There can be various ways of taking advantage of these triggers; it depends on your creativity.

21.Startup & Shutdown Database Event Triggers In


Oracle PL/SQL
So far We saw how to create and work with database event Logon and Logoff triggers. Now the only options which
are left are Database event Startup and Shutdown Triggers

Startup Trigger
Startup triggers execute during the startup process of the database. In order to create a database event trigger for
shutdown and startup events we either need to logon to the database as a user with DBA privileges such as sys or we
must possess the ADMINISTER DATABASE TRIGGER system privilege.

Example

Step1: Logon to the database

In order to create a trigger on Startup Database Event first we will have to logon to our database using the user SYS
with DBA privileges.

Step 2: Create a Table

To store the data generated by the execution of trigger we will require a table.

CREATE TABLE startup_audit (


Event_type VARCHAR2(15),
event_date DATE,
event_time VARCHAR2(15)
);

Step 3: Create the database Event Startup Trigger


In this step we will create a trigger which will execute every time the database in which it is created starts up.

CREATE OR REPLACE TRIGGER startup_audit


AFTER STARTUP ON DATABASE
BEGIN
INSERT INTO startup_audit VALUES
(
ora_sysevent,
SYSDATE,
TO_CHAR(sysdate, 'hh24:mm:ss')
);
END;
/

On successful execution this trigger will insert a row of data each time database starts up.

Shutdown Triggers
SHUTDOWN triggers execute before database shutdown processing is performed. Similar to the startup trigger,
only a user with DBA role or ADMINISTER DATABASE TRIGGER system privilege can create a shutdown
trigger.

Example.

First 2 steps of creating a database event shutdown triggers are same as that of the startup trigger which we saw
above.

CREATE OR REPLACE TRIGGER tr_shutdown_audit


BEFORE SHUTDOWN ON DATABASE
BEGIN
INSERT INTO startup_audit VALUES(
ora_sysevent,
SYSDATE,
TO_CHAR(sysdate, 'hh24:mm:ss')
);
END;
/

Table used in this trigger is the same one which we created during the coding of the Startup trigger above.

SHUTDOWN triggers execute only when the database is shut down using NORMAL or IMMEDIATE mode. They
do not execute when the database is shut down using ABORT mode or when the database crashes.

You can also use shutdown database event triggers for gathering your database system statistics. Here is an example

CREATE OR REPLACE TRIGGER before_shutdown


BEFORE SHUTDOWN ON DATABASE
BEGIN
gather_system_stats;
END;
/
22.How To Create Instead-Of Insert Trigger In Oracle
PL/SQL
Instead Of Trigger
Instead-of triggers in oracle database provide a way of modifying views that cannot be modified directly through the
DML statements. By using Instead-of triggers, you can perform Insert, Update, Delete and Merge operations on a
view in oracle database.

Restriction on Instead-of View


Instead-of triggers can control Insert, Delete, Update and Merge operations of the View, not the table. Yes you heard
it right, you can write an instead-of trigger on Views only and not on tables in Oracle database. That is the restriction
that you have to comply with. Along with this you even have to comply with every general restriction that is
imposed on all types of triggers. We have discussed those in the Introduction of triggers section.

Uses of Instead-of trigger.


Since an Instead-of trigger can only be used with views therefore we can use them to make a non-updatable view
updatable as well as to override the default behavior of views that are updatable.

What are Modifiable and Non Modifiable Views?


A view is naturally modifiable if you do not require INSTEAD OF triggers to insert, delete or update data as well as
if it complies to the restrictions discussed herewith. If the view query comprises of any of the mentioned constructs,
then it is not naturally modifiable and therefore you cannot perform inserts, updates, or deletes on the view:

Set operators
Aggregate functions
GROUP BY, CONNECT BY, or START WITH clauses
The DISTINCT operator
Joins (however, some join views are updatable)

In case a view consists of pseudo columns or expressions, then it is only possible to update it with an UPDATE
statement and that also when it does not refer to any such pseudo columns or for that matter, expressions.

Syntax

CREATE [OR REPLACE] TRIGGER trigger_name


INSTEAD OF operation
ON view_name
FOR EACH ROW
BEGIN
---Your SQL Code—
END;
/

If you noticed carefully then you’ll see that we do not have either BEFORE or AFTER clause in the syntax. This is
because unlike other triggers, instead-of trigger executes neither BEFORE nor AFTER but instead of a triggering
event. That is why we do not need to specify either BEFORE or AFTER clause.

Examples
Instead-of Insert Trigger
Instead-of trigger can be best demonstrated using a View joining two or more tables. Thus in this example I will
create two simple tables and will then create a view over them. After that I will create an Instead of trigger for Insert
operation on this view.

Step1: Create Tables


Table 1- trainer

CREATE TABLE trainer(


full_name VARCHAR2(20)
);

Table 2- Subject

CREATE TABLE subject(


subject_name VARCHAR2(15)
);

Insert dummy data into the above tables

INSERT INTO trainer VALUES ('Hussain’);


INSERT INTO subject VALUES ('Oracle');

Step 2: Create View


In this step I will create a view which will show you the combined result of the data from the two tables above.

CREATE VIEW vw_hussain AS


SELECT full_name, subject_name FROM trainer, subject;

This is a non-updatable view which you can confirm by executing any DML statement over it. Error as a result of
DML operation on this view will be your confirmation.

Step 3: Create Trigger

Next I will create an Instead-of Insert trigger over the view vw_rebellionrider that we created in step 2.

CREATE OR REPLACE TRIGGER tr_Io_Insert


INSTEAD OF INSERT ON vw_hussain
FOR EACH ROW
BEGIN
INSERT INTO trainer (full_name) VALUES (:new.full_name);
INSERT INTO subject (subject_name) VALUES (:new.subject_name);
END;
/

On successful execution, this trigger will insert a new row of data into both the underlying tables of the view
vw_rebellionrider. You can confirm that by executing an insert DML over the view.

INSERT INTO vw_hussain(full_name,subject_name) VALUES('HUSSAIN','STEEL');


1 row inserted.
23.Create Instead-Of Update Trigger In Oracle PL/SQL
Instead-Of Update Trigger
Instead-of update trigger will override the default behavior of your update operation when you execute the update
statement and will let you update the data of the underlying tables over which your view is created.

Example:-

Tables (Trainer and Subject) and View (VW_RebellionRider) used in this example are the same as the ones we
created in the previous tutorial.

CREATE OR REPLACE TRIGGER io_update


INSTEAD OF UPDATE ON vw_hussain
FOR EACH ROW
BEGIN
UPDATE trainer SET FULL_NAME = :new.full_name
WHERE FULL_NAME = :old.full_name;
UPDATE subject SET subject_NAME = :new.subject_name
WHERE subject_NAME = :old.subject_name;
END;
/

On successful execution this trigger will let you execute an Update DML on the view.

UPDATE VW_HUSSAIN SET full_name='SHAFI' WHERE full_name ='Manish Sharma';


2 rows updated

24.Create Instead-Of DELETE Trigger In Oracle PL/SQL


Similar to other instead-of triggers which we have seen in previous section, using INSTEAD-OF DELETE we can
override the standard action of Delete DML on a view.

Instead-of Delete trigger Example.


In this example I will again use the View VW_RebellionRider which we created earlier and have consistently used
in this Instead-of trigger series so far.

Needless to say that executing DELETE DML on this view will return an error because of its non-updatable nature.
Thus the only way to perform DELETE DML on this view is by using an Instead of trigger. Let’s quickly create
one.

Set sereveroutput on;


CREATE OR REPLACE TRIGGER io_delete
INSTEAD OF DELETE ON vw_hussain
FOR EACH ROW
BEGIN
DELETE FROM trainer WHERE FULL_NAME = :old.FULL_NAME;
DELETE FROM subject WHERE SUBJECT_NAME= :old.SUBJECT_NAME;
END;
/
On successful execution this trigger will allow you to execute DELETE DML on the view.

DELETE FROM VW_HUSSAIN WHERE full_name ='HUSSAIN';


1 row deleted.
25.PL/SQL Cursors In Oracle Database
In Oracle SQL, a cursor is like a temporary container that holds the result set of a query. It allows you to access and
process the data returned by the query one row at a time. Think of it as a small window that moves through the rows,
showing you one row at a time.

When you execute a SELECT statement, a cursor is created in the background to handle the result set. You can then
use this cursor to fetch each row of data and perform actions on it individually.

Cursors are particularly useful when you need to process data row by row or when you want more control over how
you handle the query results. They help you work with the data in a procedural manner, letting you perform
calculations, apply conditions, and do other operations on each row separately.

In summary, a cursor in Oracle SQL is a tool that allows you to fetch and process data row by row from a query
result, giving you the ability to work with the data in a more controlled and step-by-step manner.

Cursor is a pointer to a memory area called context area. This context area is a memory region inside the
Process Global Area or PGA assigned to hold the information about the processing of a SELECT statement
or DML Statement such as INSERT, DELETE, UPDATE or MERGE.

What is the Context Area?

Let’s dig a little deeper and see what the context area is?

The context area is a special memory region inside the Process Global Area or PGA which helps oracle
server in processing an SQL statement by holding the important information about that statement.

This information includes:

 Rows returned by a query.


 Number of rows processed by a query.
 A pointer to the parsed query in the shared pool.

Using cursor you can control the context area as it is a pointer to the same.

Advantages of Cursors

There are two main advantages of a cursor:

1.Cursor is names thus you can reference it in your program whenever you want.

2.Cursor allows you to fetch and process rows returned by a SELECT statement by a row at a time.

Types of cursors in oracle database


There are two types of cursors in oracle database:

Implicit cursor
Explicit cursor
Implicit Cursors in Oracle Database
As the name suggests these are the cursors which are automatically created by the oracle server every time an SQL
DML statement is executed. User cannot control the behavior of these cursors. Oracle server creates an implicit
cursor in the background for any PL/SQL block which executes an SQL statement as long as an explicit cursor does
not exist for that SQL statement.

Oracle server associates a cursor with every DML statement. Each of the Update & Delete statements has cursors
which are responsible to identify those set of rows that are affected by the operation. Also the implicit cursor fulfills
the need of a place for an Insert statement to receive the data that is to be inserted into the database.

Explicit Cursor in oracle database


In contrast to implicit cursors, we have explicit cursors. Explicit cursors are user defined cursors which means user
has to create these cursors for any statement which returns more than one row of data. Unlike implicit cursor user
has full control of explicit cursor. An explicit cursor can be generated only by naming the cursor in the declaration
section of the PL/SQL block.

Advantages of Explicit Cursor:

1.Since Explicit cursors are user defined hence they give you more programmatic control on your program.

2.Explicit cursors are more efficient as compared to implicit cursors as in latters case it is hard to track data errors.

Steps for creating an Explicit Cursor


To create an explicit cursor you need to follow 4 steps. These 4 steps are:

 Declare
 Open
 Fetch
 Close

In case of implicit cursors oracle server performs all these steps automatically for you.

Steps while working with an explicit cursor


---------------------------------------------------------
.
1.Declare the cursor to initialize in the memory.
2.Open the cursor to allocate memory.
3.Fetch the cursor to retrieve data.
4.Close the cursor to release allocated memory.

1) Declare the cursor: It defines the cursor with a name and the associated SELECT statement.

Syntax: CURSOR name IS SELECT statement;

2) Open the cursor: It is used to allocate memory for the cursor and make it easy to fetch the rows
returned by the SQL statements into it.

Syntax: OPEN cursor_name;

3) Fetch the cursor: It is used to access one row at a time. You can fetch rows from the above-opened
cursor as follows:

Syntax: FETCH cursor_name INTO variable_list;

4) Close the cursor:lt is used to release the allocated memory. The following syntax is used to close the
above-opened cursors.

Syntax: Close cursor_name;

Cursor Attributes
-------------------------------
%FQUND

INTO statement retumned one or more rows, Otherwise it returns FALSE

%NOTFOUND

its return value is TRUE if DML statements like INSERT, DELETE and UPDATE affect no row, or a
SELECT INTO statement retum
no rows. Otherwise it returns FALSE. It is a just opposite of %FOUND

%ISOPEN

always retums FALSE for implicit cursors, because the SQL cursor is automatically closed after
executing its associated SOL
statements.

%ROWCOUNT

It returns the number of rows affected by DML statements like INSERT, DELETE, and UPDATE or
returned by a SELECT INTO

Declare: How To Declare a Database Cursor


Declaring a cursor means initializing a cursor into memory. You define explicit cursor in declaration section of your
PL/SQL block and associate it with the SELECT statement.

Syntax
CURSOR cursor_name IS select_statement;

Open: How to Open a Database Cursor


Whenever oracle server comes across an ‘Open Cursor’ Statement the following four steps take place automatically.

1.All the variables including bind variables in the WHERE clause of a SELECT statement are examined.

2.Based on the values of the variables, the active set is determined, and the PL/SQL engine executes the query for
that cursor. Variables are examined at cursor open time.

3.The PL/SQL engine identifies the active set of data.

4.The active set pointer sets to the first row.

Syntax
OPEN cursor_name;

Fetch: How to retrieve data from cursor


The process of retrieving the data from the cursor is called fetching. Once the cursor is declared and opened then
you can retrieve the data from it. Let’s see how.

Syntax
FETCH cursor_name INTO PL/SQL variable;
Or
FETCH cursor_name INTO PL/SQL record;

What happens when you execute fetch command of a cursor?

1.The use of a FETCH command is to retrieve one row at a time from the active set. This is usually done inside a
loop. The values of each row in the active set can then be stored in the corresponding variables or PL/SQL record
one at a time, performing operations on each one successively.

2.After completion of each FETCH, the active set pointer is moved forward to the next row. Therefore, each FETCH
returns successive rows of the active set, until the entire set is returned. The last FETCH does not assign values to
the output variables as they still contain their previous values.

Close: How To Close a Database Cursor?


Once you are done working with your cursor it’s advisable to close it. As soon as the server comes across the
closing statement of a cursor it will relinquish all the resources associated with it.

Syntax
CLOSE cursor_name;
Basic Programming Structure of the Cursor
Here is the basic programming structure of the cursor in oracle database.

DECLARE
CURSOR cursor_name IS select_statement;
BEGIN
OPEN cursor_name;
FETCH cursor_name INTO PL/SQL variable [PL/SQL record];
CLOSE cursor_name;
END;
/

Cursor Attributes
Oracle provides four attributes which work in correlation with cursors. These attributes are:

 %FOUND
 %NOTFOUND
 %ISOPEN
 %ROWCOUNT

First three attributes ‘Found’, ‘NotFound’ and ‘IsOpen’ are Boolean attributes whereas the last one
‘RowCount’ is a numeric attribute.

Let’s quickly take a look at all these attributes.

%Found
Cursor attribute ‘Found’ is a Boolean attribute which returns TRUE if the previous FETCH command returned
a row otherwise it returns FALSE.

%NotFound
‘Not Found’ cursor attribute is also a Boolean attribute which returns TRUE only when previous FETCH
command of the cursor did not return a row otherwise this attribute will return FALSE.

%IsOpen
Again ‘Is Open’ Cursor attribute is a Boolean attribute which you can use to check whether your cursor is open
or not. It returns TRUE if the cursor is open otherwise it returns FALSE.

%RowCount
Row count cursor attribute is a numeric attribute which means it returns a numeric value as a result and that
value will be the number of records fetched from a cursor at that point in time.
26.How To Create An Explicit Cursor In Oracle Database
As we have already learnt that whenever we execute a DML statement, the oracle server creates an implicit cursor in
the background. As these cursors are created by oracle server itself thus user does not have much programmatic
control on them. In case if you want to control your own DMLs then you need to write an explicit cursor.

So let’s quickly see how you can create your own database cursor in oracle database.

SET SERVEROUTPUT ON;


DECLARE
V_NAME VARCHAR2(30);
CURSOR CUR_HUSSAIN IS
SELECT FIRST_NAME FROM HR.EMPLOYEES WHERE EMPLOYEE_ID <105;
BEGIN
OPEN CUR_HUSSAIN;
LOOP
FETCH CUR_HUSSAIN INTO V_NAME;
DBMS_OUTPUT.PUT_LINE(V_NAME);
EXIT WHEN CUR_HUSSAIN%NOTFOUND;
END LOOP;
CLOSE CUR_HUSSAIN;
END;
/

Steven
Neena
Lex
Alexander
Bruce
Bruce

PL/SQL procedure successfully completed.

We used EMPLOYEE table of HR sample Schema for creating the above explicit cursor.Declaration of your cursor
can only be done in the “Declaration” section of the PL/SQL block and the rest of the steps of explicit cursor
creation cycle must be done in the execution section of a PL/SQL block.

27.How To Create Cursor Parameter In Oracle Database


What is Parameterized cursor?
Unlike simple explicit cursor, parameterized cursors accept values as parameter. You specify the list of parameters
separated by comma (,) while declaring the cursor and supply the corresponding argument for each parameter in the
list while opening the cursor.

Definition:
Cursor parameter can be appropriately defined as an explicit cursor that accepts arguments from the user in
the form of parameter.

Syntax of Parameterized Cursor in Oracle Database

CURSOR cur _ name (parameter list) IS SELECT statement;

Syntax of declaring a cursor parameter is pretty similar to that of the simple cursor except the addition of
parameters enclosed in the parenthesis.
OPEN cur _ name (argument list)

You have to provide corresponding arguments for each parameter that are specified during the declaration. Rest
of the steps are the same as that of the simple cursor.

There are few things which you have to take care of while specifying the parameters in your explicit
cursor.

1.In case of multiple parameters, always separate parameters and the corresponding arguments in the list from
each other using comma (,).

2.You can specify as many parameters as you need just make sure to include an argument in parameter list for
each parameter when you open the cursor.

3.While specifying a parameter during the declaration of the explicit cursor only specify the data type not the
data width.

Some Wonderful Advantages of Parameterized Cursors

Makes the cursor more reusable


You can use a parameter and then pass different values to the WHERE clause each time a cursor is opened
instead of hardcoding a value into the WHERE clause of a query to select particular information.

Avoids scoping problems


When you pass parameters instead of hardcoding the values, the result set for that cursor is not tied to a specific
variable in a program or block. Therefore in case your program has nested blocks, you can define the cursor at
a higher-level (enclosing) block and use it in any of the sub-blocks with variables defined in those local blocks.

When do we need a parameterized cursor?


You must be wondering when we need a cursor with parameters in our PL/SQL.

The simplest answer is whenever you need to use your cursor in more than one place with different values for
the same WHERE clause of your SELECT statement.

Example of Parameterized cursor


SET SERVEROUTPUT ON;
DECLARE
VAR_FNAME VARCHAR2(30);
CURSOR CUR_EMP(EMP_ID NUMBER) IS
SELECT FIRST_NAME FROM HR.EMPLOYEES WHERE EMPLOYEE_ID<EMP_ID;
BEGIN
OPEN CUR_EMP(110);
LOOP
FETCH CUR_EMP INTO VAR_FNAME;
DBMS_OUTPUT.PUT_LINE(VAR_FNAME);
EXIT WHEN CUR_EMP%NOTFOUND;
END LOOP;
CLOSE CUR_EMP;
END;
/

Steven
Neena
Lex
Alexander
Bruce
David
Valli
Diana
Nancy
Daniel
Daniel

PL/SQL procedure successfully completed.

28.How To Create Cursor Parameter With Default Value


In Oracle Database
In Previous section we learnt that in PL/SQL we are allowed to create a cursor with parameter known as
Cursor Parameter (a.k.a. Parameterized Cursor). Every cursor parameter has some restrictions which we have
to comply with for example we have to specify the argument for each parameter when we open the cursor
otherwise we get a PLS 00306 error.

To overcome this restriction, we have the option called default value. Default value is the value which you
assign to the parameter of your cursor during the declaration of the cursor.

Example 1 of Cursor Parameter with Default Value


SET SERVEROUTPUT ON;
DECLARE
VAR_NAME VARCHAR2(50);
VAR_EMP_ID NUMBER(10);
CURSOR CUR_NAME_ID(CUR_VAR_EMP_ID NUMBER :=190) IS
SELECT FIRST_NAME,EMPLOYEE_ID FROM HR.employees WHERE EMPLOYEE_ID
>CUR_VAR_EMP_ID;
BEGIN
OPEN CUR_NAME_ID;
LOOP
FETCH CUR_NAME_ID INTO VAR_NAME,VAR_EMP_ID;
EXIT WHEN CUR_NAME_ID%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(VAR_NAME ||' '||VAR_EMP_ID);
END LOOP;
CLOSE CUR_NAME_ID;
END;
/

Randall 191
Sarah 192
Britney 193
Samuel 194
Vance 195
Alana 196
Kevin 197
Donald 198
Douglas 199
Jennifer 200
Michael 201
Pat 202
Susan 203
Hermann 204
Shelley 205
William 206

PL/SQL procedure successfully completed.

As you can see in the above code I assigned a value (which is 190) using assignment operator to the parameter
CUR_VAR_EMP_ID in the cursor declaration and nothing while opening the cursor. Upon the execution this
PL/SQL block will show you the first name and employee id of all the employees who have employee id
greater than 190.

Default Value Is Not a Substitute Value


Default value is not a substitute value for the parameter of your cursor. It comes into action only when the user
does not specify the argument for the parameter while opening the cursor. In case user has supplied the
argument for the parameter in OPEN CURSOR statement then the compiler will show the result according to
that parameter and not according to the Default value.

Example 2 of Cursor Parameter with Default Value

SET SERVEROUTPUT ON;


DECLARE
VAR_NAME VARCHAR2(50);
VAR_EMP_ID NUMBER(10);
CURSOR CUR_NAME_ID(CUR_VAR_EMP_ID NUMBER :=190) IS
SELECT FIRST_NAME,EMPLOYEE_ID FROM HR.employees WHERE EMPLOYEE_ID
>CUR_VAR_EMP_ID;
BEGIN
OPEN CUR_NAME_ID(200);
LOOP
FETCH CUR_NAME_ID INTO VAR_NAME,VAR_EMP_ID;
EXIT WHEN CUR_NAME_ID%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(VAR_NAME ||' '||VAR_EMP_ID);
END LOOP;
CLOSE CUR_NAME_ID;
END;
/
Michael 201
Pat 202
Susan 203
Hermann 204
Shelley 205
William 206

PL/SQL procedure successfully completed.

If you compare the result of both the codes demonstrated in the above examples you will see the difference
because the result returned by Example 1 is according to the default value (which is 190) which you specified
during the declaration while the result returned by Example 2 will be according to the argument (which is 200)
you have specified in the OPEN cursor statement.

Use of Default Value in Cursor Parameter


Specifying the default value for the parameter of your cursor can increase the efficiency of your app or code by
minimizing the chances of PLS 00306 error.

29.Cursor For Loop With Simple Explicit Cursor In


Oracle Database
As the name suggests Cursor For Loop is a type of For loop provided by oracle PL/SQL which makes working
with cursors in oracle database a lot easier by executing OPEN, FETCH & CLOSE Cursor statements
implicitly in the background for you.

Definition:
Cursor for Loop Is an Extension of the Numeric For Loop provided by Oracle PL/SQL which works on
specified cursors and performs OPEN, FETCH & CLOSE cursor statements implicitly in

Syntax of Cursor For Loop.


FOR loop_index IN cursor_name
LOOP
Statements…
where END LOOP;

where loop index is a row type record variable which will hold the data return by the cursor

Example 1: Cursor For Loop With Simple Explicit Cursor

SET SERVEROUTPUT ON;


DECLARE
CURSOR CUR_FULL_NAME IS
SELECT FIRST_NAME,LAST_NAME FROM HR.employees WHERE EMPLOYEE_ID >200;
BEGIN
FOR LOOP_INDEX IN CUR_FULL_NAME
LOOP
DBMS_OUTPUT.PUT_LINE(LOOP_INDEX.first_name||' '||LOOP_INDEX.last_name);
END LOOP;
END;
/
Example 2: Cursor For Loop With Inline Cursor
You can pass the cursor definition directly into the Cursor For Loop. The code for that is:

SET SERVEROUTPUT ON;


BEGIN
FOR LOOP_INDEX IN (SELECT FIRST_NAME,LAST_NAME FROM HR.employees WHERE
EMPLOYEE_ID >200)
LOOP
DBMS_OUTPUT.PUT_LINE(LOOP_INDEX.first_name||' '||LOOP_INDEX.last_name);
END LOOP;
END;
/

Michael Hartstein
Pat Fay
Susan Mavris
Hermann Baer
Shelley Higgins
William Gietz

PL/SQL procedure successfully completed.

As you can see in the above code, instead of declaring a cursor into a separate declaration section of PL/SQL
block we can write the Cursor’s SELECT DML statement right inside the loop statement after IN keyword.

Just remember:

1. Directly write the SELECT statement without specifying the cursor name into the loop statement.
2. Enclose the SELECT statement into parenthesis.
3. Do not terminate the SELECT statement with a semicolon (;)

How many times will Cursor For Loop execute?


Unlike Numeric For Loop with Cursor For Loop we don’t have minimum or maximum range which will decide
the number of execution. So how many times will this loop execute?

This loop will execute for each row returned by the specified cursor and it will terminate either when there is
no row to return or there is an occurrence of an exception.

30.Cursor For Loop With Parameterized Explicit Cursor


In Oracle Database
Using cursor for loop, working with parameterized cursor is as easy as working with simple explicit cursor.
Checkout the example given below.

SET SERVEROUTPUT ON;


DECLARE
CURSOR CUR_FULL_NAME(VAR_EMP_ID NUMBER)IS
SELECT FIRST_NAME,LAST_NAME FROM HR.EMPLOYEES WHERE
EMPLOYEE_ID>VAR_EMP_ID;
BEGIN
FOR LOOP_INDEX IN CUR_FULL_NAME(200)
LOOP
DBMS_OUTPUT.PUT_LINE(LOOP_INDEX.first_name||' '||LOOP_INDEX.last_name);
END LOOP;
END;
/

OR
SET SERVEROUTPUT ON;
DECLARE
CURSOR CUR_FULL_NAME(VAR_EMP_ID NUMBER :=200)IS
SELECT FIRST_NAME,LAST_NAME FROM HR.EMPLOYEES WHERE
EMPLOYEE_ID>VAR_EMP_ID;
BEGIN
FOR LOOP_INDEX IN CUR_FULL_NAME
LOOP
DBMS_OUTPUT.PUT_LINE(LOOP_INDEX.first_name||' '||LOOP_INDEX.last_name);
END LOOP;
END;
/

Michael Hartstein
Pat Fay
Susan Mavris
Hermann Baer
Shelley Higgins
William Gietz

PL/SQL procedure successfully completed.

You can pass the values for the parameters of your cursor just by simply writing the argument right after the
name of your cursor in loop statement as shown in the above example (Statement In bold). Always remember
to enclose the arguments inside the parenthesis.

31.Introduction To Record Datatypes In Oracle Database


What is a Record in Oracle Database?
Records are composite data structures made up of different components called fields. These fields can have
different data types. This means that you can store data of different data types in a single record variable.
Similar to the way we define columns in a row of a table.

Definition:-
A record is a group of related data items stored in fields, each with its own name and datatype.

Types of Record datatype in Oracle database


In Oracle PL/SQL we have three types of Record datatype.

1. Table Based Record


2. Cursor Based Record, and
3. User Defined Record.
How to declare a Record Datatype in Oracle Database. (%ROWTYPE
attribute.)
Similar to %TYPE which is for declaring an anchored datatype variable, Oracle PL/SQL provides us an
attribute % ROWTYPE for declaring a variable with record datatype.

Syntax of Record Datatype

 Table Based Record

Variable_ name table_name%ROWTYPE;

Variable Name: A user defined name given to the variable. You have to specify the name of the variable
which could be anything. But you have to follow the oracle guidelines for variable name.

Table Name: Table name will be the name of the table over which the record datatype is created. This table
will serve as the base table for the record. Also the Oracle Server will then create corresponding fields in the
record that will have the same name as that of a column in the table.

%ROWTYPE: Attribute which indicates the compiler that the variable which is declared is of Record Type.

 Cursor based Record

Variable_ name cursor_name%ROWTYPE;

The syntax of cursor based record is pretty similar to the one which we just saw. You just have to specify the
name of the cursor in place of table name, rest of the things remain same.

How to access data stored is Record Type Variable.


Whenever you create a record based on a table, oracle server will create fields corresponding to each column of
the table and all those fields have the same name as a column in the table. That makes referencing or accessing
data from the record much easier. Here is how you access data from record variable.

Record_variable_name.column_name_of_the_table;

Using dot (.) notation you can access the data stored into the field of the record.
32. What Are Table Based Record Datatypes In Oracle
Database
In the previous section we saw that the record datatype variables are composite data structures made up of
different components called fields that have the same name and data types as that of the columns of a table
using which you created that record. There we saw that there are three types of record variables available in
Oracle Database. In this section we will concentrate on the first type of record variable which is “ Table Based
Record Datatypes” Variables

What are Table Based Record Datatype Variables?


As the name suggests Table Based Record Datatype Variables are variable of record datatype created over a
table of your database.

Whenever you declare a record type variable oracle engine will declare a composite data structure with fields
corresponding to each column of the specified table. For example if we have a record variable created using
Employees table then that variable has 11 fields corresponding to 11 columns of the employees table. Also all
these fields have the same name, data type and data width as that of the columns of the table.

How to Declare a Table Based Record Datatype Variables in Oracle


Database?
The declaration of a table based record datatype variables is very similar to the declaration of simple user
variables.

For example

SET SERVEROUTPUT ON;


DECLARE
v_emp employees%ROWTYPE;

That is the declaration section of an anonymous PL/SQL block where we declared a record type variable with
the name v_emp. V_emp record variable is based on employees table of the HR sample user. As this record
variable is based on “employee” table of HR sample user thus it will have 11 fields corresponding to the 11
columns of the employees table.

How to Initialize Record Datatype Variables in Oracle Database?


In Oracle Database a record data type variable can be initialized by multiple ways similar to the simple user
variables which we have seen in PL/SQL tutorial 2. However in this tutorial we will focus on the three most
common ways of initializing a Record type variable. These are:

1. By fetching data from all the columns of a row of a table into the record variable using SELECT-INTO
statement.
2. By fetching data from selected columns of the table into the record variable using SELECT-INTO statement.
3. By directly assigning the value into the record variable using assignment operator.
We will discuss each of the above ways of initializing a record data type variable one tutorial at a time. In this
tutorial we will focus on the first way of initializing database records which is by Fetching data from all the
columns of a row of a table.

Initialize Record Variable by Fetching Data from All the Columns


(SELECT-INTO Statement)
We already know that whenever you declare a record type variable oracle engine will declare a composite data
structure with fields corresponding to each column of the specified table. We can initialize all these fields by
fetching the data from all the columns of a row of the table using SELECT-INTO statement.

SELECT * INTO v_emp FROM employees


WHERE employee_id = 100;

As we are talking about fetching data from all the columns thus we are using the SELECT * statement and
storing the data into our record variable V_EMP.

NOTE
Take a note here that a table based record variable can hold data of a single row at a time, thus you have to
make sure that the SELECT-INTO statement returns the data from one row only and for that you can filter the
data using WHERE clause, as we did in the above statement.

How to access data from the record datatype variables in Oracle


Database?
In order to access the data stored into a record variable we use the dot notation. In which we first write the
name of our record variable followed by a dot and then the name of the field (or the name of the column) as
both fields of a Table based Record Type variable and the column of the table over which the record variable is
declared share the same name whose data we want to retrieve.

DBMS_OUTPUT.PUT_LINE (v_emp.first_name ||' '||v_emp.salary);

Example: Table based record type variable initialization with SELECT


asterisk (*) statement.
SET SERVEROUTPUT ON;
DECLARE
v_emp employees%ROWTYPE;
BEGIN
SELECT * INTO v_emp FROM employees
WHERE employee_id = 100;
DBMS_OUTPUT.PUT_LINE (v_emp.first_name ||' '||v_emp.salary);
DBMS_OUTPUT.PUT_LINE(v_emp.hire_date);
END;
/
EXAMPLE 2
SET SERVEROUTPUT ON;
DECLARE
V_VAR HR.EMPLOYEES%ROWTYPE;
BEGIN
SELECT * INTO V_VAR FROM HR.EMPLOYEES WHERE EMPLOYEE_ID =105;
DBMS_OUTPUT.PUT_LINE('FULL NAME OF THE EMPLOYEE = '||V_VAR.FIRST_NAME||' '||
V_VAR.LAST_NAME);
DBMS_OUTPUT.PUT_LINE('SALARY = '||V_VAR.SALARY);
DBMS_OUTPUT.PUT_LINE('HIRE DATE = '||V_VAR.HIRE_DATE);
END;
/

FULL NAME OF THE EMPLOYEE = David Austin


SALARY = 4800
HIRE DATE = 25-JUN-05

PL/SQL procedure successfully completed.

33.How to Initialize Table Based Record Type Variables


In Oracle Database
In the previous section we saw, how to initialize a record variable by fetching data from all the columns of a
table using SELECT-INTO statement. But what if we want to fetch the data from selected columns of a table?
Can we still use the same process for initializing the record variable?

The answer is No, we cannot use the same process shown in the previous tutorial for initializing a record datatype
variable by fetching data from select columns of a table. The execution of the following example where we are using
the data from one column “First Name” of the “Employees” table for initializing the record datatype variable
“v_emp” will return an error.

SET SERVEROUTPUT ON;


DECLARE
V_VAR HR.EMPLOYEES%ROWTYPE;
BEGIN
SELECT first_name,last_name INTO V_VAR FROM HR.EMPLOYEES WHERE
EMPLOYEE_ID =105;
DBMS_OUTPUT.PUT_LINE('FULL NAME OF THE EMPLOYEE = '||V_VAR.FIRST_NAME||' '||
V_VAR.LAST_NAME);
END;
/

Error report -
ORA-06550: line 4, column 40:
PL/SQL: ORA-00913: too many values
ORA-06550: line 4, column 1:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:

That error is “PL/SQL: ORA-00913: too many values” So what does this error means? Why is it saying “too many
values” even when we are fetching only one data. I know sometimes PL/SQL error can be deceptive and confusing.
In order to find out the solution of this problem and understand this error we have to recall what we learnt in the
previous tutorial. There we learnt that Database Records are composite data structures made up of multiple fields
which share same name, datatype and data width as that of the columns of the table over which it is created. And the
data which was fetched gets stored into these fields.

In case of initializing a record variable by fetching data from all the columns of a table, we don’t have to do
anything, oracle engine does all the dirty work in the background for you. It first fetches the data from the table and
then stores that data into the corresponding field into the record which has the same data type and data width, and
for that matter also shares the same name.

But when it comes to initializing a record datatype variable by fetching the data from selected columns we have to
do all this work manually. We have to specify the name of the column from which we want to fetch the data and
then we have to specify the name of the field where we want to store that data.

In the above example we did specify the column name of the table whose data we want to fetch but we didn’t
specify the name of the record’s field where we want to store the fetched data. That confuses the compiler on where
to store the data which ultimately causes the error.

How to Solve “PL/SQL ORA-00913: Too Many Values” Error?


The PL/SQL ORA-00913 error can easily be solved by specifying the record’s field name where you want the
fetched data to be stored. But here you have to be a bit careful. You have to make sure that the field’s datatype and
data width must match with the datatype and data width of the column whose data you have fetched.

Now the question here is that how to specify the record data type field’s name? We can specify the name of the field
of the record variable using Dot (.) notation where we first write the name of the already declared record variable
followed by a dot (.) and the name of the field. And luckily both the columns of the table and fields of the record
share the same name.

So now that we have learnt why we are having PL/SQL ORA-00913 error on initializing the record data type
variable using data from select columns. Let’s modify the above example accordingly and try to resolve it.
Example : Initialize the Record Datatype variable using data from
Multiple Columns.
SET SERVEROUTPUT ON;
DECLARE
V_VAR HR.EMPLOYEES%ROWTYPE;
BEGIN
SELECT first_name,last_name INTO V_VAR.first_name,V_VAR.last_name FROM
HR.EMPLOYEES WHERE EMPLOYEE_ID =105;
DBMS_OUTPUT.PUT_LINE('FULL NAME OF THE EMPLOYEE = '||V_VAR.FIRST_NAME||' '||
V_VAR.LAST_NAME);
END;
/

FULL NAME OF THE EMPLOYEE = David Austin

PL/SQL procedure successfully completed.

34.How to Create Cursor Based Record Datatype


Variables In Oracle Database
What are Cursor Based Records in Oracle Database?
Cursor based records are those variables whose structure is derived from the SELECT list of an already created
cursor. As we know that record datatypes are composite data structures made up of multiple fields and in the case of
Cursor based record these fields are initialized by fetching data from the SELECT-LIST of the cursor that was used
to create this variable.

How To Create Cursor Based Record In Oracle Database?


The creation of cursor based record variable involves:

1.Declaration of Cursor based Record.


2.Initialization of Cursor Based Record and
3.Accessing the data stored into the cursor based record variable.

Let’s discuss each of these above steps one by one.

1.Declare Cursor Based Record In Oracle Database


As it is obvious that in order to declare a Cursor Based Record we need to have a Cursor over which we can design
our Record variable. For the demonstration let’s have the same cursor which we have discussed in PL/SQL cursors
sections on “How to Create Simple Explicit Cursor.”

SET SERVEROUTPUT ON;


DECLARE
CURSOR CUR_HUSSAIN IS
SELECT FIRST_NAME, LAST_NAME FROM HR.EMPLOYEES WHERE EMPLOYEE_ID
=100;

Once you have created your cursor then you are all set to declare your Cursor based Record variable.
VAR_EMP CUR_HUSSAIN %ROWTYPE;

Declaration of Cursor Based Record is pretty much similar to the declaration of table based record. The declaration
starts with the name of the record variable, which is completely user defined followed by the name of an already
created cursor. And at the end “%ROWTYPE” attribute which indicates that we are declaring a Record Datatype
variable to the compiler.

2.Initialize Cursor Based Record Datatype


Once you have successfully declared your record datatype variable next you have to initialize it and by that I mean
putting some value into the record variable. Though the initializing process of cursor based record is very simple and
pretty much similar to the one we have seen in the previous tutorial on “Table Based Record” but unlike table
records here we are initializing a record variable which is based on a cursor thus we have to make sure that we
should follow the cursor cycle properly.

BEGIN
OPEN CUR_HUSSAIN;
FETCH CUR_HUSSAIN INTO VAR_EMP;

Every cursor needs to be opened before being used. Thus here we first opened the cursor and then using FETCH-
INTO statement we fetched the data into the record variable “var_emp”.

3.Access data from the cursor based record


After Declaration and Initialization of cursor based record the thing which we have to learn is How to access data
from the cursor based record.

DBMS_OUTPUT.PUT_LINE (VAR_EMP.FIRST_NAME);
DBMS_OUTPUT.PUT_LINE (VAR_EMP.SALARY);

You can see in the above two statements that once again we used the Dot (.) notation for fetching the data from the
record variable. Though these two statements look very similar to one which we have seen in table based record
variable tutorial, but they are not. In case of table based record we have to write the name of the column of the table
but in case of cursor based record we can only write the name of those columns of the table which we specified in
the SELECT-List of the cursor.

Once you have declared, initialize and access the data then make sure to close the cursor.

Now let’s compile all the above line of codes (LOCs) together and make them into a single PL/SQL block.

SET SERVEROUTPUT ON;


DECLARE
CURSOR CUR_HUSSAIN IS
SELECT FIRST_NAME, LAST_NAME FROM HR.EMPLOYEES WHERE EMPLOYEE_ID
=105;
VAR_EMP CUR_HUSSAIN%ROWTYPE;
BEGIN
OPEN CUR_HUSSAIN;
FETCH CUR_HUSSAIN INTO VAR_EMP;
DBMS_OUTPUT.PUT_LINE (VAR_EMP.FIRST_NAME);
DBMS_OUTPUT.PUT_LINE (VAR_EMP.LAST_NAME);
CLOSE CUR_HUSSAIN;
END;
/

David
Austin

PL/SQL procedure successfully completed.

In PL/SQL, you cannot declare a cursor-based record variable before declaring the cursor itself. The
cursor definition must appear before you declare a record variable based on it.
35.Cursor Based Record Datatype With Cursor Returning
Multiple Values In Oracle Database
We have already seen in the previous section how to create Cursor based Record Type Variable based on Simple
Cursor which returns a single row of data. Now the question arises here is that can we use the same single record
datatype variable with the cursor which returns multiple rows of data?. Lets see to handle multiple values returned
by a cursor using single cursor based record datatype variable

Step 1: Declare a Simple Explicit Cursor


A Cursor-based record datatype requires an already created cursor. This cursor will become an underlying base for
our record type variable. All the fields of the record type variable which is created using this cursor will have the
same name and datatype as that of the columns used in the SELECT-List of the cursor.

SET SERVEROUTPUT ON;


DECLARE
CURSOR cur_hussain IS
SELECT first_name, salary FROM hr.employees
WHERE employee_id > 200;

Unlike the cursor from the previous tutorial which is returning a single row of data, this cursor will return multiple
rows. All these rows will consist of the first name and salary of all the employees with employee id greater than 200.

Step2: Declare the Cursor Based Record Datatype Variable


As we have created the cursor, now we are all set to declare our record variable using this cursor.

var_emp cur_hussain%rowtype;

Var_emp is the record type variable and as it is based on the cursor cur_hussain thus we can proudly call it a Cursor-
Based record type variable. Now we have to see whether this single record variable is capable of holding all the data
returned by the underlying cursor cur_hussain

Step 3: Initialize the Cursor-Record Variable


As we discussed in the PL/SQL previous section that is initialization of a record variable is the process of assigning
some values to it. In case of Cursors, FETCH-INTO statement does this work. But we have to make sure that we
have followed the Cursor Life Cycle properly.

begin
open cur_hussain ;
loop
fetch cur_hussain into var_emp;
exit when cur_hussain%notfound;
dbms_output.put_line(var_emp.first_name||' '||var_emp.salary);
end loop;
close cur_hussain;
end;
/

So that is it. That’s all we have to. Now let’s combine all these chunks of code which we saw in different steps
above into a single anonymous PL/SQL block.

SET SERVEROUTPUT ON;


DECLARE
CURSOR cur_hussain IS
SELECT first_name, salary FROM hr.employees
WHERE employee_id > 200;
var_emp cur_hussain%rowtype;
begin
open cur_hussain ;
loop
fetch cur_hussain into var_emp;
exit when cur_hussain%notfound;
dbms_output.put_line(var_emp.first_name||' '||var_emp.salary);
end loop;
close cur_hussain;
end;
/

Michael 13000
Pat 6000
Susan 6500
Hermann 10000
Shelley 12008
William 8300

PL/SQL procedure successfully completed.

When you compile and run the above code you will get all the data which FETCH-INTO statement fetched from the
cursor cur_hussain and stored into the Cursor-based Record variable var_emp. This implies that we can indeed
handle multiple rows of data using a single Cursor Based Record.

Here is the code done using Cursor For-Loop which is equivalent to the above code. As you can see it
is much less complex with few Line-of-Codes (LOCs).

SET SERVEROUTPUT ON;


DECLARE
CURSOR cur_hussain IS
SELECT first_name, salary FROM hr.employees
WHERE employee_id > 200;
var_emp cur_hussain%rowtype;
begin
for var_emp in cur_hussain
loop
dbms_output.put_line(var_emp.first_name||' '||var_emp.salary);
end loop;
end;
/

Michael 13000
Pat 6000
Susan 6500
Hermann 10000
Shelley 12008
William 8300

PL/SQL procedure successfully completed.


36.How To Create User defined Record Datatype Variable
In Oracle Database
As the name suggests, user define records are the record variables whose structure is defined by the user, which is
unlike the table based or cursor based records whose structures are derived from their respective tables or cursor.
This means that with user define records you can have complete control over the structure of your record variable.

The creation process of user define record variable is divided into two parts. Before defining the record we first need
to define the TYPE for the record variable. This TYPE will become the base of the User Define Record variable and
will help in driving its structure. Once the TYPE is successfully declared then we can use it for creating our user
define record variable.

Syntax of User Define Records in Oracle Database

Below is the syntax for creating the TYPE for User Defined Record Datatype Variable.

TYPE type_name IS RECORD (


field_name1 datatype 1,
field_name2 datatype 2,
...
field_nameN datatype N
);

Once we have our TYPE declared we are all set to create our Record Variable. This variable will then acquire all the
properties of the type using which it is created. And here is the syntax for creating the user define record datatype
variable.

record_name TYPE_NAME;

Did you notice that unlike the Table based or Cursor Based Record Variable we do not have to use %ROWTYPE
attribute here for declaring the record variable because we are deriving it from user defined record

Example: How To Create User Defined Record Datatype Variable.

Step 1: Declare Type for the User Defined Record Variable


SET SERVEROUTPUT ON;
DECLARE
TYPE emp_dept IS RECORD(
f_name VARCHAR2(20),
d_name hr.departments.department_name%type
);

Step 2: Declare User Define Record Variable


After creating the TYPE you are all set to create your User Defined Record Variable.

var_ur emp_dept;

This above PL/SQL statement will create a record variable with the name var_ur.

Step 3: Initialize the User Defined Record Variable.


User defined record variable can be initialized in multiple ways. For instance you can initialize the record variable
directly by assigning value to it using assignment variable or you can fetch the values stored into the column of a
table using SELECT-INTO statement. So let’s move ahead with our example and learn how to initialize a user
defined record variable using SELECT-INTO statement.

Next we will write the execution section. In the execution section we will have a SELECT statement which will be
joining employees table and departments table and returning the first name and department name of the specific
employee.

BEGIN
SELECT first_name , department_name
INTO var_ur.f_name, var_ur.d_name
FROM hr.employees join hr.departments
Using (department_id) WHERE employee_id = 100;

DBMS_OUTPUT.PUT_LINE('name of the employee is '||var_ur.f_name||'and he beongs to '||


var_ur.d_name||' '||'department');
END;
/

The select statement which we have here will return the first name and the department name of the employee whose
employee id is 100. The data for both the columns are coming from different tables thus we used a JOIN here. As
there are two different tables involved in the query thus in such a situation use of Table Based Record Variable is
not possible therefore the viable solution is the user define record variable.

Let’s join all the above chunks of codes together into a single anonymous PL/SQL block.

SET SERVEROUTPUT ON;


DECLARE
TYPE emp_dept IS RECORD(
f_name VARCHAR2(20),
d_name hr.departments.department_name%type
);
var_ur emp_dept;
BEGIN
SELECT first_name , department_name
INTO var_ur.f_name, var_ur.d_name
FROM hr.employees join hr.departments
Using (department_id) WHERE employee_id = 100;

DBMS_OUTPUT.PUT_LINE('Name of the employee is '||var_ur.f_name||'and he beongs to '||


var_ur.d_name||' '||'department');
END;
/

Name of the employee is Stevenand he beongs to Executive department

PL/SQL procedure successfully completed.

That is how we create a User Defined Record Datatype Variable in Oracle Database.

37.Introduction To PL/SQL Functions In Oracle Database


What are PL/SQL functions in Oracle Database?
In Oracle Database we can define a PL/SQL function as a self-contained sub-program that is meant to do some
specific well defined task. Functions are named PL/SQL block which means they can be stored into the database as a
database object and can be reused. That is also the reason why some books refer to PL/SQL functions as stored
functions.
PL/SQL functions

PL/SQL functions are code blocks within Oracle Database used to compute and return a single value. They
accept parameters, process data, and encapsulate logic for reuse. Functions are invoked from SQL, other
PL/SQL code, or applications, enhancing modularity and performance. While limited to returning a value, they
contribute to efficient and organized database-driven applications.

Types of PL/SQL functions in Oracle Database

There are two types of PL/SQL functions in Oracle Database, these are

1.Pass-by-Value Functions

Behavior: In pass-by-value functions, the values of the actual parameters (arguments) are copied into the
function's parameters. This means that any changes made to the parameters within the function do not affect the
original values outside the function.

Purpose: These functions are commonly used for calculations and operations where you don't want the original
values to change.

Example:

FUNCTION pass_by_value_example(a NUMBER) RETURN NUMBER IS


b NUMBER := a;
BEGIN
b := b + 1; -- Changing 'b' doesn't affect 'a'
RETURN b;
END;

2.Pass-by-Reference functions

Behavior: In pass-by-reference functions, the function receives a reference (memory address) to the original
variables as parameters. Any changes made to the parameters within the function are reflected in the original
variables.

Purpose: These functions are used when you want to modify the original values or when you need to return
multiple values from the function.

Example:

FUNCTION pass_by_reference_example(a IN OUT NUMBER) RETURN NUMBER IS


BEGIN
a := a + 1; -- Changing 'a' affects the original variable
RETURN a;
END;

In both types of functions, the goal is to encapsulate logic for reusability, but they handle parameter values
differently. By default, PL/SQL uses pass-by-value, which means that modifications within the function do not
affect the original values. However, if you want modifications to affect the original values, you need to use pass-by-
reference, often indicated using the IN OUT or OUT keywords.

When choosing between these types, consider the nature of the data you're working with and the desired behavior of
the function. Pass-by-value functions are useful when you want to maintain the immutability of the original values,
while pass-by-reference functions are suitable for cases where you need to modify those values directly.

In Oracle Database both types of functions should have to return some values and these values should be a
valid SQL or PL/SQL datatype.
Syntax of PL/SQL Functions in Oracle Database

CREATE [OR REPLACE] FUNCTION function_name


(Parameter 1, Parameter 2…)
RETURN datatype
IS
Declare variable, constant etc.
BEGIN
Executable Statements
Return (Return Value);
END;

Function Execution Method

Depending on your creativity and programming skills, a PL/SQL function can be called by multiple ways. Here are
some general ways of calling a PL/SQL function in Oracle Database

>You can use SQL*Plus utility of the Oracle Database to invoke a PL/SQL function that can be called from PL/SQL
as procedural statement.

>An anonymous PL/SQL block can also be used to call a function.

>You can even call a function directly into a SELECT or DML statement.

38.How To Create PL/SQL Function In Oracle Database


The function body is divided into two parts

1.First is the header of the PL/SQL function and


2.Second is the execution part of the PL/SQL function

Step 1. Create the Header of a PL/SQL Function.

The header consists of the signature of the function or the declaration of the PL/SQL function.

--Function Header

CREATE OR REPLACE FUNCTION circle_area (radius NUMBER)


RETURN NUMBER IS

Step 2. Declare Variables or the Constant


If your program requires you to declare any variable or constant or anything then you can do it right after creating
the header, that too without using the DECLARE keyword.

--Declare a constant and a variable


pi CONSTANT NUMBER(7,2) :=3.141;
area NUMBER(7,2);

Step 3. Create the Execution Part of the PL/SQL function.


Once you have created the header of your function and declared all your necessary variables as well as constants
then you are all set to create the execution part of your PL/SQL function. Here in the execution section of a PL/SQL
function, you write all your execution statements. This part also defines the working of your function.

BEGIN
--Area of Circle pi*r*r;
area := pi * (radius * radius);
RETURN area;
END;
/

Quick Info:
To calculate the square of the circle’s radius in the area of circle, you can also use the inbuilt function of POWER (p,
q). This function takes two numeric input and returns one numeric value which will be the answer to the arithmetic
expression of p raise to q.

PL/SQL function for calculating “Area of the Circle”.

CREATE OR REPLACE FUNCTION CIRCLE_AREA(RADIUS NUMBER)


RETURN NUMBER IS

AREA NUMBER(7,3);
PI NUMBER(7,3) :=3.141;

BEGIN

AREA := PI*(RADIUS*RADIUS);
RETURN AREA;
END;
/
-- CALCULATING AREA OF A CIRCLE USING ABOVE CREATED FUNCTION
CIRCLE_AREA

SET SERVEROUT ON;


BEGIN
DBMS_OUTPUT.PUT_LINE(CIRCLE_AREA(14));
END;
/

615.636

PL/SQL procedure successfully completed.

--USING FUNCTION INTO A SELECT STATEMENT BY USING A SIMPE TABLE

TABLE CREATION

CREATE TABLE CALCULATONS(


VAR_VALUE NUMBER);

INSERTING DATA INTO TABLE

INSERT INTO CALCULATONS VALUES(10);


INSERT INTO CALCULATONS VALUES(25);
INSERT INTO CALCULATONS VALUES(30);

CALCULATION OF AREA USING TABLE DATA

SELECT VAR_VALUE AS RADIUS, CIRCLE_AREA(VAR_VALUE) AS CIRCLE_AREA FROM


CALCULATONS;
38.What Are PL/SQL Stored Procedures In Oracle
Database
Similar to PL/SQL Functions a stored Procedure is a self-contained subprogram that is meant to do some specific
tasks. Also similar to functions, procedures are named PL/SQL blocks thus they can be reused because they are
stored into the database as a database object. But unlike PL/SQL functions a stored procedure does not return any
value.

Syntax of PL/SQL Stored Procedures

CREATE [OR REPLACE] PROCEDURE pro_name (Parameter – List)


IS [AUTHID DEFINER | CURRENT_USER]
Declare statements
BEGIN
Executable statements
END procedure name;
/

The above Syntax of PL/SQL stored procedure is pretty much similar to the syntax of PL/SQL Functions that we
saw in the last PL/SQL tutorial. Except for two things:

1.There is no Return clause.

A core difference between a PL/SQL Function and a stored procedure is that unlike Functions a stored procedure
does not return any value.

2. AUTHID Clause.

The AUTHID clause is used for setting the authority model for the PL/SQL Procedures. This clause has two flags.

>>DEFINER
>>CURRENT_USER

As this clause is optional thus in case if you do not use AUTHID clause then Oracle Engine will set the authority
(AUTHID) to the DEFINER by default for you. Now, you must be wondering what these DEFINER and
CURRENT_USER rights are?

DEFINER right: Definer right is the default right assigned to the procedure by oracle engine. This right means
anyone with Execution Privilege on the procedure acts as if they are the owner of the schema in which the privilege
is created.

CURRENT_USER right: Setting the authority level of a stored procedure to the current_user right overrides the
default right which is definer and change it to the invoker rights.

Invoker right authority means that you call the procedure to act on your local data and it requires that you replicate
data objects in any participating schema.
Some Extra Points About Stored Procedure
1.You can define a procedure with or without formal parameters.
2.A parameter can be either pass-by-value or pass-by-reference.
3.A procedure will be a pass-by-value procedure when you don’t specify the parameter mode because it uses the
default IN mode.

**Differences between PL/SQL Functions and PL/SQL Stored Procedures:**

PL/SQL functions and stored procedures are both types of database objects that encapsulate a block of code,
but they serve different purposes:

1. **Return Value:**
- **Function:** A function must return a single value using the `RETURN` statement. It's used in SELECT
statements or within expressions to compute and return a value.
- **Stored Procedure:** A stored procedure doesn't need to return a value. It can perform various
operations, such as inserting, updating, or deleting data, but it doesn't return a result like a function does.

2. **Usage:**
- **Function:** Functions are typically used in SQL statements (SELECT queries) or within expressions,
allowing you to compute and return a value as part of the result set.
- **Stored Procedure:** Stored procedures are used to encapsulate a series of SQL and PL/SQL statements
that perform specific tasks or operations. They can also be called from other PL/SQL code or even from
outside the database.

3. **Calling:**
- **Function:** Functions can be called directly within SQL statements or expressions.
- **Stored Procedure:** Stored procedures are usually called using the `CALL` statement or within other
PL/SQL blocks.

**Parameter Modes in PL/SQL Functions and Procedures:**

When defining parameters for PL/SQL functions and procedures, you can specify different parameter modes
to indicate how the parameters are used within the function or procedure. The available parameter modes are:

1. **IN:**
- This is the default mode if you don't specify a mode.
- An `IN` parameter allows you to pass values into the function or procedure.
- The function or procedure can read and use the value but cannot modify it.

2. **OUT:**
- An `OUT` parameter is used to return a value from a procedure.
- The parameter's value is initially NULL, and the procedure can modify the parameter's value to provide an
output.
- Functions can't have `OUT` parameters since they are expected to return a single value.

3. **IN OUT:**
- An `IN OUT` parameter combines the behavior of both `IN` and `OUT` parameters.
- You can pass a value into the procedure, the procedure can modify the value, and the modified value is
also accessible after the procedure call.

**Formal and Actual Parameters:**

1. **Formal Parameters:**
- Formal parameters are the placeholders you define in the function or procedure header. They define the
names, data types, and modes of the parameters that the function or procedure can accept.
- These parameters serve as variables within the function or procedure block, and you can reference them to
perform operations.

2. **Actual Parameters:**
- Actual parameters are the values you provide when calling a function or procedure.
- They correspond to the formal parameters and provide the data that the function or procedure works with.
- Actual parameters can be constants, variables, expressions, or other function/procedure calls.

In summary, PL/SQL functions return values and are often used in SQL queries, while stored procedures don't
return values and are used to perform tasks. Parameter modes (IN, OUT, IN OUT) dictate how parameters are
used within functions and procedures. Formal parameters are defined in the function/procedure signature,
while actual parameters are the values you pass when calling the function/procedure.

39.How To Create PL/SQL Stored Procedures Without


Parameters In Oracle Database
While discussing the syntax in the Introduction to PL/SQL stored procedures we saw that a stored procedure can
have zero, one or many parameters. Today in this section we will learn how to create a PL/SQL stored procedure
with zero parameters or say without any parameters. Apart from creating a stored procedure in oracle database, we
will also learn in this tutorial the multiple ways of calling a stored procedure in a PL/SQL program.

How To Create PL/SQL Stored Procedure without Parameters In Oracle Database

SET SERVEROUTPUT ON;

CREATE OR REPLACE PROCEDURE MY_NAME IS


EMP_NAME VARCHAR2(30) := 'HUSSAIN';
EMP_PROJECT VARCHAR2(30) := 'FSF LEVEL2 TEAM';

BEGIN

DBMS_OUTPUT.PUT_LINE('HI THIS IS '||EMP_NAME||' FROM '||EMP_PROJECT);


END MY_NAME;
/

In the above example I have created a PL/SQL Stored procedure with the name MY_NAME which has two
variables capable of holding strings of VARCHAR2 datatype. In the execution section this PL/SQL procedure has
only one DBMS OUTPUT statement which is displaying the strings stored into those variable back to the user in a
formatted manner.

How to Call PL/SQL Stored Procedures in Oracle Database


After successfully creating and compiling the stored procedure, next you have to call this subroutine. You can do so
in multiple ways such as:

 Call a PL/SQL stored procedure using EXECUTE statement.


 Call a PL/SQL stored procedure using an Anonymous PL/SQL block.
 Call a PL/SQL stored procedure using a Named PL/SQL block.

1.Call a PL/SQL stored procedure using EXECUTE statement


The best way to quickly check the output of your stored procedure or test the working of your PL/SQL procedure is
to call it using EXECUTE keyword. In order to call a stored procedure using EXECUTE keyword you simply have
to write the same keyword followed by the name of the procedure.

EXECUTE MY_NAME;
Or you can also write the first 4 letters of the EXECUTE keyword followed by the procedure name.

EXEC MY_NAME;

HI THIS IS HUSSAIN FROM FSF LEVEL2 TEAM

PL/SQL procedure successfully completed.

Both the statements are the same and will do the same work.

2.Call a PL/SQL stored procedure using an Anonymous PL/SQL block


The second way of calling a procedure is to place a procedure call statement inside the execution section of an
anonymous PL/SQL block.

BEGIN
MY_NAME;
END;

HI THIS IS HUSSAIN FROM FSF LEVEL2 TEAM

PL/SQL procedure successfully completed.

You simply have to write the name of your stored procedure inside the execution section of an anonymous and
named PL/SQL block. The compiler will automatically interpret that as a procedure call statement. If your procedure
accepts any parameters then you can supply values for parameters here.

3.Call a PL/SQL stored procedure using a Named PL/SQL block.


SET SERVEROUTPUT ON;
CREATE OR REPLACE FUNCTION call_MY_NAME RETURN VARCHAR2 AS
BEGIN
MY_NAME;
RETURN 'Favorite string displayed.';
END;
/

SET SERVEROUTPUT ON;


BEGIN
DBMS_OUTPUT.PUT_LINE(call_MY_NAME);
END;
/

HI THIS IS HUSSAIN FROM FSF LEVEL2 TEAM

Favorite string displayed.

PL/SQL procedure successfully completed.


40.How To Create PL/SQL Stored Procedures With
Parameters In Oracle Database
In the previous section we have discussed how to create stored procedure without parameters. But sometimes it may
happen that you will need to create a stored procedure which accepts parameters. Lets see how

Step 1: Create the header of the stored procedure


In the header of the procedure we define its signature.

CREATE OR REPLACE PROCEDURE emp_sal


(dep_id NUMBER, sal_raise NUMBER)
IS

The header is pretty similar to the one which we saw in the last section except that this time our procedure is
accepting parameters which are dep_id and sal_raise of NUMBER datatype.

Step 2: Create the execution section of the stored procedure


In the execution section we write all the executable statements which define the working of the stored
procedure.

BEGIN
UPDATE employees SET salary = salary * sal_raise WHERE department_id = dep_id;
END;
/

For a better understanding I have tried to make this code as simple as possible. In the execution section we only
have one DML statement which is UPDATE. Using this we update the salary column of employee table.

You can write the business logic like this then wrap them up into a procedure and call them in your app when
needed. This will give you more control on your app. It will also save you from writing the same code again
and again.

This procedure will accept two parameters which is the department id and the numeric value for salary raise.
First parameter which is the dep_id, is used to determine the ID of the department. The second parameter which
is sal _ raise will become the multiplication factor in the salary raise.

Let’s combine all the above chunks of code into a single one named PL/SQL unit.

Stored Procedure for Department Wide Salary Raise

CREATE OR REPLACE PROCEDURE emp_sal( dep_id NUMBER, sal_raise NUMBER)


IS
BEGIN
UPDATE emp SET salary = salary * sal_raise WHERE department_id = dep_id;
END;
/
Once you have successfully created your stored procedure, next you have to call it in your program or code.

CREATE TABLE EMP(


department_id NUMBER,
salary NUMBER);
INSERT INTO EMP VALUES(201,349000);
INSERT INTO EMP VALUES(202,368000);
INSERT INTO EMP VALUES(203,329000);
INSERT INTO EMP VALUES(201,319000);
INSERT INTO EMP VALUES(201,339000);

EXECUTE emp_sal(201,1.07);

Actual Parameters Versus Formal Parameters

What are Formal Parameters?


A formal parameter is a parameter which you specify when you define the subroutine or function.
These parameters define the list of possible variables, their positions along with their datatypes. While
specifying the formal parameters in the signature of your subroutines you do not assign any value to
them except the default values which make a parameter optional.

Example of Formal Parameters


CREATE OR REPLACE FUNCTION circle_area (radius NUMBER)
RETURN NUMBER IS

This is the header of the PL/SQL Function which we saw in How to Create Functions in Oracle
Database. Here the parameter radius NUMBER is the formal parameter.

What are actual parameters?

Actual parameters are the parameters which you specify when you call the subroutine such as
Functions or Procedures. These are actually the values you provide to the subroutine when you call
them. You can call a subroutine without an actual parameter when the formal parameter has a default
value.

Example of Actual Parameters


BEGIN
DBMS_OUTPUT.PUT_LINE(circle_area (25));
END;
/
Here in the above PL/SQL anonymous block, we call the function circle_area( ) whose signature we
saw above by passing the value 25 against the formal parameter radius NUMBER. This Numeric value
25 is the actual parameter.

Always make sure that the datatype of the value you specified as an actual parameter must match with
the data type of the corresponding formal parameter. Also, the value specified as an actual parameter
of a function will override the default value of the corresponding formal parameter if it has any.

41.Calling Notation For PL/SQL Subroutines In Oracle


Database
What is Calling Notation for PL/SQL Subroutines?
Calling notation is a way of providing values to the parameters of a subroutine such as PL/SQL function or a
stored procedure.

Types of Calling Notations for Subroutines


In Oracle PL/SQL there are 3 types of calling notations. These are:

1. Positional Notation
2. Named Notation and
3. Mixed calling notation

Positional Calling Notations

Positional notation is the most common calling notation which you can see in almost every computer
programming language. In positional notation we have to specify the value for each formal parameter in a
sequential manner. This means that you have to provide the values for the formal parameters in the same order
as they were declared in the procedure or in the function.

In positional notation the datatype and the position of the actual parameter must match with the formal
parameter.

Example: Positional Notation for calling PL/SQL Subroutines


CREATE OR REPLACE PROCEDURE emp_sal( dep_id NUMBER, sal_raise NUMBER)
IS
BEGIN
UPDATE emp SET salary = salary * sal_raise WHERE department_id = dep_id;
DBMS_OUTPUT.PUT_LINE ('salary updated successfully');
END;
/

This is the same example which we did in previous section on how to create stored procedure with parameters
albeit some minor changes. Now if we use positional calling notation then we have to supply the values to both
the parameters of the above procedure in the same manner in which they are declared.
Stored Procedure call using positional notation in Oracle Database

EXECUTE emp_sal(40,2);

In this simple procedure call, the value 40 is corresponding to the formal parameter dep_id and value 2 is
corresponding to the parameter sal_raise.

Named Calling Notations


Named calling notation lets you pass values to the formal parameters using their names. This will in turn let
you assign values to only required or say mandatory parameters.

This calling notation is useful when you have a subroutine with parameters where some of those parameters are
mandatory and some are optional and you want to pass the values to only the mandatory ones.

Association Operator

In order to assign values to the formal parameters using their names we use association operator. It is a
combination of equal to (=) sign and greater than (>) sign. We write the name of the formal parameter to the
left hand side of the operator and the value which you want to assign to the right hand side of the operator.

Example of Named Calling Notation for calling a PL/SQL Subroutines


SET SERVEROUTPUT ON;
CREATE OR REPLACE FUNCTION ADD_NUMBER(NUM_1 NUMBER,NUM_2 NUMBER
DEFAULT 0,NUM_3 NUMBER)
RETURN NUMBER IS
BEGIN
DBMS_OUTPUT.PUT_LINE('NUM_1 = '||NUM_1);
DBMS_OUTPUT.PUT_LINE('NUM_2 = '||NUM_2);
DBMS_OUTPUT.PUT_LINE('NUM_3 = '||NUM_3);
RETURN NUM_1+NUM_2+NUM_3;
END;
/

The above function has 3 parameters. Among these 3 parameters 2 are mandatory and 1 is optional with a
default value 0.

You can call this function using positional notation. But it has a restriction which you have to fulfill and that is
that you have to supply values to all the formal parameters in the same order in which they are declared and the
datatype of formal and actual parameters must match.

So if you want to omit the optional parameter and want to use their default value or you just forgot the order of
the parameter in which they were declared! Then it will be slightly difficult for you to call the above subroutine
using positional notation. In such a scenario you can take advantage of Named Calling Notation. This calling
notation will provide you the desired flexibility in calling your subroutines.

PL/SQL Function call using Named Calling Notation in Oracle Database

SET SERVEROUTPUT ON;


DECLARE
VAR_RESULT NUMBER;
BEGIN
VAR_RESULT := ADD_NUMBER(NUM_1 => 5,NUM_3 =>4);
DBMS_OUTPUT.PUT_LINE(VAR_RESULT);
END;
/

NUM_1 = 5
NUM_2 = 0
NUM_3 = 4
9

PL/SQL procedure successfully completed.

Mixed Calling Notation for calling PL/SQL Subroutines


As the name suggests in mixed calling notation you can call subroutines using the combination of named as
well as positional calling notations. Mixed calling notation is very helpful where the parameter list is defined
with all mandatory parameters first and optional parameters next.

Example of Mixed calling notation for calling PL/SQL subroutines


Here is the anonymous block in which we are calling the same function add_num ( ) which we coded when
doing named calling notation.

SET SERVEROUTPUT ON;


DECLARE
VAR_RESULT NUMBER;
BEGIN
VAR_RESULT := ADD_NUMBER(10,NUM_3 =>4);
DBMS_OUTPUT.PUT_LINE(VAR_RESULT);
END;
/

NUM_1 = 10
NUM_2 = 0
NUM_3 = 4
14

PL/SQL procedure successfully completed.

42.Introduction To PL/SQL Packages In Oracle Database

What are PL/SQL Packages in Oracle Database?


Packages are stored libraries in the database which allow us to group related PL/SQL objects under one name.
Or in simple words, Packages are logical groups of related PL/SQL objects. Packages are named PL/SQL
Blocks which mean they are permanently stored into the database schema and can be referenced or reused by
your program.

Definition of PL/SQL Packages


Packages are stored libraries in the database which allow us to group related PL/SQL objects under one
name.
What are the contents included in a package?
A package can hold multiple database objects such as

 Stored Procedures
 PL/SQL Functions
 Database Cursors
 Type declarations as well as
 Variables

Info
All the objects included into a package are collectively called Package Elements.

Package Architecture
PL/SQL package is divided into two parts:

1. The Package Specification, also known as the Header and


2. The Package Body

Both these parts are stored separately in the data dictionary. The package specification is the required part
whereas the package body is optional, but it is a good practice to provide the body to the package.

1.Package Specification
Package specification is also known as the package header. It is the section where we put the declaration of all
the package elements. Whatever elements we declare here in this section are publicly available and can be
referenced outside of the package.

Info
In this section we only declare package elements but we don’t define them. Also this is the mandatory
section of the package.

Syntax of Package specification


CREATE OR REPALCE PACKAGE pkg_name IS
Declaration of all the package element…;
END [pkg_name];

2.Package Body
In package body we provide the actual structure to all the package elements which we have already declared in
the specification by programming them. Or we can say that a package body contains the implementation of the
elements listed in the package specification.

Unlike package specification a package body can contain both declaration of the variable as well as the
definition of all the package elements. Any package elements such as PL/SQL Function, a cursor or a stored
procedure which is not in the package specification but coded in the package body is called Private Package
Elements and thus they cannot be referenced outside the package.

Syntax of the package body


CREATE OR REPALCE PACKAGE BODY pkg_name IS
Variable declaration;
Type Declaration;
BEGIN
Implementation of the package elements…
END [pkg_name];

Syntax is bit similar to package specification here we added BODY keyword which indicates body of a
package

43.How To Create PL/SQL Packages In Oracle Database

How to Create Package?


For the demonstration I am going to create a very simple package which will consist of two elements that is a
function and a stored procedure

As we talked while discussing the architecture of the package in the previous sectionthat the package is divided
into two parts, which are

Package header
The package body

So we will start with creating the package header first

Package Header
SET SERVEROUTPUT ON;
CREATE OR REPLACE PACKAGE PKG_HUSSAIN IS
FUNCTION PRINT_STRG RETURN VARCHAR2;
PROCEDURE PROCE_SUPERHERO (FIRST_NAME VARCHAR2, LAST_NAME VARCHAR2);
END PKG_HUSSAIN;
/
By taking a look at the above code we can clearly say that the package is going to hold two package elements
which are – a PL/SQL function PRINT_STRG and a stored procedure PROCE_SUPERHERO.

We are creating a table SUPER_HEROS for the below package example

CREATE TABLE SUPER_HEROS(


F_NAME VARCHAR2(40),
L_NAME VARCHAR2(40));

Package Body
CREATE OR REPLACE PACKAGE BODY PKG_HUSSAIN IS
--Function Implimentation
FUNCTION PRINT_STRG RETURN VARCHAR2 IS
BEGIN
RETURN 'HI THIS IS HUSSAIN FROM FSF LEVEL2 TEAM';
END PRINT_STRG;
--Procedure Implimentation
PROCEDURE PROCE_SUPERHERO (FIRST_NAME VARCHAR2, LAST_NAME VARCHAR2)IS
BEGIN
INSERT INTO SUPER_HEROS(F_NAME,L_NAME) VALUES (FIRST_NAME,LAST_NAME);
END;
END PKG_HUSSAIN;
/

In the above code for the package body we implemented both the package elements which we defined into the
package header.

Info
Both package header and body are individual database objects thus you have to compile them separately in
order to put your package to work.

How to access the package elements?


We have our package header and body created and compiled successfully, what’s next? Like every other database
object, package serves a unique purpose. Using a package you can group different database objects under one name
and as PL/SQL packages are named database blocks thus they can be stored into the database and can be used later
when needed.
So the question arises here is how to access the package elements? To access the elements defined and
implemented into a package we use dot (.) notation. According to which in order to access the package element
you have to first write the name of your package followed by dot (.) operator and then the name of the package
element.

Example:
For example say you want to call the PL/SQL function print_strg of our package PKG_HUSSAIN.

--Package Calling Function


SET SERVEROUTPUT ON;
BEGIN
DBMS_OUTPUT.PUT_LINE (PKG_HUSSAIN.print_strg);
END;

HI THIS IS HUSSAIN FROM FSF LEVEL2 TEAM

PL/SQL procedure successfully completed.

For example say you want to call the PL/SQL procedure print_strg of our package PKG_HUSSAIN.

--Package Calling Procedure


SET SERVEROUTPUT ON;
BEGIN
PKG_HUSSAIN.PROCE_SUPERHERO('SPIDER', 'MAN');
END;
/
To check wheter data inserted into table or not
SELECT * FROM SUPER_HEROS;
44.Introduction To PL/SQL Exception Handling In Oracle
Database

What is an Exception?
Any abnormal condition or say event that interrupts the normal flow of your program’s instructions at run time is an
exception. Or in simple words you can say an exception is a run time error.

Info:
Exceptions are designed for run time error handling rather than compile time error handling. Errors that
occur during compilation phase are detected by the PL/SQL compiler and reported back to the user.

Types of exceptions
There are two types of PL/SQL exceptions in Oracle database.

1. System-defined exceptions and


2. User-defined exceptions

System-Defined Exceptions
System-defined exceptions are defined and maintained implicitly by the Oracle server. These exceptions are mainly
defined in the Oracle STANDARD package. Whenever an exception occurs inside the program. The Oracle server
matches and identifies the appropriate exception from the available set of exceptions.

System defined exceptions majorly have a negative error code and error message. These errors have a short name
which is used with the exception handler.

Info:
Oracle avails two utility functions SQLCODE & SQLERRM to retrieve the error code and message for last
occur exception.

User-Define Exceptions
Unlike System-Define Exception, User-Define Exceptions are raised explicitly in the body of the PL/SQL block
(more specifically inside the BEGIN-END section) using the RAISE Statement.

How to Declare a User-Define Exception in Oracle Database.


There are three ways of declaring user-define exceptions in Oracle Database.

1. By declaring a variable of EXCEPTION type in declaration section.

You can declare a user defined exception by declaring a variable of EXCEPTION datatype in your code and
raise it explicitly in your program using RAISE statement and handle them in the Exception Section.

2. Declare user-defined exception using PRAGMA EXCEPTION_INIT function.


Using PRAGMA EXCEPTION_INIT function you can map a non-predefined error number with the variable of
EXCEPTION datatype. Means using the same function you can associate a variable of EXCEPTION datatype
with a standard error.

3. RAISE_APPLICATION_ERROR method.

Using this method you can declare a user defined exception with your own customized error number and
message.

For the demonstration purpose I will write a code which will check whether the divisor is zero or not in the
division operation. If it is zero then an error will occur and will be displayed to the user otherwise an actual
value which is the result of the division arithmetic will be returned on the output screen.

Step 1: Declare a variable of Exception datatype


By Exception variable I mean a variable with Exception datatype. Like any other PL/SQL variable you can
declare an Exception variable in declaration section of the anonymous as well as named PL/SQL block. This
exception variable will then work as user-define exception for your code.

DECLARE
VAR_DIVIDEND NUMBER := '&PROVIDE_DIVIDEND';
VAR_DIVISOR NUMBER := '&PROVIDE_DIVIDEND';
VAR_RESULT NUMBER;
EXCEPTION_VAR EXCEPTION;

In above code ‘&’ used to take input from the user

In this declaration section we have 4 variables. Among these 4 variables first 3 are normal Number datatype
variables and the 4th one which is EXCEPTION_VAR is the special EXCEPTION datatype variable. This
variable will become our User-Define Exception for this program.

Step 2: Raise the Exception


The next step after declaring an Exception variable is to raise the exception. To raise the exception in PL/SQL
we use Raise statement.

Raise statement is a special kind of PL/SQL statement which changes the normal flow of execution of the code.
As soon as compiler comes across a raise condition it transfers the control over to the exception handler.

BEGIN
IF VAR_DIVISOR = 0 THEN
RAISE EXCEPTION_VAR;
END IF;

Here raise condition is accompanied with the IF-THEN condition. With the help of this we can avoid unwanted
switches during the control flow of the program. Using If Condition we are making sure that this error will
come into action only when the divisor is equal to 0.

VAR_RESULT :=VAR_DIVIDEND/VAR_DIVISOR;
DBMS_OUTPUT.PUT_LINE('RESULT = '||VAR_RESULT);
After writing the logic for raising the error you can write your other executable statements of the code just like
we did here. After the Raise statement we are performing the arithmetic of division operation and storing the
result into the variable VAR_RESULT, as well as displaying it back as the output using the DBMS OUTPUT
statement.

Step 3: Handle the exception


That is the main section of the code. Here we write the logic for our user-define exception and tell the compiler
what it should do when that error occurs.

EXCEPTION WHEN EXCEPTION_VAR THEN


DBMS_OUTPUT.PUT_LINE('Error Error - Your Divisor is Zero');
END;
/

Here we have the exception handler for the variable EXCEPTION_VAR. In the exception handling section we
have a DBMS OUTPUT statement which will get displayed when our user define error which is
EXCEPTION_VAR occurs.

Now let’s group all these chunks of codes together.

Divide by zero error using PL/SQL User-define Exception in


Oracle Database
SET SERVEROUTPUT ON;
DECLARE
VAR_DIVIDEND NUMBER := '&PROVIDE_DIVIDEND';
VAR_DIVISOR NUMBER := '&PROVIDE_ DIVISOR;
VAR_RESULT NUMBER;
EXCEPTION_VAR EXCEPTION;
BEGIN
IF VAR_DIVISOR = 0 THEN
RAISE EXCEPTION_VAR;
END IF;

VAR_RESULT :=VAR_DIVIDEND/VAR_DIVISOR;
DBMS_OUTPUT.PUT_LINE('RESULT = '||VAR_RESULT);
EXCEPTION WHEN EXCEPTION_VAR THEN
DBMS_OUTPUT.PUT_LINE('Error Error - Your Divisor is Zero');
END;
/

RESULT = 5

PL/SQL procedure successfully completed.


If we provide divisor as 0
Error Error - Your Divisor is Zero

PL/SQL procedure successfully completed.

OR (we can directly assign values to variables)

SET SERVEROUTPUT ON;


DECLARE
VAR_DIVIDEND NUMBER := 10;
VAR_DIVISOR NUMBER := 0;
VAR_RESULT NUMBER;
EXCEPTION_VAR EXCEPTION;
BEGIN
IF VAR_DIVISOR = 0 THEN
RAISE EXCEPTION_VAR;
END IF;

VAR_RESULT :=VAR_DIVIDEND/VAR_DIVISOR;
DBMS_OUTPUT.PUT_LINE('RESULT = '||VAR_RESULT);
EXCEPTION WHEN EXCEPTION_VAR THEN
DBMS_OUTPUT.PUT_LINE('Error Error - Your Divisor is Zero');
END;

Error Error - Your Divisor is Zero

PL/SQL procedure successfully completed.

45.Declare User-Define Exception Using


RAISE_APPLICATION_ERROR Method In Oracle
Database
As discussed in the introduction to PL/SQL exception handling there are three ways of declaring user-define
exceptions in Oracle PL/SQL. Among those three we have already discussed and learnt the first way in the
previous section. in this section we will take a step ahead and see the second way of declaring user define
exception and learn how to declare user-define exception using RAISE_APPLICATION_ERROR method.

What is RAISE_APPLICATION_ERROR method?


RAISE APPLICATION ERROR is a stored procedure which comes in-built with Oracle software. Using this
procedure you can associate an error number with the custom error message. Combining both the error number
as well as the custom error message you can compose an error string which looks similar to those default error
strings which are displayed by Oracle engine when an error occurs.

How many errors can we generate using RAISE_APPLICATION_ERROR

procedure?
RAISE_APPLICATION_ERROR procedure allows us to number our errors from -20,000 to -20,999 thus we
can say that using RAISE_APPLICATION_ERROR procedure we can generate 1000 errors.

Raise_application_error is part of which package?

You can find RAISE_APPLICATION_ERROR procedure inside DBMS_STANDARD package.

Syntax of Raise_Application_Error

raise_application_error (error_number, message [, {TRUE | FALSE}]);

Here the error_number is a negative integer in the range of -20000.. -20999 and the message is a character
string up to 2048 bytes long. In case of the optional third parameter being TRUE, the error is placed on the pile
of all the previous errors. However in case of FALSE (the default) parameter, the error replaces all previous
errors. RAISE_APPLICATION_ERROR is part of package DBMS_STANDARD, and you do not need to
qualify references to package STANDARD.

Optional Parameter: There's another thing you can add if you want. It's like an extra option. If you set it
to "TRUE," the error you're raising will be added to a list of previous errors. If you set it to "FALSE"
(which is the default), the new error will replace any previous errors.

Example of RAISE_APPLICATION_ERROR procedure


In the following example we will take an input of numeric datatype from the user and check if it is 18 or above.
If it is not then the user-define error, which we will declare, will be raised otherwise there will be the normal
flow of execution of the program.

In the following example we will take an input of numeric datatype from the user and check if it is 18 or above.
If it is not then the user-define error, which we will declare, will be raised otherwise there will be the normal
flow of execution of the program.

Step1: Set the server output on


If we want to see the result returned by the PL/SQL program on the default output screen then we will have to
set the server output ‘on’ which is by default set to ‘off’ for the session.

SET SERVEROUTPUT ON;

Step 2: Take User Input


Though we can hardwire the values in our code as we did in the last tutorial but it is not that fun. In order to
make the code more dynamic I decided to accept the input by user this time by letting them to enter the value
into a pop-up box with a customized message printed on it.
We can take the input using pop-up box with a customized message printed on it using ACCEPT command in
Oracle PL/SQL.

ACCEPT var_age NUMBER PROMPT 'What is your age?';

Command starts with the keyword accept followed by the name of the variable and its datatype. In our case the
name is var_age and datatype is NUMBER. That is the first half of the statement. This part will help us in
storing the input value. The other half of the statement will be responsible for printing the customized message
on the pop-up box. Using the keyword PROMPT which is right after the datatype of the variable, you can
specify any desired string which you want printed on your pop-up box. In our case this customized message
will be ‘What is your age?’

Step 3: Declare Variable


DECLARE
age NUMBER := &var_age;

Due to the scope restriction we cannot use the value stored into the variable which we used in the accept
command. This means we cannot directly use that value into our PL/SQL program. We can solve this problem
by assigning the value that was stored into the variable var_age to a variable which is local to the PL/SQL
block. That is exactly what we did in the above segment of the code.

Step 4: Declare the user-define exception by using


RAISE_APPLICATION_ERROR procedure
BEGIN
IF age < 18 THEN
RAISE_APPLICATION_ERROR (-20008, 'you should be 18 or above for the DRINK!');
END IF;

Here in this code segment we declared the user-define exception using RAISE_APPLICATION_ERROR
procedure. This procedure is called using two parameters. In which first parameter is the negative number
which, in my case, is -20008 and the second number is a string which gets displayed if the same error occurs.

Now the question is when will this error occur?

As you can see that the code is enclosed inside an IF-THEN conditional control block which is making sure
that the error will be raised only if the age of the user is less than 18 years.

Step 5: Executable statement


DBMS_OUTPUT.PUT_LINE('Sure, What would you like to have?');

Executable statements are those that get compiled and run when there is no error and the program has a normal flow
of execution. In order to make the code simple and easy to understand I just wrote a single statement which is the
DBMS OUTPUT statement.

Step 6: Write the Exception handler


Now that we have declared as well as raised the user-define exception next we need to write the exception handler
for it. As said in the previous PL/SQL tutorial that in the Exception Handler section we specify what will happen
when the error which you raised will trigger.
EXCEPTION WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/
In this exception handling section I have called a SQLERRM function using DBMS OUTPUT statement. This is a
utility function provided by Oracle which retrieves the error message for the last occurred exception.

User-Define Exception Using Raise_Application_Error Procedure


SET SERVEROUTPUT ON;
ACCEPT var_age NUMBER PROMPT 'What is yor age';
DECLARE
age NUMBER := &var_age;
BEGIN
IF age < 18 THEN
RAISE_APPLICATION_ERROR (-20008, 'you should be 18 or above for the DRINK!');
END IF;
DBMS_OUTPUT.PUT_LINE ('Sure, What would you like to have?');
EXCEPTION WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE (SQLERRM);
END;
/

when user input is grater than 18

Sure, What would you like to have?

PL/SQL procedure successfully completed.

when user input is less than 18

ORA-20008: you should be 18 or above for the DRINK!

PL/SQL procedure successfully completed.


How To Declare User Define Exception Using PRAGMA
EXCEPTION_INIT

What is PRAGMA EXCEPTION_INIT?


Pragma Exception_Init is a two part statement where first part is made up of keyword PRAGMA and second
part is the Exception_Init call.

PRAGMA Keyword
A pragma is a compiler directive which indicates that the Statements followed by keyword PRAGMA is a
compiler directive statement this means that the statement will be processed at the compile time & not at the
runtime.

In summary, compilation is the preparation step where the code is transformed into a
machine-readable format, and execution (running) is the actual step where the computer
carries out the instructions specified in the code.

PRAGMA Exception_Init
Exception_init helps you in associating an exception name with an Oracle error number. In other words we can
say that using Exception_Init you can name the exception.

Why name the exception?


Yes, there is a way of declaring user-define exception without the name and that is by using
Raise_Exception_Error procedure. This indeed is a simple and easy way but as we learnt in the last tutorial that
to handle exceptions without name we use OTHERS exception handler.

Now think that in your project you have multiple exceptions and that too without name. In order to handle all
those exceptions you have a single exception handler with name OTHERS. In this case on the occurrence of an
exception condition the compiler will display the error stack produced by the OTHER handler.

Can you imagine how difficult it will be to trace that part of your project which is causing the error. In order to
trace that part you need to go through each & every line of your code. This will be mere waste of time.

You can save all those time wasting efforts just by naming the exception, that way you can design an exception
handler specific to the name of your exception which will be easily traceable. This is the advantage of naming
the exception.
Syntax of Pragma Exception_Init.

PRAGMA EXCEPTION_INIT (exception_name, error_number);

Example: Declare User-define exception using Pragma Exception_Init


DECLARE
ex_age EXCEPTION;
age NUMBER := 17;
PRAGMA EXCEPTION_INIT(ex_age, -20008);
BEGIN
IF age<18 THEN
RAISE_APPLICATION_ERROR(-20008, 'You should be 18 or above for the drinks!');
END IF;

DBMS_OUTPUT.PUT_LINE('Sure! What would you like to have?');

EXCEPTION WHEN ex_age THEN


DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/

Why use PRAGMA EXCEPTION_INIT with


RAISE_APPLICATION_ERROR?
Though it is not mandatory to use PRAGMA EXCEPTION_INIT with RAISE_APPLICATION_ERROR
procedure however it is more of a personal preference than a programming rule. If you want to print an error
message with an error number like the Oracle’s standard way of showing an error then it is the best practice to
use PRAGMA EXCEPTION_INIT with RAISE_APPLICATION_ERROR procedure.

You might also like