Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
5 views

PLSQL notes

PL/SQL is an extension of SQL that allows for procedural programming, enabling the creation of complex applications through blocks of code. It features advantages such as block structures, error handling, and better performance by processing multiple SQL statements at once. PL/SQL supports various data types, including variables, constants, and records, and provides conditional statements for control flow.
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views

PLSQL notes

PL/SQL is an extension of SQL that allows for procedural programming, enabling the creation of complex applications through blocks of code. It features advantages such as block structures, error handling, and better performance by processing multiple SQL statements at once. PL/SQL supports various data types, including variables, constants, and records, and provides conditional statements for control flow.
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 60

Ftrigg PL/SQL

PL/SQL is an extension of Structured Query Language (SQL) that is used in Oracle.


Unlike SQL, PL/SQL allows the programmer to write code in a procedural format. Full
form of PL/SQL is "Procedural Language extensions to SQL".

Difference between SQL and PL/SQL

SQL PL/SQL

 SQL is a single query that is used to  PL/SQL is a block of


perform DML and DDL operations. codes that used to write
the entire program blocks/
procedure/ function, etc.

 It is declarative, that defines what need  PL/SQL is procedural that


to be done, rather than how things need defines how the things
to be done. needs to be done.

 Execute as a single statement.  Execute as a whole block.

 Mainly used to manipulate data.  Mainly used to create an


application.

 Interaction with a Database server.  No interaction with the


database server.

 Cannot contain PL/SQL code in it.  It is an extension of SQL,


so that it can contain SQL
inside it.

Advantages of PL/SQL

 Block Structures: PL SQL consists of blocks of code, which can be nested within each
other. Each block forms a unit of a task or a logical module. PL/SQL Blocks can be
stored in the database and reused.
 Procedural Language Capability: PL SQL consists of procedural language constructs
such as conditional statements (if else statements) and loops like (FOR loops).

 Better Performance: PL SQL engine processes multiple SQL statements simultaneously


as a single block, thereby reducing network traffic.

 Error Handling: PL/SQL handles errors or exceptions effectively during the execution of
a PL/SQL program. Once an exception is caught, specific actions can be taken depending
upon the type of the exception or it can be displayed to the user with a message.

Block Structure

PL/SQL blocks have a pre-defined structure in which the code is to be grouped. Below are
different sections of PL/SQL blocks.

1. Declaration section

2. Execution section

3. Exception-Handling section

PL/SQL Block Syntax. Below is the syntax of the PL/SQL block structure.

Types of PL/SQL block

PL/SQL blocks are of mainly two types.


1. Anonymous blocks
2. Named Blocks

Anonymous blocks:

Anonymous blocks are PL/SQL blocks which do not have any names assigned to them.
They need to be created and used in the same session because they will not be stored in the
server as database objects.

Since they need not store in the database, they need no compilation steps. They are written
and executed directly, and compilation and execution happen in a single process.

Below are few more characteristics of Anonymous blocks.

 These blocks don't have any reference name specified for them.
 These blocks start with the keyword 'DECLARE' or 'BEGIN'.
 Since these blocks do not have any reference name, these cannot be stored for later
purpose. They shall be created and executed in the same session.
 They can call the other named blocks, but call to anonymous block is not possible as
it is not having any reference.
 It can have nested block in it which can be named or anonymous. It can also be
nested in any blocks.
 These blocks can have all three sections of the block, in which execution section is
mandatory, the other two sections are optional.

Named blocks:

Named blocks have a specific and unique name for them. They are stored as the database
objects in the server. Since they are available as database objects, they can be referred to or
used as long as it is present on the server. The compilation process for named blocks
happens separately while creating them as a database objects.

Below are few more characteristics of Named blocks.

 These blocks can be called from other blocks.


 The block structure is same as an anonymous block, except it will never start with
the keyword 'DECLARE'. Instead, it will start with the keyword 'CREATE' which
instruct the compiler to create it as a database object.
 These blocks can be nested within other blocks. It can also contain nested blocks.
 Named blocks are basically of two types:

1. Procedure
2. Function

We need to execute "set serveroutput on" if we need to see the output of the code.

To create editor file in sql: SQL>set editfile d:/sqledit.sql


1. To print hello world

Sql>ed

BEGIN
dbms_output.put_line (‘Hello World..');
END:
/

Save and close the editor

Sql>/
Output:
Hello World...

Declaring and usage of variables in the program

2. to print the "Hello World" using the variables.

DECLARE
text VARCHAR2(25);
BEGIN
text:= ‘Hello World’;
dbms_output.put_line (text);
END:
/
Output:
Hello World

Comments in PL/SQL

Comment can be used in the program to increase the readability of the program. In
PL/SQL codes can be commented in two ways.

 Using '--' in the beginning of the line to comment that particular line.
 Using '/*…….*/' we can use multiple lines. The symbol '/*' marks the starting of the
comment and the symbol '*/' marks the end of the comment. The code between these
two symbols will be treated as comments by the compiler

BEGIN
--single line comment
dbms output.put line (' Hello World ’);
/*Multi line commenting begins
Multi line commenting ends */
END;
/
Output:
Hello World

PL/SQL Placeholders

Placeholders are temporary storage area. PL/SQL Placeholders can be any of Variables,
Constants and Records. Oracle defines placeholders to store data temporarily, which are
used to manipulate data during the execution of a PL SQL block.

Define PL/SQL Placeholders

Depending on the kind of data you want to store, you can define placeholders with a name
and a datatype. Few of the datatypes used to define placeholders are as given below.
Number (n,m) , Char (n) , Varchar2 (n) , Date , Long , Long raw, Raw, Blob, Clob, Nclob,
Bfile

Properties of Identifiers

 Must start with a letter


 Maximum size is limited to 30 letters
 Cannot contain whitespace characters
 Can contain dollar sign ('$'), underscore ('_') and hash sign ('#')
 Is case-insensitive

PL/SQL Variables
General Syntax to declare a variable is
variable_name datatype [NOT NULL := value ];

 variable_name is the name of the variable.


 datatype is a valid PL/SQL datatype.
 NOT NULL is an optional specification on the variable.
 value or DEFAULT valueis also an optional specification, where you can
initialize a variable.
 Each variable declaration is a separate statement and must be terminated by a
semicolon.

For example, if you want to store the current salary of an employee, you can use a
variable.
DECLARE
salary number (6);

* “salary” is a variable of datatype number and of length 6.

When a variable is specified as NOT NULL, you must initialize the variable when it
is declared.

For example: The below example declares two variables, one of which is a not null.

DECLARE
salary number(4);
dept varchar2(10) NOT NULL := “HR Dept”;

The value of a variable can change in the execution or exception section of the PL/SQL
Block. We can assign values to variables in the two ways given below.

1) We can directly assign values to variables.


The General Syntax is:

variable_name:= value;
<variable_name> <datatype> := <value>;

2) We can assign values to variables directly from the database columns by using a
SELECT.. INTO statement. The General Syntax is:

SELECT column_name INTO variable_name


FROM table_name [WHERE condition];

Example: The below program will get the salary of an employee with id '1116' and display
it on the screen.

DECLARE
var_salary number(6);
var_emp_id number(6) = 1116;
BEGIN
SELECT salary
INTO var_salary
FROM employee
WHERE emp_id = var_emp_id;
dbms_output.put_line(var_salary);
dbms_output.put_line('The employee '
|| var_emp_id || ' has salary ' || var_salary);
END;
/
PL/SQL Constants
As the name implies a constant is a value used in a PL/SQL Block that remains
unchanged throughout the program.

General Syntax to declare a constant is:

constant_name CONSTANT datatype := VALUE;


 constant_name is the name of the constant i.e. similar to a variable name.
 The word CONSTANT is a reserved word and ensures that the value does not
change.
 VALUE - It is a value which must be assigned to a constant when it is declared.
You cannot assign a value later.

For example, to declare salary_increase, you can write code as follows:

DECLARE
salary_increase CONSTANT number (3) := 10;

