You are on page 1of 68

PL/SQL

 PL/SQL stands for Procedural Language/SQL

Need of PL/SQL
 Procedural Language/Structured Query Language is an
extension to SQL.

 PL/SQL provides programming facility to the users.

 Set of instructions that can be stored in the server as


Database Objects in compiled form.
PL SQL Client Engine
PLSQL Server Side
PLSQL Block structure
Declare => Optional

Begin => Mandatory

Exception => Optional

End; => Mandatory

/ => Executor
Types of variable
 PLSQL Variable

 Scalar
 Composite
 Reference
 LOB (large objects)

 Non-PLSQL Variable
 Bind variable or Host variable
Bind Variable
Bind Variable should be prefixed with a colon ( : )

variable v_id number;

Begin
SELECT EID INTO :v_id from employee2 where deptno=50;
End;
/

print v_id;
Conditional Constructs
 Conditional Constructs

 IF – THEN – ELSE
 IF – ELSIF-ELSE
 CASE

 Looping Constructs

 WHILE
 LOOP
 FOR
Conditional Constructs
 Conditional Constructs

 IF – THEN – ELSE
 IF – ELSIF-ELSE
 CASE
 Syntax for IF
IF condition THEN
sequence_of_statements
END IF;
 Syntax for IF – THEN – ELSE
IF condition THEN
sequence_of_statements1
ELSE
sequence_of_statements2
END IF;
Conditional Constructs
 Syntax for IF – ELSIF-ELSE
IF condition1 THEN
sequence_of_statements1
ELSIF condition2 THEN
sequence_of_statements2
ELSE
sequence_of_statements3
END IF;
 Syntax for CASE
CASE selector
WHEN expression1 THEN
sequence_of_statements1;
WHEN expression2 THEN
sequence_of_statements2; ... WHEN expressionN
THEN sequence_of_statementsN; [ELSE
sequence_of_statementsN+1;]
END CASE
Conditional Constructs
 Looping Constructs
 WHILE
 LOOP
 FOR
 Syntax for WHILE
WHILE condition LOOP
sequence_of_statements
END LOOP;

 Syntax for LOOP


LOOP
sequence_of_statements
END LOOP;
 Syntax for FOR
FOR counter IN [REVERSE] lower_bound..higher_bound
LOOP sequence_of_statements END LOOP;
Conditional Constructs
Example 1: using IF- THEN –ELSE

declare
salary number:=40000;
BEGIN
IF salary > 20000 THEN
dbms_output.put_line ('Software Engineer');
ELSE
dbms_output.put_line ('You are not a software Engineer');
END IF;
END;
/
Conditional Constructs
Example 2: using IF- THEN - ELSIF –ELSE
declare
grade char(1) :='A';
begin
IF grade = 'A' THEN
dbms_output.put_line('Excellent');
ELSIF grade = 'B' THEN
dbms_output.put_line('Very Good');
ELSIF grade = 'C' THEN
dbms_output.put_line('Good');
ELSIF grade = 'D' THEN
dbms_output.put_line('Fair');
ELSIF grade = 'F' THEN
dbms_output.put_line('Poor');
ELSE
dbms_output.put_line('No such grade');
END IF;
end;
Conditional Constructs
Example 3: using CASE

declare
grade char(1) :='C';
begin
CASE grade
WHEN 'A' THEN dbms_output.put_line('Excellent');
WHEN 'B' THEN dbms_output.put_line('Very Good');
WHEN 'C' THEN dbms_output.put_line('Good');
WHEN 'D' THEN dbms_output.put_line('Fair');
WHEN 'F' THEN dbms_output.put_line('Poor');
ELSE dbms_output.put_line('No such grade');
END CASE;
end;
/
Conditional Constructs
Example 4 : using LOOP

