PLSQL
PLSQL
Features of PL/SQL
Advantages of PL/SQL
PL/SQL block
Header: An optional section .Used only for named blocks. It determines the way
the named block or program must be called.
Declaration section : An optional section. All identifies variables, cursors, and
subblocks that are referenced in the execution and exception sections are declared
here.
Execution section: This is the mandatory section.Statements the PL/SQL runtime
engine will execute at runtime are written here.
Exception section: Optional section.Handles exceptions to normal processing
(warnings and error conditions).
DECLARE
BEGIN
execute at runtime>
EXCEPTION
END;
Example:
DECLARE
str varchar2(20):= 'Hello, World!';
BEGIN
dbms_output.put_line(str);
END;
Data Types
These are data items that have internal components. We can access and
manipulate each of these internal components individually.
For example, records in a table. Records have fields with different data types.
We can pass records to subprograms as a single parameter.
Syntax :
Variables
A variable is nothing but a name given to a storage area that programs can
manipulate.
Syntax :
Example:
emp_name varchar2(25);
address1 varchar2(100);
Programmer can provide an initial value other than NULL to a variable using
assignment operator during declaration.
Example1:
My_counter number := 0;
For each item in the SELECT list, there must be a corresponding, type- compatible
variable in the INTO list.
Example2:
Where v_name and v_no are variables declared with the data type same as the data
type ename and deptno columns of employee table respectively.
Example1:
A complete PL/SQL clock to print the name and salary of employees from
employee table.
DECLARE
BEGIN
eno := &eno;
SELECT name, salary INTO emp_name, sal FROM employee
WHERE eno=empno;
DBMS_OUTPUT.PUT_LINE(emp_name);
DBMS_OUTPUT.PUT_LINE(salary);
END;
Example2:
DECLARE
BEGIN
DBMS_OUTPUT.PUT_LINE(rs)
END;
Operators
Example:
DECLARE
num1 NUMBER(4):=&num1;
num2 NUMBER(4):=1;
BEGIN
WHILE (num2<=num1)
LOOP
DBMS_OUTPUT.PUT_LINE(num2);
num2:=num2+1;
END LOOP;
END;
Conditional control structures allows to control the flow of the execution of the
program based on a condition. In programming terms, it means that the statements
in the program are not executed sequentially, rather, one group of statements, or
another will be executed, depending on how the condition is evaluated.
IF-THEN
IF-THEN –ELSE
IF-THEN-ELIF
CASE
IF - THEN:
Syntax:
IF (condition) THAN
statements;
END IF;
Example:
DECLARE
a number(2) := 0;
BEGIN
END IF;
END;
IF - THEN - ELSE:
Syntax:
IF (condition) THAN
statements;
ELSE
Statements;
END IF;
Example:
DECLARE
a number(3) := 0;
BEGIN
a:=&a;
ELSE
END IF;
END;
IF-THEN- ELIF:
Syntax:
IF (condition) THAN
statements;
Statements;
ELSE
Statements;
END IF;
Example:
DECLARE
a number(3) := 0;
BEGIN
a:=&a;
IF ( a = 10 ) THEN
dbms_output.put_line('Value of a is 10' );
ELSIF ( a = 20 ) THEN
dbms_output.put_line('Value of a is 20' );
ELSIF ( a = 30 ) THEN
dbms_output.put_line('Value of a is 30' );
ELSE
END IF;
END;
CASE statement:
The CASE statement selects one sequence of statement to execute similar to IF.
The expression is evaluated once and its value is matched with several blocks
whichever block matches first , that is evaluated.
Syntax:
CASE selector
WHEN expression1 THEN
Statement 1;
WHEN expression2 THEN
Statement 2;
ELSE
Statement n;
END CASE;
The reserved word CASE marks the beginning of the CASE statement.
The 'selector' is a value that determines , which WHEN clause should be executed.
It is evaluated only once for the whole selection process.
Each WHEN clause contains an expression and one or more executable statements
associated with it.
Example:
DECLARE
grade varchar2(1):='A';
BEGIN
grade:=&grade;
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
GOTO statement:
GOTO provides the ability to jump through a program from one place to another. It
is better to have a limited usage of GOTO in program code. When a jump is
proposed using GOTO , it is associated with an appropriate
label.
The label must be unique within its scope and must precede an executable
statement.
When executed, the GOTO statement transfers the control to the labelled
statements or block.
The labels are enclosed between angular brackets << and >>
Syntax:
GOTO label_name;
Example:
DECLARE
num NUMBER(2) := 1;
BEGIN
LOOP
num := num+1;
IF num > 5 THEN
GOTO 1_ENDOFLOOP; -- print num 5 times
END IF;
DBMS_OUTPUT.PUT_LINE('value = ' || );
END LOOP;
END;
an inner block
a loop
an IF statement
an exception
Practice Assignments on Looping Structures
1. Write a PL/SQL block to print the even numbers from 1 to a given
number using while loop.
2. Write an Anonymous Block to accept two different number and find
addition, subtraction, multiplication and division of given two numbers
using CASE.
3. Write a PL/SQL block to print the multiplication table up to 10 multiples
for a given number in the below format:
5*1=5
5 * 2 = 10
5 * 3 = 15
…...
5 * 10 = 50
4. Write a PL/SQL block to check whether the given number is a palindrome
or not.
5. Write a PL/SQL to find the sum of first hundred odd numbers.
6. Write an anonymous block to print the following series using for loop.
1
12
123
1234
12345
7. Write an anonymous block to print the following series using for loop. 5 5
555
4444
333
12
1
8. Write a PL/SQL to print the number of times a specified character is
appearing in a given string.
Note: Use the below tables to perform the queries for below two
assignments.
FACULTY – fid , name , qualification
BATCH – bid , start_date , end_date , fid , cid , timing
COURSE – cid , cname , duration , fee
STUDENT – sid , sname , gender , doj , bid , cid
9. Write a PL/SQL block to display the student details for a specified student
id.
10.Write a PL/SQL block to print the batch id , start date , end date and
number of days the batch batch will be staying.
Introduction to Cursors
For processing an SQL statement, oracle needs to allocate memory called context
area. A cursor is a pointer to this context area. PL/SQL controls the context area
through a cursor.
Cursor contains information on a select statement and the rows accessed by it. This
temporary work area is used to store the data retrieved from the database and
manipulate this data.
The set of rows the cursor holds is referred to as the active set.
Types of Cursors:
a) Implicit Cursors
Oracle automatically creates an implicit cursor for all DML (INSERT,
UPDATE and DELETE) and Select statements
Programmers cannot control the implicit cursors and the information in it.
For INSERT operations, the cursor holds the data that to be inserted.
For UPDATE and DELETE operations, the cursor identify the rows that are
affected.
%NOTFOUND: Returns FALSE for implicit cursors, because Oracle closes the
SQL cursor automatically after executing its associated SQL statement. It returns
TRUE for explicit cursor if the cursor is open, otherwise returns FALSE.
Example: To update the salary of all employees in the Employee table and print
the count of rows updated or if the table is empty print ‘no employees selected’.
DECLARE
total_rows number(2);
BEGIN
IF sql%notfound THEN
dbms_output.put_line('no employee selected');
total_rows := sql%rowcount ;
END IF;
END;
/NT
b) Explicit Cursors:
Cursors declared by the programmer for Queries that return more than one
row.
Declared and managed by the programmer and manipulated through specific
statements in the blocks.
The size of the active set meets the search criteria in the select statement.
All the cursor attributes available for implicit cursors will work on explicit cursors
in the same manner.
In the declarative section of PL/SQL block, declare the cursor by naming it and
defining the structure of Query to be associated with it.
Syntax:
Open statement allocates the memory for the cursor and makes it ready for fetching
the rows returned by the SQL statement into it.
Syntax :
OPEN cursor_name ;
OPEN cur_emp;
The Fetch statement retrieves the rows from the cursor one at a time.
Syntax:
Include the same number of variables in the variable list as the number of columns
selected in cursor definition.
Example: To fetch the Rows from the cursor cur_emp opened in the previous
statement.
Syntax :
CLOSE cursore_Name;
CLOSE cur_emp;
Example1: To declare cursor to select all records from employee table and print
the values . Employee table has following structure:
DECLARE
c employee%rowtype;
BEGIN
OPEN c1;
Loop
FETCH c1 into c;
End Loop;
CLOSE c1;
END;
Example2 : To print the employee number and name of those employee who gets
salary more than 20000.
DECLARE
c employee%rowtype;
BEGIN
OPEN c1;
Loop
FETCH c1 into c;
End Loop;
CLOSE c1;
END;
Parameterized Cursor
We can send any number of parameters to cursors. Supplying a value
to the query dynamically in the where condition is cursor Parameter.
Declaring a Parameterized Cursor:
CURSOR cursor_name(parameter_list) IS
Example:
DECLARE
CURSOR c1 (p_dept_id) IS select * from employee where deptno =
p_deptid;
c employee%rowtype;
v_dept_id number;
BEGIN
v_dept_id :=20;
OPEN c1(v_dept_id);
Loop
FETCH c1 into c;
Exit when c1%notfound;
dbms_output.put_line('Employee Number: '||c.eno);
dbms_output.put_line('Employee Name: '||c.ename);
End Loop;
CLOSE c1;
END;
Syntax:
Example:
PL/SQL block to print the product name and the unit price of all products in the
table.
DECLARE
CURSOR cur_product IS
SELECT product_name, unit_price FROM products;
BEGIN
FOR product IN cur_product
LOOP
DBMS_OUTPUT.PUT_LINE( product.product_name || ': $'
|| product.unit_price );
END LOOP;
END;
Write a PL/SQL block to update the basic salary of each employee by 2000 The
code should print a message as “None of the salaries where updated” in case there
is no record in the table. Should print a message as below “Salaries for 1000
employees are updated' if there are 1000 rows in the table.
Use cursor attributes to print appropriate messages.
Total salary needs to be calculated as Total salary = basic Salary + 50% of Basic
Salary .
EXCEPTION HANDLING
Introduction
When an exception occurs, a message which explains its cause is received PL/SQL
exception consists of three parts
Type of exception
Error Code
Error Message
Types Of Exceptions
BEGIN
Execution block statements.
EXCEPTION
WHEN exception_name THEN
statements to be executed
WHEN OTHERS THEN ---- optional
statements to be executed
END;
Example:
To print the id of the employee from employee table for the employee named
Deepak. If the employee with name Deepak not found the message "Employee not
found " should be displayed.
DECLARE
v_id Number(4);
BEGIN
dbms_output.put_line('Employee id is '||v_Id);
EXCEPTION
END;
The functions SQLCODE and SQLERRM are useful in the OTHERS handler as
they return the Oracle error code and message text.
Examples:
Example:
DECLARE
c_id customers.id%type := 8;
c_name customers.name%type;
c_addr customers.address%type;
BEGIN
SELECT name, address INTO c_name, c_addr FROM customers WHERE id
= c_id;
DBMS_OUTPUT.PUT_LINE ('Name: '|| c_name);
DBMS_OUTPUT.PUT_LINE ('Address: ' || c_addr);
EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.put_line('No such customer!');
WHEN others THEN
DBMS_OUTPUT.put_line('Error Due To -->'||
SQLCODE||SQLERRM);
END;
Those system exception for which oracle does not provide a name is known as
unnamed system exception.
These exception do not occur frequently. These Exceptions have a code and an
associated message.
Example:
Lets consider the product table and order_items table . Here product_id is a
primary key in product table and a foreign key in order_items table. If we try to
delete a product_id from the product table when it has child records in order_id
table an exception will be thrown with oracle code number -2292. We can provide
a name to this exception and handle it in the exception section as given below.
DECLARE
Child_rec_exception EXCEPTION;
PRAGMA
EXCEPTION_INIT (Child_rec_exception, -2292);
BEGIN
Delete FROM product where product_id= 104;
EXCEPTION
WHEN Child_rec_exception THEN
User-defined Exceptions
Example:
Lets consider the product table and order_items tables.
Lets create a business rule that if the total no of units of any particular product sold
is more than 20, then it is a huge quantity and a special discount should be
provided.
DECLARE
huge_quantity EXCEPTION;
CURSOR product_quantity IS
SELECT p.product_name as name, sum(o.total_units) as units
FROM order_tems o, product p
WHERE o.product_id = p.product_id;
quantity order_tems.total_units%type;
up_limit CONSTANT order_tems.total_units%type := 20;
message VARCHAR2(50);
BEGIN
FOR product_rec in product_quantity
LOOP
quantity := product_rec.units;
IF quantity > up_limit THEN
message := 'The number of units of product ' || product_rec.name ||' is
more than 20. Special discounts should be provided.Rest of
the records are skipped. '
RAISE huge_quantity;
ELSIF quantity < up_limit THEN
Example:
DECLARE
huge_quantity EXCEPTION;
CURSOR product_quantity IS
SELECT p.product_name as name, sum(o.total_units) as units
FROM order_tems o, product p
WHERE o.product_id = p.product_id;
quantity order_tems.total_units%type;
up_limit CONSTANT order_tems.total_units%type := 20;
message VARCHAR2(50);
BEGIN
FOR product_rec in product_quantity LOOP
quantity := product_rec.units;
IF quantity > up_limit THEN
RAISE huge_quantity;
ELSIF quantity < up_limit THEN
v_message:= 'The number of unit is below the discount limit.';
END IF;
DBMS_OUTPUT.put_line (message);
END LOOP;
EXCEPTION
WHEN huge_quantity THEN
raise_application_error(-2100, 'The number of unit is above
the discount limit.');
END;
Sub Program:
Packaged subprogram:
Nested subprogram:
Parts of Subprogram:
Declarative Part:
Optional part.
Does not start with DECLARE keyword.
Contains declarations of cursors , constants, variables, exceptions and nested
sub programs.
Executable Part
Procedure
Function
Procedures
Procedure Header:
Components:
Parameter list: The optional parameter list contains name, mode and types
of the parameters.
Procedure Body:
Statements after the IS keyword is the procedure body. The procedure body has
similar syntax like an anonymous block and consists of the declaration, execution
and exception sections.
Example1:
total1 number;
average1 number;
BEGIN
total1:=(m1+m2+m3);
average1:=(total1/3);
END;
EXECUTE find_Total_Average(20,30,40);
For example,
DECLARE
a number;
b number;
c number;
BEGIN
a:=&a;
b:=&b;
c:=&c;
find_Total_Average (a,b,c);
END;
BEGIN
result:= num1;
ELSE
result:= num2;
END IF;
END;
/
Anonymous block to call the procedure:
DECLARE
a NUMBER :=100;
b NUMBER :=200;
c NUMBER;
BEGIN
findMin(a, b, c);
END;
BEGIN
END;
DECLARE
BEGIN
a:= 20;
squareNum(a);
END;
Note:
Functions
Basic Structure
Return Type:
BEGIN
num_read:=&num_read;
sum:=num_in +num_read;
RETURN sum;
END;
It has one parameter called name_in of type number and it returns a number.
To write a function to find the first name of the employee for a given id from the
table
Employees(emp_id,first_name,last_name,designation);
BEGIN
RETURN emp_name;
EXCEPTION
END;
The argument e_id of type number is used to pass the id value of the
employee to be searched in the employee table.
Variable emp_name is declared as VARCHAR(20) to hold the value to be
fetched from the table.
Function returns the first_name value from the employee table if table has a
record with emp_id value equal to the e_id value given as argument.
If no matching record found in the table, function raises no_data_found
exception and from the EXCEPTION block returns “No such Employee !”.
Define an anonymous block with a variable declared to catch the return value in
the block.
DECLARE
employee_name varchr2(30);
v_dept_id number
BEGIN
v_dept_id := 20;
employee_name := find_employee_name(v_dept_id);
dbms_output.put_line('employee name is -->'||employee_name);
END;
3) In PL/SQL Statements:
dbms_output.put_line(find_employee_name(20));
Importance of Triggers
Trigger Restrictions
Instead of triggers
Triggers on system events and user events.
Row level trigger fires for each and every record which are performing INSERT,
UPDATE and DELETE from the database table.
BEFORE trigger :
Triggering SQL statements may or may not execute, depending on the BEFORE
trigger conditions block.
AFTER trigger :
AFTER trigger execute after the triggering DML statement (INSERT, UPDATE,
DELETE) is executed.
[OF col_name]
ON table_name
DECLARE
Declaration-statements
BEGIN
Executable-statements
EXCEPTION
Exception-handling-statements
END;
Where
Dropping trigger:
Triggers created can be removed by using Drop command.
Syntax:
Example 1:
To create a row-level trigger for the Employee table that would fire for INSERT or
UPDATE or DELETE operations performed on the table and display the salary
difference between the old salary value and the new salary value .
DECLARE
sal_diff number;
BEGIN
sal_diff := :NEW.salary - :OLD.salary;
END;
When the above code is executed at the SQL prompt, it produces the following
result –
Trigger Created.
The trigger created above, display_salary_changes will be fired and it will display
the following result –
Old salary :
Salary difference:
Since this is a new record , the old salary is not available and the result comes as
null.
Salary difference:2000.00
1. Write a simple function to accept two numbers and return the summation of
the numbers . Create an anonymous block and call the function .
2. Write a function to find a factorial of a given number.
3. Write a function to return the day of week( like monday or tueseday ) for
given date.
4. Write a function to check whether the given number is a prime number or
not.
5. Write a function to accept a string and a character and return the number of
times the given character exists in given string.
6. Write a function to reverse a given string.
7. Write a stored function to accept a number from user and display its cube
value (i.e., num^3).
10. Write a function to find the number of employees who gets basic pay more
than a given amount. The amount to be compared will be passed as argument to
the stored function.