You must assign a value to a constant at the time you declare it. If you do not assign a
value to a constant while declaring it and try to assign a value in the execution section,
you will get a error. If you execute the below Pl/SQL block you will get error.

DECLARE
salary_increase CONSTANT number(3);
BEGIN
salary_increase := 100;
dbms_output.put_line (salary_increase);
END;

PL/SQL Records

What are records?

Records are another type of datatypes which oracle allows to be defined as a


placeholder. Records are composite datatypes, which means it is a combination of
different scalar datatypes like char, varchar, number etc. Each scalar data types in the
record holds a value. A record can be visualized as a row of data. It can contain all the
contents of a row.

Declaring a record:

To declare a record, you must first define a composite datatype; then declare a record
for that type.
The following table consolidates the different ways in which you can define and
declare a pl/sql record.

Usage
Syntax

TYPE record_type_name IS RECORD Define a composite datatype,


(column_name1 datatype, column_name2 where each field is scalar.
datatype, ...);

col_name table_name.column_name%type; Dynamically define the datatype


of a column based on a database
column.

record_name record_type_name; Declare a record based on a user-


defined type.

record_name table_name%ROWTYPE; Dynamically declare a record


based on an entire row of a table.
Each column in the table
corresponds to a field in the
record.

Example:
1.
DECLARE
TYPE employee_type IS RECORD
(employee_id number(5),
employee_first_name varchar2(25),
employee_last_name employee.last_name%type,
employee_dept employee.dept%type);
employee_salary employee.salary%type;
employee_rec employee_type;

2.
DECLARE
employee_rec employee%ROWTYPE;
The advantages of declaring the record as a ROWTYPE are:
1) You do not need to explicitly declare variables for all the columns in a table.
2) If you alter the column specification in the database table, you do not need to update the
code.

The disadvantage of declaring the record as a ROWTYPE is:


1) When u create a record as a ROWTYPE, fields will be created for all the columns in
the table and memory will be used to create the datatype for all the fields. So use
ROWTYPE only when you are using all the columns of the table in the program.

Passing Values To and From a Record

The following table consolidates the different ways you can assign values to and from
a record:

Usage
Syntax
record_name.col_name := value; To directly assign a value to a
specific column of a record.
record_name.column_name := value; To directly assign a value to a
specific column of a record, if
the record is declared using
%ROWTYPE.
SELECT col1, col2 INTO To assign values to each field of
record_name.col_name1, a record from the database table.
record_name.col_name2 FROM table_name
[WHERE clause];
SELECT * INTO record_name FROM To assign a value to all fields in
table_name [WHERE clause]; the record from a database table.
variable_name := record_name.col_name; To get a value from a record
column and assigning it to a
variable.

Example #1 – Program-Defined Record

DECLARE
no1 number(5);
name1 employee5.name%type;
salary1 number(5);
deptno1 employee.deptno%type;
commission1 employee5.comm%type;

TYPE emp_rec IS RECORD


(no number(5),
name employee5.name%type,
salary number(5),
deptno employee.deptno%type,
commission employee5.comm%type);

emp1 emp_rec;
BEGIN
select empno,name,salary,deptno into
no1,name1,salary1,deptno1 from
employee5 where empno=1;
dbms_output.put_line('employee no is '||no1);
dbms_output.put_line('employee name is '||
name1);
dbms_output.put_line('employee slary is '||
salary1);
dbms_output.put_line('employee department
no is '||deptno1);

select * into emp1 from employee5 where


empno=2;
dbms_output.put_line('employee no is '||
emp1.no);
dbms_output.put_line('employee name is '||
emp1.name);
dbms_output.put_line('employee slary is '||
emp1.salary);
dbms_output.put_line('employee department
no is '||emp1.deptno);

END;
/

Output:
SQL> @ five.sql
employee no is 1
employee name is aaa
employee slary is 10000
employee department no is 10
employee no is 2
employee name is bbb
employee slary is 20000
employee department no is 30

Example #2 – Table-based Record


DECLARE
cust_record customers%rowtype;
BEGIN record
SELECT * into cust_record
FROM customer_details
WHERE customer_id = 105;
dbms_output.put_line('Customer ID: ' ||
cust_record.customer_id);
dbms_output.put_line('Customer First Name: ' ||
cust_record.f_name);
dbms_output.put_line('Customer Email Id: ' ||
cust_record.email_id);
dbms_output.put_line('Customer Bill Amount: ' ||
cust_record.bill_amount);
END;

Example #3 – Cursor Based Record


DECLARE
CURSOR cust_record is
SELECT customer_id, f_name, mobile_number
FROM customers_details;
customer_record cust_record%rowtype;
BEGIN
OPEN cust_record;
LOOP
FETCH cust_record into customer_record;
EXIT WHEN cust_record%notfound;
DBMS_OUTPUT.put_line(customer_record.customer_id || ' ' ||
customer_record.f_name);
END LOOP;
END;
Conditional Statements in PL/SQL

syntax
There are different syntaxes for the IF-THEN-ELSE statement.

Syntax (IF-THEN)

The syntax is for IF-THEN in Oracle/PLSQL is:

IF condition THEN
{...statements to execute when condition is TRUE...}
END IF;

You use the the IF-THEN syntax, when you want to execute statements only
when condition is TRUE.

Syntax (IF-THEN-ELSE)

The syntax is for IF-THEN-ELSE in Oracle/PLSQL is:

IF condition THEN
{...statements to execute when condition is TRUE...}

ELSE
{...statements to execute when condition is FALSE...}

END IF;

You use the IF-THEN-ELSE syntax, when you want to execute one set
of statements when condition is TRUE or a different set of statements when condition is
FALSE.

Syntax (IF-THEN-ELSIF)

The syntax for IF-THEN-ELSIF in Oracle/PLSQL is:

IF condition1 THEN
{...statements to execute when condition1 is TRUE...}
ELSIF condition2 THEN
{...statements to execute when condition2 is TRUE...}

END IF;

You use the IF-THEN-ELSIF syntax, when you want to execute one set
of statements when condition1 is TRUE or a different set of statements when condition2 is
TRUE.

Syntax (IF-THEN-ELSIF-ELSE)

The syntax for IF-THEN-ELSIF-ELSE in Oracle/PLSQL is:

IF condition1 THEN
{...statements to execute when condition1 is TRUE...}

ELSIF condition2 THEN


{...statements to execute when condition2 is TRUE...}

ELSE
{...statements to execute when both condition1 and condition2 are
FALSE...}

END IF;

You use the IF-THEN-ELSIF-ELSE syntax, when you want to execute one set
of statements when condition1 is TRUE, a different set of statements when condition2 is
TRUE, or a different set of statements when all previous conditions
(ie: condition1 and condition2) are FALSE

Iterative Statements in PL/SQL


Iterative control Statements are used when we want to repeat the execution of
one or more statements for specified number of times.

There are three types of loops in PL/SQL:

• Simple Loop
• While Loop
• For Loop

1) Simple Loop
A Simple Loop is used when a set of statements is to be executed
at least once before the loop terminates. An EXIT condition must
be specified in the loop, otherwise the loop will get into an
infinite number of iterations. When the EXIT condition is satisfied
the process exits from the loop.

General Syntax to write a Simple Loop is:


LOOP
statements;
EXIT;
{or EXIT WHEN condition;}
END LOOP;
These are the important steps to be followed while using Simple Loop.

1) Initialise a variable before the loop body.


2) Increment the variable in the loop.
3) Use a EXIT WHEN statement to exit from the Loop. If you use a EXIT statement
without WHEN condition, the statements in the loop is executed only once.

2) While Loop

A WHILE LOOP is used when a set of statements has to be executed as long as a


condition is true. The condition is evaluated at the beginning of each iteration. The
iteration continues until the condition becomes false.

The General Syntax to write a WHILE LOOP is:

WHILE <condition>
LOOP statements;
END LOOP;
Important steps to follow when executing a while loop:

1) Initialise a variable before the loop body.


2) Increment the variable in the loop.
3) EXIT WHEN statement and EXIT statements can be used in while loops but it's not
done oftenly.

3) FOR Loop
A FOR LOOP is used to execute a set of statements for a predetermined number of
times. Iteration occurs between the start and end integer values given. The counter
is always incremented by 1. The loop exits when the counter reachs the value of the
end integer.

The General Syntax to write a FOR LOOP is:

FOR counter IN val1..val2


LOOP statements;
END LOOP;

 val1 - Start integer value.


 val2 - End integer value.

Important steps to follow when executing a while loop:

1) The counter variable is implicitly declared in the declaration section, so it's not
necessary to declare it explicity.
2) The counter variable is incremented by 1 and does not need to be incremented
explicitly.
3) EXIT WHEN statement and EXIT statements can be used in FOR loops but it's not
done oftenly.

CASE Statement
 A CASE statement is similar to IF-THEN-ELSIF statement that selects one alternative
based on the condition from the available options.

 Unlike IF-THEN-ELSIF, the CASE statement can also be used in SQL statements.

 ELSE block in CASE statement holds the sequence that needs to be executed when
none of the alternatives got selected.

Syntax:

CASE (expression)
WHEN <valuel> THEN action_blockl;
WHEN <value2> THEN action_block2;
WHEN <value3> THEN action_block3;
ELSE action_block_default;
END CASE;

Example:
DECLARE
a NUMBER :=55;
b NUMBER :=5;
arth_operation VARCHAR2(20) :='MULTIPLY';
BEGIN
dbms_output.put_line('Program started.' );
CASE (arth_operation)
WHEN 'ADD' THEN dbms_output.put_line('Addition of the numbers are: '|| a+b );
WHEN 'SUBTRACT' THEN dbms_output.put_line('Subtraction of the numbers are: '||a-
b );
WHEN 'MULTIPLY' THEN dbms_output.put_line('Multiplication of the numbers are: '||
a*b );
WHEN 'DIVIDE' THEN dbms_output.put_line('Division of the numbers are:'|| a/b);
ELSE dbms_output.put_line('No operation action defined. Invalid operation');
END case;
dbms_output.put_line('Program completed.' );
END;
/

SET SERVEROUTPUT ON
DECLARE
l_day VARCHAR2(10);
BEGIN
l_day := TRIM(TO_CHAR(SYSDATE, 'DAY'));

CASE l_day
WHEN 'SATURDAY' THEN
DBMS_OUTPUT.put_line('The weekend has just started!');
WHEN 'SUNDAY' THEN
DBMS_OUTPUT.put_line('The weekend is nearly over!');
ELSE
DBMS_OUTPUT.put_line('It''s not the weekend yet!');
END CASE;
END;
/

SEARCHED CASE Statement


The SEARCHED CASE statement is similar to the CASE statement, rather than using
the selector to select the alternative, SEARCHED CASE will directly have the expression
defined in the WHEN clause.

 The first WHEN clause that satisfies the condition will be executed, and the
controller will skip the remaining alternatives.

Syntax:

CASE
WHEN <expression1> THEN action_blockl;
WHEN <expression2> THEN action_block2;
WHEN <expression3> THEN action_block3;
ELSE action_block_default;
END CASE;

