You are on page 1of 68

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
PL SQL Client Engine
PLSQL Server Side
Declare => Optional
Begin => Mandatory
Exception => Optional
End; => Mandatory
/ => Executor
PLSQL Block structure
PLSQL Variable
Scalar
Composite
Reference
LOB (large objects)
Non-PLSQL Variable
Bind variable or Host variable
Types of 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;
Bind Variable
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
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
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;
/
Conditional Constructs
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
PLSQL CURSOR
SQL%FOUND
SQL%NOTFOUND
SQL%ROWCOUNT
SQL%ISOPEN
SQL Cursor Attributes for
Implicit 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.
Controlling Explicit Cursors
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
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;
/
Cursor with Attributes
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;
/
Locking Cursor
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;
EXCEPTION
Implicitly raised.
Predefined Server Exception
Non-Predefined Server Exception
Explicitly raised.
User Defined Exception
Types of Exceptions
Sample predefined exceptions:
NO_DATA_FOUND
TOO_MANY_ROWS
INVALID_CURSOR
ZERO_DIVIDE
DUP_VAL_ON_INDEX
Sample predefined exceptions
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;
/
Example
A named block of code => Subprogram
Types:
Procedures => Performs action
Functions => Computes Value
Subprogram
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.
Procedure
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);
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 2 with OUT parameter
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;
/
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
Example 3 INOUT parameter
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
return any value
Procedures should be
executed.
3 types of modes can be
used
Do not contain RETURN
clause in the header
Function should return a value
Functions should be invoked.
Only IN mode can be used
Must contain a RETURN
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