DECLARE
x NUMBER := 2;
BEGIN
LOOP
DBMS_OUTPUT.PUT_LINE('x =' || x);
x := x+2;
EXIT WHEN x > 10;
END LOOP;
end;
/
Conditional Constructs
Example 4 : using WHILE - LOOP

DECLARE
x NUMBER := 2;
BEGIN
while(x<=10) LOOP
DBMS_OUTPUT.PUT_LINE('x =' || x);
x := x+2;
END LOOP;
end;
/
Conditional Constructs
Example 5: using FOR
DECLARE
x NUMBER := 1;
BEGIN
FOR x IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE('x =' || x);
END LOOP;
end;
/
=======================
DECLARE
x NUMBER;
d number;
BEGIN
d:=&d;
FOR x IN REVERSE 1..d LOOP
DBMS_OUTPUT.PUT_LINE('x =' || x);
END LOOP;
end;
PLSQL CURSOR
A cursor is a pointer to the private memory area
allocated by the Oracle server.

There are two types of cursors:

Implicit: Created and managed internally by the


Oracle server to process SQL statements.
Explicit: Explicitly declared by the programmer
SQL Cursor Attributes for
Implicit Cursors
 SQL%FOUND

 SQL%NOTFOUND

 SQL%ROWCOUNT

 SQL%ISOPEN
Controlling Explicit Cursors
 Declare => Create a named SQL Area
 Open => Identify the active set
 Fetch => Load the current rows into
variables
 Check for rows? => Test for existing rows. Return to
FETCH if rows are found
 Close => Release the active set.
Cursor
DECLARE
emp_rec Employee2%rowtype;
CURSOR emp_cur IS
SELECT * FROM Employee2 WHERE salary > 5000;
BEGIN
OPEN emp_cur;
FETCH emp_cur INTO emp_rec;
dbms_output.put_line (emp_rec.ename|| ' ' ||
emp_rec.city);
CLOSE emp_cur;
END;
/
Cursor with Attributes
DECLARE

CURSOR emp_cur IS
SELECT ename,city FROM Employee2;
emp_rec emp_cur%rowtype;
BEGIN
IF NOT emp_cur%ISOPEN THEN
OPEN emp_cur;
END IF;
LOOP
FETCH emp_cur INTO emp_rec;
EXIT WHEN emp_cur%NOTFOUND;
dbms_output.put_line(emp_rec.ename|| ' ' ||emp_rec.city);
END LOOP;
close emp_cur;
END;
/
Locking Cursor
DECLARE
CURSOR emp_cur IS SELECT * FROM employee2
FOR UPDATE OF eid;
BEGIN
FOR emp_rec IN emp_cur
LOOP
UPDATE employee2 SET salary = (emp_rec.salary *2)
WHERE CURRENT OF emp_cur;
dbms_output.put_line(emp_rec.salary);
END LOOP;
END;
/
EXCEPTION
 Exception are raised during the run time
 It causes termination of program in oracle
 Handled by the Exception Handler which
consists of handlers for all the exceptions

Syntax:
EXCEPTION
WHEN exception_name THEN
sequence_of_statements1;
WHEN exception_name THEN
sequence_of_statements1;
WHEN OTHERS THEN
statement1;
statement2;
END;
Types of Exceptions
 Implicitly raised.
Predefined Server Exception
Non-Predefined Server Exception

 Explicitly raised.
 User Defined Exception
Sample predefined exceptions
Sample predefined exceptions:
– NO_DATA_FOUND
– TOO_MANY_ROWS
– INVALID_CURSOR
– ZERO_DIVIDE
– DUP_VAL_ON_INDEX
Example
declare
v_id employee2.eid%type;
v_name employee2.ename%type;
v_sal employee2.salary%type;

v_error_code number;
v_error_msg varchar2(225);

begin
select eid,ename,salary into v_id, v_name,v_sal from
employee2 where eid=05;
dbms_output.put_line('Emp id: ' || v_id || ', Emp name: ' ||
v_name);
Example
--v_sal := v_sal/0;
dbms_output.put_line('Salary is :'||v_sal);