Example:
DECLARE
a NUMBER :=55;
b NUMBER :=5;
arth_operation VARCHAR2(20) :='MULTIPLY';
BEGIN
dbms_output.put_line('Program started.' );
CASE
WHEN arth_operation = 'ADD' THEN dbms_output.put_line('Addition of the numbers
are: '|| a+b );
WHEN arth_operation = 'SUBTRACT' THEN dbms_output.put_line('Subtraction of the
numbers are: '||a-b );
WHEN arth_operation = 'MULTIPLY' THEN dbms_output.put_line('Multiplication of the
numbers are: '|| a*b );
WHEN arth_operation = 'DIVIDE' THEN dbms_output.put_line('Division of the
numbers are:'|| a/b);
ELSE dbms_output.put_line('No operation action defined. Invalid operation');
END case;
dbms_output.put_line('Program completed.' );
END;
/

PL/SQL Program To Add Two Numbers

Declare
Var1 integer;
Var2 integer;
Var3 integer;
Begin
Var1:=&var1;
Var2:=&var2;
Var3:=var1+var2;
Dbms_output.put_line(var3);
End;
/
PL/SQL Program to Find Factorial of a Number
declare
n number;
fac number:=1;
i number;

begin
n:=&n;

for i in 1..n
loop
fac:=fac*i;
end loop;

dbms_output.put_line('factorial='||fac);
end;
/

PL/SQL Program to Print Table of a Number

declare
n number;
i number;

begin
n:=&n;

for i in 1..10
loop
dbms_output.put_line(n||' x '||i||' = '||n*i);
end loop;
end;
/
PL/SQL Program to Check Number is Odd or Even
declare
n number:=&n;

begin
if mod(n,2)=0
then
dbms_output.put_line('number is even');
else
dbms_output.put_line('number is odd');
end if;
end;
/
PL/SQL Program to Swap two Numbers

declare
a number;
b number;
temp number;

begin
a:=5;
b:=10;

dbms_output.put_line('before swapping:');
dbms_output.put_line('a='||a||' b='||b);

temp:=a;
a:=b;
b:=temp;

dbms_output.put_line('after swapping:');
dbms_output.put_line('a='||a||' b='||b);

end;
/

Pl/SQL Program for Palindrome Number

declare
n number;
m number;
rev number:=0;
r number;

begin
n:=12321;
m:=n;

while n>0
loop
r:=mod(n,10);
rev:=(rev*10)+r;
n:=trunc(n/10);
end loop;

if m=rev
then
dbms_output.put_line('number is palindrome');
else
dbms_output.put_line('number is not palindrome');
end if;
end;
/
PL/SQL Program to Reverse a String
declare
str1 varchar2(50):='&str';
str2 varchar2(50);
len number;
i number;

begin
len:=length(str1);

for i in reverse 1..len


loop
str2:=str2 || substr(str1,i,1);
end loop;

dbms_output.put_line('Reverse of String is:'||str2);


end;
/

Procedures, Functions and Packages


Procedures:
Procedures and functions allow code to be named and stored in the database, making code
reuse simpler and more efficient. Procedures and functions still retain the block format, but the
DECLARE keyword is replaced by PROCEDURE or FUNCTION definitions,
Stored procedures can also have parameters. These parameters have to be
valid SQL types, and have one of three different modes: IN, OUT, or IN OUT.
IN parameters are arguments to' the stored procedure. OUT parameters are
returned from the stored procedure; it assigns values to all OUT parameters
that the user can process. INOUT parameters combine the properties of IN and
OUT parameters: They contain values to be passed to the stored procedures, and
the stored procedure can set their values as return values.
IN parameters: By default procedure or function parameters are IN parameters.

CREATE OR REPLACE PROCEDURE display_numbers (


p_lower IN NUMBER,
p_upper IN NUMBER)
AS
BEGIN
FOR i IN p_lower .. p_upper LOOP
DBMS_OUTPUT.put_line(i);
END LOOP;
END;
/

SET SERVEROUTPUT ON
EXECUTE display_numbers(2, 6);
2
3
4
5
6

PL/SQL procedure successfully completed.

Proc1.sql
create or replace procedure add(n1 in int,n2 in int,result out int)
as
begin
result :=n1+n2;
end;

sql>@proc1.sql

sql>edit proc2.sql

declare
result int;
begin
add(5,5,result);
dbms_output.put_line(result);
end;

sql>@proc2.sql

Functions:

Functions are similar to procedures but return a single value.

CREATE OR REPLACE FUNCTION difference (


p_lower IN NUMBER,
p_upper IN NUMBER)
RETURN NUMBER
AS
BEGIN
RETURN p_upper - p_lower;
END;
/

VARIABLE l_result NUMBER


BEGIN
:l_result := difference(2, 6);
END;
/

PL/SQL procedure successfully completed.

PRINT l_result

L_RESULT
----------
4

Example:

Sql>ed funtest.sql

CREATE OR REPLACE FUNCTION GET_DOUBLE(X NUMBER)

RETURN NUMBER AS

BEGIN

RETURN X * 2;

END;

SQL> @funtest

Function created.

SQL> select get_double(2) from dual;

GET_DOUBLE(2)

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

Packages:

Packages allow related code, along with supporting types, variables and cursors, to be grouped together.
The package is made up of a specification that defines the external interface of the package, and a body
that contains all the implementation code. The following code shows how the previous procedure and
function could be grouped into a package.
CREATE OR REPLACE PACKAGE my_package AS

PROCEDURE display_numbers (
p_lower IN NUMBER,
p_upper IN NUMBER);

FUNCTION difference (
p_lower IN NUMBER,
p_upper IN NUMBER)
RETURN NUMBER;

END;
/

CREATE OR REPLACE PACKAGE BODY my_package AS

PROCEDURE display_numbers (
p_lower IN NUMBER,
p_upper IN NUMBER)
AS
BEGIN
FOR i IN p_lower .. p_upper LOOP
DBMS_OUTPUT.put_line(i);
END LOOP;
END;

FUNCTION difference (
p_lower IN NUMBER,
p_upper IN NUMBER)
RETURN NUMBER
AS
BEGIN
RETURN p_upper - p_lower;
END;

END;
/

Once the package specification and body are compiled they can be executed as before, provided the
procedure and function names are prefixed with the package name.

SET SERVEROUTPUT ON
EXECUTE my_package.display_numbers(2, 6);
2
3
4
5
6

PL/SQL procedure successfully completed.

VARIABLE l_result NUMBER


BEGIN
:l_result := my_package.difference(2, 6);
END;
/

PL/SQL procedure successfully completed.

PRINT l_result

L_RESULT
----------
4

How To Use "OUT" Parameter Properly?

Here are the rules about OUT parameters:


 A formal OUT parameter acts like an un-initialized variable. It must be assigned with new values before the
end of the procedure or function.
 An actual OUT parameter must be a variable.
 An actual OUT parameter will not pass any value to the formal parameter.
 An actual OUT parameter will receive a copy of the value from the formal parameter at the end of the
procedure or function.
Example:
create or replace procedure sum(a in number,b in number,c out number)
as
begin
c:=a+b;
dbms_output.put_line('a+b='||c);
end sum;
/
To execute the above procedure:
Method1:
Use the bind variables for procedure parameters
SQL> set serverout on
SQL> var a number;
SQL> var b number;
SQL> var c number;
SQL> begin
2 :a:=5;
3 :b:=8;
4 sum(:a,:b,:c);
5 end;
6 /
a+b=13
PL/SQL procedure successfully completed.
Method2:
Create a procedure as follows and save it in ptest.sql
sum
declare
a number;
b number;
c number;
procedure sum(a in number,b in number,c out number)
as
begin
c:=a+b;
end sum;
begin
a:=&a;
b:=&b;
sum(a,b,c);
dbms_output.put_line('a+b='||c);
end ;
/
SQL>@ptest.sql

Method 3

How To Use "IN OUT" Parameter Properly?

Here are the rules about IN OUT parameters:


 A formal IN OUT parameter acts like an initialized variable.
 An actual IN OUT parameter must be a variable.
 An actual IN OUT parameter passes a copy of its value to the formal parameter when entering the
procedure or function.
 An actual IN OUT parameter will receive a copy of the value from the formal parameter at the end of the
procedure or function
Example:
create or replace procedure test1 as
a number;
b number;
procedure swap(a in out number,b in out number)
as
begin
a:=a+b;
b:=a-b;
a:=a-b;
end swap;
begin
a:=&a;
b:=&b;
dbms_output.put_line('a='||to_char(a)||',b='||to_char(b));
swap(a,b);
dbms_output.put_line('a='||to_char(a)||',b='||to_char(b));
end test1;
/
Execution
SQL> @two
Enter value for a: 23
old 2: a number:=&a;
new 2: a number:=23;
Enter value for b: 45
old 3: b number:=&b;
new 3: b number:=45;
Procedure created.

SQL> exec test1


a=23,b=45
a=45,b=23
PL/SQL procedure successfully completed.

CREATE OR REPLACE FUNCTION totalCustomers


RETURN number IS
total number(2) := 0;
BEGIN
SELECT count(*) into total
FROM customers;

RETURN total;
END;
/

Example: Using %ROWTYPE with a PL/SQL Record

Proc2.sql

CREATE OR REPLACE PROCEDURE PROC2 AS


-- declare record variable that represents a row fetched from the ----
-- employees table
emp_rec employees%ROWTYPE;
-- declare variable with %ROWTYPE attribute
BEGIN
SELECT * INTO emp_rec FROM EMPLOYEES WHERE employee_id = 120;
-- retrieve record
DBMS_OUTPUT.PUT_LINE('Employee name: ' || emp_rec.first_name || ' '
|| emp_rec.last_name); -- display
END;
/

Proc1.sql
create or replace procedure proc1 as
empid emp.empno%TYPE; -- employee_id datatype is NUMBER(6)
emplname emp.ename%TYPE; -- last_name datatype is VARCHAR2(25)
BEGIN
empid:= 7900; -- this is OK because it fits in NUMBER(6)
-- empid := 3018907; -- this is too large and will cause an overflow
emplname:= 'Patel'; -- this is OK because it fits in VARCHAR2(25)
DBMS_OUTPUT.PUT_LINE('Employee ID: ' || empid); -- display data
DBMS_OUTPUT.PUT_LINE('Employee name: ' || emplname); -- display dataet
update emp set ename=emplname where empno=empid;
END;
/

CURSORS
A cursor is a pointer to a private SQL area that stores information about the processing of a
SELECT or data manipulation language (DML) statement (INSERT, UPDATE, DELETE,
or MERGE). Cursor management of DML statements is handled by Oracle Database, but
PL/SQL offers several ways to define and manipulate cursors to execute SELECT
statements.

Explicit Cursor vs Implicit Cursor


 Implicit cursors are automatically created and used every time a Select statement is issued in
PL/SQL, when there is no explicitly defined cursor. Explicit cursors, as the name suggests, are
defined explicitly by the developer. In PL/SQL an explicit cursor is actually a named query
defined using the key word cursor.
 Implicit cursors are automatically created and used by Oracle each time a select statement is
issued. If an implicit cursor is used, the Database Management System (DBMS) will perform the
open, fetch and close operations automatically. Implicit cursors should be used only with SQL
statements that return a single row. If the SQL statement returns more than one row, using an
implicit cursor will introduce an error. An implicit cursor is automatically associated with each
Data Manipulation Language (DML) statements, namely INSERT, UPDATE and DELETE
statements. Also, an implicit cursor is used to process SELECT INTO statements. When fetching
data using implicit cursors NO_DATA_FOUND exception can be raised when the SQL statement
returns no data. Furthermore, implicit cursors can raise TOO_MANY_ROWS exceptions when
the SQL statement returns more than one row.
 explicit cursors are queries defined using a name. An explicit cursor can be thought of as a
pointer to a set of records and the pointer can be moved forward within the set of records. Explicit
cursors provide the user the complete control over opening, closing and fetching data. Also,
multiple rows can be fetched using an explicit cursor. Explicit cursors can also take parameters
just like any function or procedure so that the variables in the cursor can be changed each time it
is executed. In addition, explicit cursors allow you to fetch a whole row in to a PL/SQL record
variable. When using an explicit cursor, first it needs to be declared using a name. Cursor
attributes can be accessed using the name given to cursor. After declaring, cursor needs to be
opened first. Then fetching can be started. If multiple rows need to be fetched, the fetching
operation needs to be done inside a loop. Finally, the cursor needs to be closed.
 PL/SQL creates implicit cursor and manages automatically means implcit open & close takes
place. It used when sql statement return only one row.It has 4 attributes SQL%ROWCOUNT,
SQL%FOUND, SQL%NOTFOUND, SQL%ISOPEN.
 .EXPLICIT: It is created & managed by the programmer. It needs every time explicit open,fetch &
close. It is used when sql statement returns more than one row. It has also 4 attributes
CUR_NAME%ROWCOUNT, CUR_NAME%FOUND, CUR_NAME%NOTFOUND, CUR_NAME
%ISOPEN. It process several rows by using loop. The programmer can pass the parameter too
to explicit cursor

S.N Attribute & Description


o

%FOUND

1 Returns TRUE if an INSERT, UPDATE, or DELETE statement affected one or


more rows or a SELECT INTO statement returned one or more rows.
Otherwise, it returns FALSE.
%NOTFOUND

The logical opposite of %FOUND. It returns TRUE if an INSERT, UPDATE, or


2
DELETE statement affected no rows, or a SELECT INTO statement returned
no rows. Otherwise, it returns FALSE.

%ISOPEN

3 Always returns FALSE for implicit cursors, because Oracle closes the SQL
cursor automatically after executing its associated SQL statement.

%ROWCOUNT

4 Returns the number of rows affected by an INSERT, UPDATE, or DELETE


statement, or returned by a SELECT INTO statement.
Implicit Cursor:

Implicit cursors are automatically created by Oracle whenever an SQL statement is


executed, when there is no explicit cursor for the statement. Programmers cannot control
the implicit cursors and the information in it.

Whenever a DML statement (INSERT, UPDATE and DELETE) is issued, an implicit


cursor is associated with this statement. For INSERT operations, the cursor holds the data
that needs to be inserted. For UPDATE and DELETE operations, the cursor identifies the
rows that would be affected.

Select * from customers;

+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
+----+----------+-----+-----------+----------+

DECLARE

total_rows number(2);

BEGIN

UPDATE customers

SET salary = salary + 500;

IF sql%notfound THEN

dbms_output.put_line('no customers selected');

ELSIF sql%found THEN

total_rows := sql%rowcount;

dbms_output.put_line( total_rows || ' customers selected ');

END IF;

END;

When the above code is executed at the SQL prompt, it produces the following
result −
6 customers selected
PL/SQL procedure successfully completed.

If you check the records in customers table, you will find that the rows have been
updated –
Select * from customers;

+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2500.00 |
| 2 | Khilan | 25 | Delhi | 2000.00 |
| 3 | kaushik | 23 | Kota | 2500.00 |
| 4 | Chaitali | 25 | Mumbai | 7000.00 |
| 5 | Hardik | 27 | Bhopal | 9000.00 |
| 6 | Komal | 22 | MP | 5000.00 |
+----+----------+-----+-----------+----------+

Example 1 of an Implicit cursors

In the following PL/SQL code block, the select statement makes use of an implicit cursor:

Begin
Update emp Where 1=2;
Dbms_output.put_line (sql%rowcount ||’ ‘|| ‘ rows are affected by the update statement’);
End;

SELECT SUM (sal) INTO TOTAL


FROM emp
WHERE depno = 10;

Another Example of an Implicit cursor

The following single-row query calculates and returns the total salary for a department.
PL/SQL creates an implicit cursor for this statement:

SELECT SUM (salary) INTO department_total


FROM employee
WHERE department_number = 10;

An Example of PL/SQL Attribute

DECLARE
rows_deleted NUMBER;
BEGIN
DELETE * FROM emp;
rows_deleted := SQL%ROWCOUNT;
END;

Explicit Cursors
Explicit cursors are programmer-defined cursors for gaining more control over
the context area. An explicit cursor should be defined in the declaration section of
the PL/SQL Block. It is created on a SELECT Statement which returns more than one
row.

The syntax for creating an explicit cursor is −


CURSOR cursor_name IS select_statement;

Working with an explicit cursor includes the following steps −

 Declaring the cursor for initializing the memory

 Opening the cursor for allocating the memory

 Fetching the cursor for retrieving the data

 Closing the cursor to release the allocated memory

Declaring the Cursor


Declaring the cursor defines the cursor with a name and the associated SELECT
statement. For example −

CURSOR c_customers IS

SELECT id, name, address FROM customers;

Opening the Cursor


Opening the cursor allocates the memory for the cursor and makes it ready for
fetching the rows returned by the SQL statement into it. For example, we will open
the above defined cursor as follows −

OPEN c_customers;

Fetching the Cursor


Fetching the cursor involves accessing one row at a time. For example, we will fetch
rows from the above-opened cursor as follows −

FETCH c_customers INTO c_id, c_name, c_addr;

Closing the Cursor


Closing the cursor means releasing the allocated memory. For example, we will
close the above-opened cursor as follows −

CLOSE c_customers;

Example
Following is a complete example to illustrate the concepts of explicit cursors

DECLARE

c_id customers.id%type;

c_name customerS.No.ame%type;

c_addr customers.address%type;

CURSOR c_customers is

SELECT id, name, address FROM customers;

BEGIN

OPEN c_customers;

LOOP

FETCH c_customers into c_id, c_name, c_addr;

EXIT WHEN c_customers%notfound;

dbms_output.put_line(c_id || ' ' || c_name || ' ' || c_addr);

END LOOP;

CLOSE c_customers;

END;

When the above code is executed at the SQL prompt, it produces the following
result −
1 Ramesh Ahmedabad
2 Khilan Delhi
3 kaushik Kota
4 Chaitali Mumbai
5 Hardik Bhopal
6 Komal MP

PL/SQL procedure successfully completed.

declare
cursor emp_cursor
is
select id,name,salary,dept_id
from employees;
v_id employees.id%type;
v_name employees.name%type;
v_salary employees.salary%type;
v_dept_id employees.dept_id%type;
begin
open emp_cursor;
loop
fetch emp_cursor into v_id,v_name,v_salary,v_dept_id;
exit when emp_cursor%notfound;
dbms_output.put_line(v_id||', '||v_name||', '||v_salary||','||v_dept_id);
end loop;
close emp_cursor;
end;

Embedded SQL

Conceptually, embedding SQL commands in a host language program is


straightforward. SQL statements (i.e., not declarations) can be used wherever a
statement in the host language is allowed (with a few restrictions). An embedded SQL
program must be processed by a special preprocessor prior to compilation. The
preprocessor replaces embedded SQL requests with host-language declarations and
procedure calls that allow run-time execution of the database accesses. Then, the
resulting program is compiled by the host-language compiler. Also, any host language
variables used to pass arguments into an SQL command must be declared in SQL.

There are, however, two complications to bear in mind. First, the data types recognized by
SQL may not be recognized by the host language and vice versa. This mismatch is
typically addressed by casting data values appropriately before passing them to or from
SQL commands. The second complication has to do with SQL being set-oriented, and is
addressed using cursors. Commands operate on and produce tables, which are sets.

1. Declaring Variables and Exceptions


SQL statements can refer to variables defined in the host program. Such host language
variables must be prefixed by a colon (:) in SQL statements and be declared between the
commands EXEC SQL BEGIN DECLARE SECTION and EXEC SQL END DECLARE
SECTION.

For example. we can declare variables c-sname, c_sid, c_rating, and c_age (with the
initial c used as a naming convention to emphasize that these are host language
variables) as follows:

EXEC SQL BEGIN DECLARE SECTION


char c_sname[20];
long c_sid;
short c_rating;
float c_age;
EXEC SQL END DECLARE SECTION
The SQL-92 standard defines such a correspondence between the host language types and
SQL types for a number of host languages. In our example, c_sname has the type
CHARACTER(20) when referred to in an SQL statement, c_sid has the type INTEGER,
c_rating has the type SMALLINT, and c_age has the type REAL.

We also need some way for SQL to report what went wrong if an error condition
arises when executing an SQL statement. The SQL-92 standard recognizes two special
variables for reporting errors, SQLCODE and SQLSTATE. SQLCODE is defined to return
some negative value when an error condition arises, SQLSTATE associates predefined
values with several common error conditions, thereby introducing some uniformity to how
errors are reported. The appropriate C type for SQLCODE is long and the appropriate C
type for SQLSTATE is char [6] , that is, a character string five characters long.

Embedding SQL Statements


To identify embedded SQL requests to the preprocessor,we use the EXEC SQL statement;
it has the form
EXEC SQL <embedded SQL statement > END-EXEC
The exact syntax for embedded SQL requests depends on the language.
SQL statements must be prefixed by EXEC SQL. An SQL statement can essentially appear
in any place in the host language program where a host language statement can appear.

As a simple example, the following EmbeddedSQL statement inserts a row, whose column
values me based on the values of the host language variables contained in it, into the
Sailors relation:

EXEC SQL
INSERT INTO Sailors VALUES (:c_sname, :csid, :crating, :cage);

The SQLSTATE variable should be checked for errors and exceptions after each
Embedded SQL statement. SQL provides the WHENEVER command to simplify
this tedious task:

EXEC SQL WHENEVER [SQLERROR | NOT FOUND] [ CONTINUE |GOTO stmt ]

The intent is that the value of SQLSTATE should be checked after each Embedded
SQL statement is executed. If SQLERROR is specified and the value of SQLSTATE
indicates an exception, control is transferred to stmt, which is presumably responsible
for error and exception handling. Control is also transferred to stmt.if NOT FOUND is
specified and the value of SQLSTATE is 02000, which denotes NO DATA.

SQLCA (SQL communication area), the definition of SQLCA must be included in the C
program by including the following line:

EXEC SQL include SQLCA ;


Example:

int main() {
EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION;
int OrderID; /* Employee ID (from user) */
int CustID; /* Retrieved customer ID */
char SalesPerson[10] /* Retrieved salesperson name */
char Status[6] /* Retrieved order status */
EXEC SQL END DECLARE SECTION;

/* Set up error processing */


EXEC SQL WHENEVER SQLERROR GOTO query_error;
EXEC SQL WHENEVER NOT FOUND GOTO bad_number;

EXEC SQL connect to system user using RadhaSarma

/* Prompt the user for order number */


printf ("Enter order number: ");
scanf("%d", &OrderID);

/* Execute the SQL query */


EXEC SQL SELECT CustID, SalesPerson, Status
FROM Orders
WHERE OrderID = :OrderID
INTO :CustID, :SalesPerson, :Status;

/* Display the results */


printf ("Customer number: %d\n", CustID);
printf ("Salesperson: %s\n", SalesPerson);
printf ("Status: %s\n", Status);
exit();

query_error:
printf ("SQL error: %ld\n", sqlca->sqlcode);
exit();

bad_number:
printf ("Invalid order number.\n");
exit();
}

2. Cursors
Cursors enable us to examine, in the host language program, a collection of
rows computed by an Embedded SQL statement.
When a query returns multiple rows, you can explicitly define a cursor to
 Process beyond the first row returned by the query
 Keep track of which row is currently being processed
A major problem in embedding SQL statements in a host language like C is that an
impedance mismatch occurs because SQL operates on set of records, whereas languages
like C do not cleanly support a set-of-records abstraction. The solution is to essentially
provide a mechanism that allows us to retrieve rows one at a time from a relation. This
mechanism is called a cursor.
We can declare a cursor on any relation or on any SQL query (because every query returns
a set of rows). Once a cursor is declared, we can open it (which positions the cursor just
before the first row); fetch the next row; move the cursor (to the next row, to the row after
the next n, to the first row, or to the previous row, etc., by specifying additional parameters
for the FETCH command); or close the cursor. Thus, a cursor essentially allows us to
retrieve the rows in a table by positioning the cursor at a particular row and reading its
contents.

General Options for a Cursor Declaration. Several options can be specified when
declaring a cursor. The general form of a cursor declaration is as follows:

DECLARE <cursor name> [ INSENSITIVE ] [ SCROLL ] CURSOR


[ WITH HOLD ] FOR <query specification>
[ ORDER BY <ordering specification> ]
[ FOR READ ONLY | FOR UPDATE [ OF <attribute list> ] ] ;

The default is that the query is for retrieval purposes (FOR READ ONLY). If some of the
tuples in the query result are to be updated, we need to specify FOR UPDATE OF
<attribute list> and list the attributes that may be updated. If some tuples are to be deleted,
we need to specify FOR UPDATE without any attributes listed.

When the optional keyword SCROLL is specified in a cursor declaration, it is


possible to position the cursor in other ways than for purely sequential access. A
fetch orientation can be added to the FETCH command, whose value can be one of
NEXT, PRIOR, FIRST, LAST, ABSOLUTE i, and RELATIVE i. The fetch
orientation allows the programmer to move the cursor around the tuples in the query
result with greater flexibility, providing random access by position or access in
reverse order.

The ORDER BY clause orders the tuples so that the FETCH command will fetch
them in the specified order.
You use the CURRENT OF cursor_name clause in a DELETE or UPDATE statement to refer
to the latest row fetched from the named cursor. The cursor must be open and positioned on a
row. If no fetch has been done or if the cursor is not open, the CURRENT OF clause results in
an error and processes no rows.

The FOR UPDATE OF clause is optional when you declare a cursor that is referenced in the
CURRENT OF clause of an UPDATE or DELETE statement. The CURRENT OF clause
signals the precompiler to add a FOR UPDATE clause if necessary

If the keyword INSENSITIVE is specified, the cursor behaves as if it is ranging over a private
copy of the collection of answer rows. Otherwise, and by default, other actions of some
transaction could modify these rows, creating unpredictable behavior. If INSENSITIVE is not
specified, the behavior is implementation dependent in this situation.
A holdable cursor is specified using the WITH HOLD clause, and is not closed when the
transaction is continued.Cursors are usually closed automatically at the end of a transaction,
i.e. when a COMMIT or ROLLBACK (or an implicit termination of the transaction)
occurs. That behavior can be changed if the cursor is declared using the WITH HOLD
clause.

#include <stdio.h>

EXEC SQL
BEGIN DECLARE SECTION;
char deptname[26];
char lname[16];
char fname[11];
EXEC SQL
END DECLARE SECTION;

main ()
{
EXEC SQL
WHENEVER SQLERROR GO TO abend;
EXEC SQL
DECLARE DEPT_EMP CURSOR FOR
SELECT DEPARTMENT, LAST_NAME, FIRST_NAME
FROM DEPARTMENT D, EMPLOYEE E
WHERE D.DEPT_NO = E.DEPT_NO
ORDER BY DEPARTMENT, LAST_NAME, FIRST_NAME;

EXEC SQL connect to system user using RadhaSarma


EXEC SQL
OPEN DEPT_EMP;
EXEC SQL
FETCH DEPT_EMP

SELECT DNAME, LASTNAME,FIRSTNAME


INTO :deptname, :lname, :fname;

while (!SQLCODE)
{
printf("%s %s works in the %s department.\n",fname,
lname, deptname);
EXEC SQL
FETCH DEPT_EMP
INTO :deptname, :lname, :fname;
}
EXEC SQL
CLOSE DEPT_EMP;
exit();

abend:
if (SQLCODE)
{
isc_print_sqlerror();
EXEC SQL
ROLLBACK;
EXEC SQL
CLOSE_DEPT_EMP;
EXEC SQL
DISCONNECT ALL;
exit(1)
}
else
{
EXEC SQL
COMMIT;
EXEC SQL
DISCONNECT ALL;
exit()
}

}
Triggers
What are triggers?

Triggers are named PL/SQL blocks which are stored in the database or we can also say that
they are specialized stored programs which execute implicitly when a triggering event occurs
which means we cannot call and execute them directly instead they only get triggered by
events in the database.

Events Which Fires the Triggers

These events can be anything such as

1. A DML Statement. For example Update, Insert or Delete, 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 statement. Or you can create a trigger which will get triggered
after the execution of your INSERT DML statement.
2. 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 such as 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 system event I
mean shut down or startup of your database.
4. 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
and record the information such as time of event occur, the username who created it.

Differences between Procedures and Triggers

A procedure is executed explicitly from another block via a procedure call with passing
arguments, while a trigger is executed (or fired) implicitly whenever the triggering
event (DML: INSERT, UPDATE, or DELETE) happens, and a trigger doesn't accept
arguments.

When triggers are used?

• Auditing information in a table by recording the changes.


• Automatically signaling other programs that action needs to take place when changes are
made to a table
• Collecting/maintaining statistical data.

How to Create Trigger


Below is the syntax for creating a trigger.

Trigger names

Triggers exist in a separate namespace from procedure, package, tables (that share the same
namespace), which means that a trigger can have the same name as a table or procedure.

Triggering Event or Statement

A triggering event or statement is the SQL statement that causes a trigger to be fired. A
triggering event can be an INSERT, UPDATE, or DELETE statement on a table, a DML event
or a DDL event or system event or a user event

Trigger Restriction or condition

A trigger restriction specifies a Boolean (logical) expression that must be TRUE for the trigger
to fire. The trigger action is not executed if the trigger restriction evaluates to FALSE or
UNKNOWN.

A trigger restriction is an option available for triggers that are fired for each row. Its function
is to control the execution of a trigger conditionally. You specify a trigger restriction using a
WHEN clause.

Trigger Action

A trigger action is the procedure (PL/SQL block) that contains the SQL statements and
PL/SQL code to be executed when a triggering statement is issued and the trigger restriction
evaluates to TRUE.
Similar to stored procedures, a trigger action can contain SQL and PL/SQL statements, define
PL/SQL language constructs (variables, constants, cursors, exceptions, and so on), and call
stored procedures. Additionally, for row trigger, the statements in a trigger action have access
to column values (new and old) of the current row being processed by the trigger. Two
correlation names provide access to the old and new values for each column.

Types of Triggers
There are 5 types of triggers in oracle database in which 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 and 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 and get fired either before or after 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:
(a) before the firing statement;
(b) prior to change of each row from the firing statement;
(c) post each row changes from the firing statement;
(d) 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 row event levels.

Types of triggers

There are two types of triggers in Oracle including row-level triggers and statement-level
triggers

Row-level triggers for data-related activities

• Row-level triggers execute once for each row in a transaction.


• Row-level triggers are the most common type of triggers; they are often used in data auditing
applications.
• Row-level trigger is identified by the FOR EACH ROW clause in the CREATE TRIGGER
command.

Statement-level triggers for transaction-related activities

• Statement-level triggers execute once for each transaction. For example, if a single
transaction inserted 500 rows into the Customer table, then a statement-level trigger on that
table would only be executed once.
• Statement-level triggers therefore are not often used for data-related activities; they are
normally used to enforce additional security measures on the types of transactions that may
be performed on a table.
• Statement-level triggers are the default type of triggers created and are identified
by omitting the FOR EACH ROW clause in the CREATE TRIGGER command.
Before and After Triggers

• Since triggers occur because of events, they may be set to occur immediately before or after
those events. The events that execute triggers are database transactions, triggers can be
executed immediately BEFORE or AFTER the statements INSERTs, UPDATEs, DELETEs.
• AFTER row-level triggers are frequently used in auditing applications, since they do not fire
until the row has been modified.
Clearly, there is a great deal of flexibility in the design of a trigger.

Valid trigger types (possible combination of triggers)

• Statement (INSERT, DELETE, UPDATE), Timing (BEFORE, AFTER),


Level (Row-level, Statement-level)
The values for the statement, timing, and level determine the types of the triggers. There are
total of 12 possible types of triggers: 3*2*2 = 12

Combining Trigger Types

• Triggers for multiple INSERT, UPDATE, DELETE commands on a table can be combined
into a single trigger (using OR), provided they are all at the same level (row-level or
statement-level), e.g., INSERT OR UPDATE OR DELETE.
• However, you can not combine BEFORE or AFTER, e.g., BEFORE OR AFTER is illegal.

:NEW and :OLD Clause

In a row level trigger, the trigger fires for each related row. And sometimes it is required to know the value
before and after the DML statement.

Oracle has provided two clauses in the RECORD-level trigger to hold these values. We can use these
clauses to refer to the old and new values inside the trigger body.

:NEW – It holds a new value for the columns of the base table/view during the trigger execution

:OLD – It holds old value of the columns of the base table/view during the trigger execution

This clause should be used based on the DML event. Below table will specify which clause is valid for
which DML statement (INSERT/UPDATE/DELETE).

INSERT UPDATE DELETE

:NEW VALID VALID INVALID. There is no new value in delete


case.

:OLD INVALID. There is no old value in insert VALID VALID


case
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)
);

SET SERVEROUTPUT ON;

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;
/

aOn 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');

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';

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';

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;
/

A database that has a set of associated triggers is called an active database.

Example2:(statement level trigger)


Write a trigger on emp table that allows updation, deletion, insertion should be done
within office hours.
CREATE OR REPLACE TRIGGER chkemp
BEFORE INSERT OR DELETE OR UPDATE ON emp
BEGIN
IF TO_NUMBER(TO_CHAR(SYSDATE,’HH24’)) NOT BETWEEN 10 AND 16 THEN

RAISE_APPLICATION_ERROR(-2001,’INVALID TIME’);

END IF;

END;

Using the RAISE_APPLICATION_ERROR procedure


Use the RAISE_APPLICATION_ERROR procedure in the executable section or exception
section (or both) of your PL/SQL program. TimesTen reports errors to your application so you
can avoid returning unhandled exceptions.

Use an error number between -20,000 and -20,999. Specify a character string up to 2,048 bytes for
your message.
CREATE OR REPLACE TRIGGER chkemp
BEFORE INSERT OR DELETE OR UPDATE ON emp
declare
INVALID_TIME exception;
BEGIN
IF TO_NUMBER(TO_CHAR(SYSDATE,'HH24')) NOT BETWEEN 10 AND 16 THEN
RAISE INVALID_TIME;
END IF;
rollback;
EXCEPTION
WHEN INVALID_TIME THEN
DBMS_OUTPUT.PUT_LINE ('Not correct time for modification of emp');
DBMS_OUTPUT.PUT_LINE (SQLERRM);
DBMS_OUTPUT.PUT_LINE (SQLCODE);

END;
/
A TRIGGER doesn't scale in a cost effective manner .

Data manipulation (INSERT, UPDATE, DELETE) often requires locks on tables, and even on
indexes. That impedes other users access to data. The more code that must execute in the
TRIGGER, the longer the locks are being held, the longer the disruption to other users, the higher
the block/deadlock frequency.

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 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.

Trigger For Auditing


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
varchar2 (30); v_user
varchar2(30); v_date
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;

Example2:

Select * from customers;

+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
+----+----------+-----+-----------+----------+

CREATE OR REPLACE TRIGGER display_salary_changes

BEFORE DELETE OR INSERT OR UPDATE ON customers

FOR EACH ROW

WHEN (NEW.ID > 0)

DECLARE

sal_diff number;

BEGIN

sal_diff := :NEW.salary - :OLD.salary;

dbms_output.put_line('Old salary: ' || :OLD.salary);

dbms_output.put_line('New salary: ' || :NEW.salary);

dbms_output.put_line('Salary difference: ' || sal_diff);

END;

Triggering a Trigger
Let us perform some DML operations on the CUSTOMERS table. Here is one INSERT
statement, which will create a new record in the table −

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)

VALUES (7, 'Kriti', 22, 'HP', 7500.00 );


When a record is created in the CUSTOMERS table, the above create
trigger, display_salary_changes will be fired and it will display the following result

Old salary:
New salary: 7500
Salary difference:

Because this is a new record, old salary is not available and the above result comes
as null. Let us now perform one more DML operation on the CUSTOMERS table. The
UPDATE statement will update an existing record in the table −

UPDATE customers

SET salary = salary + 500

WHERE id = 2;

When a record is updated in the CUSTOMERS table, the above create


trigger, display_salary_changes will be fired and it will display the following result

Old salary: 1500
New salary: 2000
Salary difference: 500
JDBC Driver

JDBC Driver is a software component that enables java application to interact with the
database. There are 4 types of JDBC drivers:

1. JDBC-ODBC bridge driver, also called Type 1.


2. Native-API driver (partially java driver), also called Type 2.
3. Network Protocol driver (fully java driver), also called Type 3.
4. Thin driver (fully java driver), also called Type 4.

1) JDBC-ODBC bridge driver

