PL SQL
PL SQL
The PL/SQL programming language was developed by Oracle Corporation in the late 1980s as procedural extension
language for SQL and the Oracle relational database. Following are certain notable facts about PL/SQL:
DECLARE
message varchar2(20):= 'Hello, World!';
BEGIN
dbms_output.put_line(message);
END;
Variable Declaration
sales number(10, 2); name varchar2(25);
pi CONSTANT double precision := 3.1415; address varchar2(100);
DECLARE
a integer := 10;
b integer := 20;
c integer;
f real;
BEGIN
c := a + b;
dbms_output.put_line('Value of c: ' || c);
f := 70.0/3.0;
dbms_output.put_line('Value of f: ' || f);
END; /
Variable Scope in PL/SQL
Local variables - Variables declared in an inner block and not accessible to outer blocks.
Global variables - Variables declared in the outermost block or a package.
DECLARE -- Global variables
num1 number := 95;
num2 number := 85;
BEGIN
dbms_output.put_line('Outer Variable num1: ' || num1);
dbms_output.put_line('Outer Variable num2: ' || num2);
DECLARE -- Local variables
num1 number := 195;
num2 number := 185;
BEGIN
dbms_output.put_line('Inner Variable num1: ' || num1);
dbms_output.put_line('Inner Variable num2: ' || num2);
END; END;
DECLARE
PROCEDURE compare (value varchar2, pattern varchar2 ) is
BEGIN
IF value LIKE pattern THEN
dbms_output.put_line ('True');
ELSE
dbms_output.put_line ('False');
END IF;
END;
BEGIN
compare('Zara Ali', 'Z%A_i');
compare('Nuha Ali', 'Z%A_i');
END;
4. Logical operators
AND, OR, NOT
PL/SQL — Conditions
1. IF - THEN statement
2. IF-THEN-ELSE statement
3. IF-THEN-ELSIF statement
4. nested IF-THEN-ELSE
5. Case statement
CASE selector
WHEN 'value1' THEN S1;
WHEN 'value2' THEN S2;
WHEN 'value3' THEN S3;
...
ELSE Sn;
default case
END CASE;
DECLARE
grade char(1) := 'A';
BEGIN
CASE grade
when 'A' then dbms_output.put_line('Excellent'); or when grade = ‘A’ then ……
when 'B' then dbms_output.put_line('Very good');
when 'C' then dbms_output.put_line('Well done');
when 'D' then dbms_output.put_line('You passed');
when 'F' then dbms_output.put_line('Better try again');
else dbms_output.put_line('No such grade');
END CASE;
END;
PL/SQL — Loops
1. PL/SQL Basic LOOP
LOOP
Sequence of statements;
END LOOP;
DECLARE
x number := 10;
BEGIN
LOOP LOOP
dbms_output.put_line(x); dbms_output.put_line(x);
x := x + 10; x := x + 10;
IF x > 50 THEN exit WHEN x > 50;
exit; END LOOP;
END IF;
END LOOP;
-- after exit, control resumes here
dbms_output.put_line('After Exit x is: ' || x);
END;
2. While Loop
3. For Loop
DECLARE
a number(2);
BEGIN
FOR a in 10 .. 20 LOOP
dbms_output.put_line('value of a: ' || a);
END LOOP;
END;
DECLARE
a number(2) ;
BEGIN
FOR a IN REVERSE 10 .. 20 LOOP
dbms_output.put_line('value of a: ' || a);
END LOOP;
END;
The PL/SQL programming language provides a data structure called the VARRAY, which can store a fixed-size
sequential collection of elements of the same type. A varray is used to store an ordered collection of
Data.
DECLARE
type namesarray IS VARRAY(5) OF VARCHAR2(10);
type grades IS VARRAY(5) OF INTEGER;
names namesarray;
marks grades;
total integer;
BEGIN
names := namesarray('Kavita', 'Pritam', 'Ayan', 'Rishav', 'Aziz');
marks:= grades(98, 97, 78, 87, 92);
total := names.count;
dbms_output.put_line('Total '|| total || ' Students');
FOR i in 1 .. total LOOP
dbms_output.put_line('Student: ' || names(i) || 'Marks: ' || marks(i));
END LOOP;
END;
DECLARE
CURSOR c_customers is
SELECT name FROM customers;
type c_list is varray (6) of customerS.No.ame%type;
name_list c_list := c_list();
counter integer :=0;
BEGIN
FOR n IN c_customers LOOP
counter := counter + 1;
name_list.extend;
name_list(counter) := n.name;
dbms_output.put_line('Customer('||counter ||'):'||name_list(counter));
END LOOP;
END;
Procedures
A subprogram is a program unit/module that performs a particular task. These subprograms are combined to
form larger programs. A subprogram can be created:
At the schema level
Inside a package
Inside a PL/SQL block
PL/SQL provides two kinds of subprograms:
Functions: These subprograms return a single value; mainly used to compute and return a value.
Procedures: These subprograms do not return a value directly; mainly used to perform an action.
Creating a Procedure
CREATE [OR REPLACE] PROCEDURE procedure_name
[(parameter_name [IN | OUT | IN OUT] type [, ...])]
{IS | AS}
BEGIN < procedure_body >
END procedure_name;
Example 3
CREATE OR REPLACE PROCEDURE adjust_salary(
in_employee_id IN EMPLOYEES.EMPLOYEE_ID%TYPE,
in_percent IN NUMBER
) IS
BEGIN
-- update employee's salary
UPDATE employees
SET salary = salary + salary * in_percent / 100
WHERE employee_id = in_employee_id;
END;
-- before adjustment
SELECT salary FROM employees WHERE employee_id = 200;
-- call procedure
exec adjust_salary(200,5);
-- after adjustment
SELECT salary FROM employees WHERE employee_id = 200;
Example 4
CREATE or REPLACE PROCEDURE pro11(no in number,temp out emp%rowtype)
IS
BEGIN
SELECT * INTO temp FROM emp WHERE empno = no;
END;
DECLARE
temp emp%rowtype;
no number :=&empno;
BEGIN
pro1(no,temp);
dbms_output.put_line('Employee is ');
dbms_output.put_line(temp.empno||' '|| temp.ename||' '||
temp.job||' '||temp.sal||' ');
END;
EXECUTE pro11(1234);
Example 5
CREATE or REPLACE PROCEDURE remove_emp1 (employee_id NUMBER) AS
tot_emps NUMBER;
BEGIN
DELETE FROM emp
WHERE emp.empno = remove_emp1.employee_id;
tot_emps := tot_emps - 1;
END;
EXECUTE remove_emp1 (7934)
Creating a Function
CREATE [OR REPLACE] FUNCTION function_name
[(parameter_name [IN | OUT | IN OUT] type [, ...])]
RETURN return_datatype
{IS | AS}
BEGIN
< function_body >
END [function_name];
Example 1
CREATE OR REPLACE FUNCTION totalCustomers DECLARE
RETURN number IS c number(2);
total number(2) := 0; BEGIN
BEGIN c := totalCustomers();
SELECT count(*) into total dbms_output.put_line('Total no. of Customers: ' || c);
FROM customers; END;
RETURN total;
END;
Example 2
DECLARE BEGIN
a number; a:= 23;
b number;
c number; b:= 45;
FUNCTION findMax(x IN number, y IN number) c := findMax(a, b);
RETURN number dbms_output.put_line(' Maximum of (23,45): ' || c);
IS
z number; END;
BEGIN
IF x > y THEN
z:= x;
ELSE
Z:= y;
END IF;
RETURN z;
END;
Cursor
Oracle creates a memory area, known as the context area, for processing an SQL statement, which contains all the
information needed for processing the statement; for example, the number of rows processed, etc.
A cursor is a pointer to this context area. PL/SQL controls the context area through a cursor. A cursor holds the rows (one
or more) returned by a SQL statement. The set of rows the cursor holds is referred to as the active set.
You can name a cursor so that it could be referred to in a program to fetch and process the rows returned by the SQL
statement, one at a time. There are two types of cursors −
Implicit cursors
Explicit cursors
Implicit Cursors
Implicit cursors are automatically created by Oracle whenever an SQL statement is executed, when there is no explicit
cursor for the statement. Programmers cannot control the implicit cursors and the information in it.
Whenever a DML statement (INSERT, UPDATE and DELETE) is issued, an implicit cursor is associated with this
statement.
For INSERT operations the cursor holds the data that needs to be inserted.
For UPDATE and DELETE operations the cursor identifies the rows that would be affected.
%FOUND 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 DELETE statement
affected no rows, or a SELECT INTO statement returned no rows. Otherwise, it returns FALSE.
%ISOPEN Always returns FALSE for implicit cursors, because Oracle closes the SQL cursor automatically after
executing its associated SQL statement.
%ROWCOUNT Returns the number of rows affected by an INSERT, UPDATE, or DELETE statement, or returned
by a SELECT INTO statement.
DECLARE
total_rows number(2);
BEGIN
UPDATE emp
SET sal = sal + 500
where empno = 7369;
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;
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.
e.g.1
DECLARE
e_id emp.empno%type;
e_name emp.ename%type;
e_job emp.job%type;
CURSOR c_Emp is
SELECT empno, ename, job FROM emp;
BEGIN
OPEN c_Emp;
LOOP
FETCH c_Emp into e_id, e_name, e_job;
EXIT WHEN c_Emp%notfound;
dbms_output.put_line('Id = ' || e_id || ' Name = ' || e_name || ' works as ' || e_job);
END LOOP;
CLOSE c_Emp;
END;
e.g.2
DECLARE
CURSOR emp_cur IS
SELECT first_name, last_name, salary FROM emp_tbl;
emp_rec emp_cur%rowtype;
BEGIN
IF NOT emp _cur%ISOPEN THEN
OPEN emp _cur;
END IF;
FETCH emp _cur INTO sales_rec;
WHILE emp _cur%FOUND THEN
LOOP
dbms_output.put_line(emp_cur.first_name || ' ' ||emp_cur.last_name
|| ' ' ||emp_cur.salary);
FETCH emp _cur INTO sales_rec;
END LOOP;
END;
e.g.3
DECLARE
CURSOR c1 IS
SELECT ename, job FROM emp
WHERE job LIKE '%CLERK%' AND mgr = 7698
ORDER BY 1;
BEGIN
FOR x IN c1
LOOP
DBMS_OUTPUT.PUT_LINE
('Name = ' || x.ename || ', Job = ' || x.job);
END LOOP;
END;
TRIGGER
A trigger is a pl/sql block structure which is fired when a DML statements like Insert, Delete, Update is executed on a
database table. A trigger is triggered automatically when an associated DML statement is executed.
CREATE [OR REPLACE ] TRIGGER trigger_name - This clause creates a trigger with the given name or
overwrites an existing trigger with the same name.
{BEFORE | AFTER | INSTEAD OF } - This clause indicates at what time should the trigger get fired. i.e for
example: before or after updating a table. INSTEAD OF is used to create a trigger on a view. before and after
cannot be used to create a trigger on a view.
{INSERT [OR] | UPDATE [OR] | DELETE} - This clause determines the triggering event. More than one
triggering events can be used together separated by OR keyword. The trigger gets fired at all the specified
triggering event.
[OF col_name] - This clause is used with update triggers. This clause is used when you want to trigger an event
only when a specific column is updated.
[ON table_name] - This clause identifies the name of the table or view to which the trigger is associated.
[REFERENCING OLD AS o NEW AS n] - This clause is used to reference the old and new values of the data being
changed. By default, you reference the values as :old.column_name or :new.column_name. The reference names
can also be changed from old (or new) to any other user-defined name. You cannot reference old values when
inserting a record, or new values when deleting a record, because they do not exist.
[FOR EACH ROW] - This clause is used to determine whether a trigger must fire when each row gets affected (
i.e. a Row Level Trigger) or just once when the entire sql statement is executed(i.e.statement level Trigger).
WHEN (condition) - This clause is valid only for row level triggers. The trigger is fired only for rows that satisfy
the condition specified.
Type of Triggers
1. BEFORE Trigger : BEFORE trigger execute before the triggering DML statement (INSERT, UPDATE, DELETE)
execute. Triggering SQL statement is may or may not execute, depending on the BEFORE trigger conditions
block.
2. AFTER Trigger : AFTER trigger execute after the triggering DML statement (INSERT, UPDATE, DELETE)
executed. Triggering SQL statement is execute as soon as followed by the code of trigger before performing
Database operation.
3. ROW Trigger : ROW trigger fire for each and every record which are performing INSERT, UPDATE, DELETE
from the database table. If row deleting is define as trigger event, when trigger file, deletes the five rows each
times from the table.
BEGIN
SELECT user INTO v_username
FROM dual;
END;