--insert into employee2 values


--(09,'manoj','04-JAn-005',6589.25,'chennai','Admin');

if (v_sal < 1000) then


v_sal := v_sal*2;
dbms_output.put_line('Salary incre:' || v_sal);
End if;
Example
exception

when too_many_rows then


dbms_output.put_line('*** Exception: too many rows');
v_error_code := SQLCODE ;
v_error_msg := SQLERRM ;
dbms_output.put_line('*** Exception: Handled'||
v_error_code ||v_error_msg);
Example
when no_data_found then
dbms_output.put_line('*** Exception: no data');
when zero_divide then
dbms_output.put_line('*** Exception: Dont divide by
zero');
when dup_val_on_index then
dbms_output.put_line('*** Exception: Dont insert a
duplicate value on primary key column');
when case_not_found then
dbms_output.put_line('*** Exception: Give an else part');
Example
when others then
-- dbms_output.put_line('*** Exception: Handled');
v_error_code := SQLCODE ;
v_error_msg := SQLERRM ;
dbms_output.put_line('*** Exception: Handled'||
v_error_code ||v_error_msg);

end;
/
Subprogram
 A named block of code => Subprogram
 Types:
 Procedures => Performs action
 Functions => Computes Value
Procedure
Syntax:

CREATE OR REPLACE PROCEDURE <PROCEDURE_NAME>


(<PARAMETER> [MODE] <DATA TYPE>,)
IS/AS
[LOCAL VARIABLE DECLARATION]
BEGIN
PL/SQL EXECUTABLE STATEMENT
[EXCEPTION]
[EXCEPTION HANDLERS]
END [PROGRAM UNIT NAME];

Mode => IN , OUT, IN OUT.


Example 1
To Create:
---------------
create procedure pr(num in number)
as
begin
dbms_output.put_line(num||'welcome');
end pr;

To Execute:
---------------
execute pr(100);
Example 2 with OUT parameter
create or replace procedure empproc(eno in
number,empname out varchar)
as
begin
select ename into empname from employee2 where
eid=eno;
end;
/

variable nam varchar2(20);


exec empproc(02,:nam );
exec empproc(empname => :nam,eno =>05);
/
print nam;
Example 3 INOUT parameter
CREATE OR REPLACE PROCEDURE format_phone
(p_phone_no IN OUT VARCHAR2)
IS
BEGIN
p_phone_no := '(' || SUBSTR(p_phone_no,1,3) ||
')' || SUBSTR(p_phone_no,4,3) ||
'-' || SUBSTR(p_phone_no,7);
END format_phone;
/
Example 3 INOUT parameter

VARIABLE g_phone_no VARCHAR2(15)


BEGIN
:g_phone_no := '8006330575';
END;
/
PRINT g_phone_no
EXECUTE format_phone (:g_phone_no)
PRINT g_phone_no
Procedures and Exception

create or replace PROCEDURE emp_proc_excp (did number)


AS
nam varchar2(20);
BEGIN
SELECT ename into nam from employee2 where eid<5;
END emp_proc_excp ;
/
Procedures and Exception
create or replace procedure pr
as
begin
dbms_output.put_line('welcome');
emp_proc_excp (10);

exception
when too_many_rows then
dbms_output.put_line('*** Exception: too many rows');
end pr;
/

exec pr;
To Drop procedure
Syntax:

Drop Procedure <procedure name>

Example:

DROP PROCEDURE pr;

DROP PROCEDURE empproc;


Functions
Syntax:
-----------

CREATE [OR REPLACE] FUNCTION function_name


[(parameter1 [mode1] datatype1,
parameter2 [mode2] datatype2,
. . .)]
RETURN datatype
IS|AS
BEGIN
Sql stmts;
RETURN variablename| expression;
END;
Functions
CREATE OR REPLACE FUNCTION tax(p_value IN
NUMBER)
RETURN NUMBER IS
BEGIN
RETURN (p_value * 0.08);
END tax;
/

SELECT eid, ename, salary, tax(salary) FROM employee2


WHERE eid= 01;
To drop a Function

Syntax:

Drop function <function name>

Example:

DROP function tax;


Difference between Procedure
and Function
Procedures may or may not Function should return a value
return any value

Procedures should be Functions should be invoked.


executed.

3 types of modes can be Only IN mode can be used


used
Do not contain RETURN Must contain a RETURN
clause in the header clause in the header
Package
Package ,
Group logically related PL/SQL types, items, and
Subprograms.

• Consist of two parts:


– Specification => public in nature
– Body => private in nature
• Cannot be invoked, parameterized, or nested

• Allow the Oracle server to read multiple objects


into memory at once
Package Specification
Package Specification:
~~~~~~~~~~~~~~~~

CREATE [OR REPLACE] PACKAGE package_name


IS|AS
public type and item declarations
subprogram specifications
END package_name;
Package Body
Package Body:
~~~~~~~~~~~~
CREATE [OR REPLACE] PACKAGE BODY
package_name
IS|AS
private type and item declarations
subprogram bodies
END package_name;
Example
create or replace package emppack
as
procedure empproc(eno in number,empname out varchar);
end emppack;
/

create or replace package body emppack as


empname varchar2(20);
procedure empproc(eno in number,empname out varchar) is
begin
select ename into empname from employee2 where eid=eno;
end;
end emppack;
/
Example
To Execute:
----------------

variable nam varchar2(20);


execute emppack.empproc(02,:nam);
print nam;
Dropping Package
Syntax:

Drop package <package name>


Drop package body <package name>
Triggers
A trigger:
• Is a PL/SQL block or a PL/SQL procedure associated with a
table, view, schema, or the database

• Executes implicitly whenever a particular event takes place

• Can be either:
– Application trigger: Fires whenever an event occurs
with a particular application
– Database trigger: Fires whenever a data event (such
as DML) or system event (such as logon or
shutdown) occurs on a schema or database
Triggers
A triggering statement contains:

• Trigger timing
– For table: BEFORE, AFTER
– For view: INSTEAD OF

• Triggering event: INSERT, UPDATE, or DELETE


• Table name: On table, view
• Trigger type: Row or statement
• WHEN clause: Restricting condition
• Trigger body: PL/SQL block
Trigger Syntax
Syntax:

CREATE [OR REPLACE] TRIGGER trigger_name


Timing event1 [OR event2 OR event3]
ON table_name
trigger_body

CREATE OR REPLACE TRIGGER <TRIGGER_NAME>


[BEFORE/AFTER] [INSERT/UPDATE/DELETE]
ON <TABLE_NAME>
[FOR EACH ROW [WHEN triggering_condition]]
trigger_body;
Trigger
Example:

create or replace trigger trig1


before insert on employee2
begin
dbms_output.put_line('Welcome');
end;
/

insert into employee2(eid,ename) values(100,'Guru');


Trigger for a particular column
CREATE OR REPLACE TRIGGER check_salary1
BEFORE UPDATE OF salary ON employee2
FOR EACH ROW
WHEN (NEW.salary < OLD.salary)
BEGIN
dbms_output.put_line('Do not decrease salary.');
END;
/

update employee2 set salary = 2000 where eid=01;


Instead Of trigger

create table tab1(eno number,ename varchar2(30),sal


number(5,2),did number);

create table tab2(dno number, name varchar2(30));

create view myview as


select e.*,d.* from tab1 e,tab2 d where e.did=d.dno;
Instead Of trigger
create or replace trigger mytrig
instead of insert on myview
for each row
begin
if inserting then
insert into tab1 values(:new.eno,:new.ename,:new.sal,:new.did);
insert into tab2 values(:new.dno,:new.name);
end if;
End mytrig;

insert into myview values(1,'Pri',500,1,1,'hr');


DDL trigger
Example : Logoff and logon trigger

create table log_trig_table(user_id varchar2(20), log_date


timestamp, action varchar2(20));

CREATE OR REPLACE TRIGGER logon_trig


AFTER LOGON ON SCHEMA
BEGIN
INSERT INTO log_trig_table(user_id, log_date, action)
VALUES (USER, current_timestamp, 'Logging on');
END;
/
DDL trigger

CREATE OR REPLACE TRIGGER logoff_trig


BEFORE LOGOFF ON SCHEMA
BEGIN
INSERT INTO log_trig_table(user_id, log_date, action)
VALUES (USER, current_timestamp, 'Logging off');
END;
/
Calling the procedure from the
Trigger using CALL
create or replace procedure sum(a number,b number)
is
begin
dbms_output.put_line('The result is :' || (a+b));
end;
/

create or replace trigger callproc


before insert on employee2
call sum(10,20)
/
insert into employee2(eid) values(10);
Mutating Problem
create or replace trigger empcount
after delete on employee2
for each row
Declare
n number;
begin
select count(*) into n from employee2;
dbms_output.put_line('There are ' || n || ' Employees now');
end;
/
delete from employee2 where eid = 16;
Dropping a trigger

Syntax:

Drop trigger <trigger name>


Collections
Composite Data Types :

Types:
- PLSQL Records
- PLSQL Collections

PLSQL collection types:


- Tables
- Index By Table (Associative Array or PLSQL Table)
- Nested Table
- Varray
Table Type

DECLARE
TYPE emp_table_type is table of employee2%ROWTYPE
INDEX BY BINARY_INTEGER;
my_emp_table emp_table_type;
x NUMBER(3):= 5;
BEGIN
FOR i IN 1..x
LOOP
SELECT * INTO my_emp_table(i) FROM employee2
WHERE eid = i;
END LOOP;
Table Type

FOR i IN my_emp_table.FIRST..my_emp_table.LAST

LOOP
DBMS_OUTPUT.PUT_LINE(my_emp_table(i).ename ||
my_emp_table(i).city);
END LOOP;
END;
Nested Table
create type expr_type as object(cmpname varchar2(20),desig
varchar(10),yrs number(2));

create type expr_table as table of expr_type;

create table emp(name varchar2(20),expr expr_table)


nested table expr store as emp_expr_tab;

insert into emp values('Priya',


expr_table(expr_type('CTS','Engineer',3),
expr_type('HCL','Admin',2)));
Varrays
create or replace type addr as varray(3) of varchar2(10);

create table customer(cid number,cname varchar2(10),address


addr);

insert into customer values(100,'Priya',addr('123','Raja


St','Chennai'));

select * from customer;

select c.cname,n.* from customer c,table(c.address) n;


Dynamic SQL
CREATE OR REPLACE PROCEDURE delete_all_rows
(p_tab_name IN VARCHAR2, p_rows_del OUT NUMBER)
IS
cursor_name INTEGER;
BEGIN
cursor_name := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(cursor_name, 'DELETE FROM '||p_tab_name,
DBMS_SQL.NATIVE );
p_rows_del := DBMS_SQL.EXECUTE (cursor_name);
DBMS_SQL.CLOSE_CURSOR(cursor_name);
END;
/

VARIABLE deleted NUMBER


EXECUTE delete_all_rows('employee2', :deleted)
PRINT deleted
Execute Immediate
CREATE PROCEDURE del_rows
(p_table_name IN VARCHAR2,
p_rows_deld OUT NUMBER)
IS
BEGIN
EXECUTE IMMEDIATE 'delete from '||p_table_name;
p_rows_deld := SQL%ROWCOUNT;
END;
/

VARIABLE deleted NUMBER


EXECUTE del_rows('employee2',:deleted)
PRINT deleted

You might also like