The JDBC-ODBC bridge driver uses ODBC driver to connect to the database. The JDBC-
ODBC bridge driver converts JDBC method calls into the ODBC function calls. This is
now discouraged because of thin driver.

Functions:

1. Translates query obtained by JDBC into corresponding ODBC query, which is then
handled by the ODBC driver.
2. Sun provides a JDBC-ODBC Bridge driver. sun.jdbc.odbc.JdbcOdbcDriver. This
driver is native code and not Java, and is closed
source.
3. Client -> JDBC Driver -> ODBC Driver -> Database
4. There is some overhead associated with the translation work to go from JDBC to
ODBC.
Advantages:

o easy to use.
o can be easily connected to any database.

Disadvantages:

o Performance degraded because JDBC method call is converted into the ODBC
function calls.
o The ODBC driver needs to be installed on the client machine.

2) Native-API driver

The Native API driver uses the client-side libraries of the database. The driver converts
JDBC method calls into native calls of the database API. It is not written entirely in java.

Functions:

1. This type of driver converts JDBC calls into calls to the client API for that database.
2. Client -> JDBC Driver -> Vendor Client DB Library -> Database

Advantage:
o performance upgraded than JDBC-ODBC bridge driver.

Disadvantage:
o The Native driver needs to be installed on the each client machine.
o The Vendor client library needs to be installed on client machine.
3) Network Protocol driver
The Network Protocol driver uses middleware (application server) that converts
JDBC calls directly or indirectly into the vendor-specific database protocol. It is fully
written in java.

Functions:
1. Follows a three tier communication approach.
2. Can interface to multiple databases - Not vendor specific.
3. The JDBC Client driver written in java, communicates with a middleware-net-server
using a database independent protocol, and then this net server translates this
request into database commands for that database.
4. Thus the client driver to middleware communication is database independent.
5. Client -> JDBC Driver -> Middleware-Net Server -> Any Database

Advantage:
o No client side library is required because of application server that can
perform many tasks like auditing, load balancing, logging etc.

Disadvantages:
o Network support is required on client machine.
o Requires database-specific coding to be done in the middle tier.
o Maintenance of Network Protocol driver becomes costly because it requires
database-specific coding to be done in the middle tier.

4) Thin driver
The thin driver converts JDBC calls directly into the vendor-specific database
protocol. That is why it is known as thin driver. It is fully written in Java language.

Functions
1. Type 4 drivers are entirely written in Java that communicate directly with a vendor's
database through socket connections. No translation or middleware layers, are
required, improving performance.
2. The driver converts JDBC calls into the vendor-specific database protocol so that
client applications can communicate directly with the database server.
3. Completely implemented in Java to achieve platform independence.
4. e.g include the widely used Oracle thin driver - oracle.jdbc.driver. OracleDriver which
connect to jdbc:oracle:thin URL format.
5. Client Machine -> Native protocol JDBC Driver -> Database server

Advantage:
o Better performance than all other drivers.
o No software is required at client side or server side.

Disadvantage:
 At client side, a separate driver is needed for each database.

Steps to connect a Java Application to Database


The following 5 steps are the basic steps involve in connecting a Java application with
Database using JDBC.

1. Register the Driver


2. Create a Connection
3. Create SQL Statement
4. Execute SQL Statement
5. Closing the connection

1. Register the Driver


Class.forName() is used to load the driver class explicitly.
Example to register with JDBC-ODBC Driver
1. Class.forName("oracle.jdbc.driver.OracleDriver");

2. Create a Connection
getConnection() method of DriverManager class is used to create a connection.
Syntax

getConnection(String url, String username, String password)

Example establish connection with Oracle Driver


Connection con = DriverManager.getConnection(

"jdbc:oracle:thin:@localhost:1521:XE","username","password");

3. Create SQL Statement


createStatement() method is invoked on current Connection object to create a SQL
Statement.
Syntax

public Statement createStatement() throws SQLException

Example to create a SQL statement

Statement s=con.createStatement();

4. Execute SQL Statement


executeQuery() method of Statement interface is used to execute SQL statements. This
method returns the object of ResultSet that can be used to get all the records of a table.
Syntax

public ResultSet executeQuery(String query) throws SQLException

Example to execute a SQL statement

ResultSet rs=s.executeQuery("select * from user");

while(rs.next())

System.out.println(rs.getString(1)+" "+rs.getString(2));

5. Closing the connection


After executing SQL statement you need to close the connection and release the session.
The close()method of Connection interface is used to close the connection.
Syntax

public void close() throws SQLException

Example of closing a connection

con.close();

Connecting to oracle Database using Thin Driver


Loading jar file:
To connect your java application with Oracle, you will also need to load ojdbc14.jar file.
This file can be loaded into 2 ways.

1. Copy the jar file into C:\Program Files\Java\jre7\lib\ext folder. or Set it


into classpath. C:>set classpath=c:\folder\ojdbc14.jar;.;

Example
Create a table in Oracle Database
create table emp(id number(10),name varchar2(20),salary number(5));

Insert some record into the table


insert into emp values(101,'adam',3000);
insert into emp values(102,'abhi',5000);

Accessing record from Student table in Java application


import java.sql.*;
class OracleCon{
public static void main(String args[]){
try{
//step1 load the driver class
Class.forName("oracle.jdbc.driver.OracleDriver");

//step2 create the connection object


Connection con=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe
","system","oracle");

//step3 create the statement object


Statement stmt=con.createStatement();

//step4 execute query


ResultSet rs=stmt.executeQuery("select * from emp");
while(rs.next())
System.out.println(rs.getInt(1)+" "+rs.getString(2)+" "+rs.getString(3));

//step5 close the connection object


con.close();

}catch(Exception e){ System.out.println(e);}

}
}
Output
101 adam 3000
102 abhi 5000

Procedure:

DECLARE
first_number NUMBER;
second_number NUMBER;

PROCEDURE swapn (num_one IN OUT NUMBER, num_two IN OUT NUMBER) IS


temp_num NUMBER;
BEGIN
temp_num := num_one;
num_one := num_two;
num_two := temp_num ;
END;

BEGIN

first_number := 10;
second_number := 20;
DBMS_OUTPUT.PUT_LINE('First Number = ' || TO_CHAR (first_number));
DBMS_OUTPUT.PUT_LINE('Second Number = ' || TO_CHAR (second_number));

-- Swap the values


DBMS_OUTPUT.PUT_LINE('Swapping the two values now.');
swapn(first_number, second_number);
-- Display the results
DBMS_OUTPUT.PUT_LINE('First Number = ' || to_CHAR (first_number));
DBMS_OUTPUT.PUT_LINE('Second Number = ' || to_CHAR (second_number));
END;
/
PL/sql block
declare

-- declare variable num1, num2


-- and temp of datatype number
num1 number;
num2 number;
temp number;

begin
num1:=1000;
num2:=2000;

-- print result before swapping


dbms_output.put_line('before');
dbms_output.put_line('num1 = '|| num1 ||' num2 = '|| num2);

-- swapping of numbers num1 and num2


temp := num1;
num1 := num2;
num2 := temp;

-- print result after swapping


dbms_output.put_line('after');
dbms_output.put_line('num1 = '|| num1 ||' num2 = '|| num2);

end;

You might also like