Functions
S.Naji
Functions and procedures
Procedures and functions that are created outside
of a package are called stored or standalone
subprograms.
Procedures and functions defined within a package
are known as packaged subprograms.
Procedures and functions nested inside other
subprograms or within a PL/SQL block are known
as local subprograms, which cannot be referenced
by other applications and exist only inside of the
enclosing block
Function Declaration
CREATE [OR REPLACE] FUNCTION function_name
[ (parameter [,parameter]) ]
RETURN return_datatype
IS | AS
[declaration_section]
BEGIN
executable_section
[EXCEPTION
exception_section]
END [function_name];
Functions Vs Procedures
Procedure may return none or more values.Function must always return one value
either a scalar value or a table.
Procedure have input,output parameters.Functions have only input parameters.
Stored procedures are called independently by EXEC command whereas Functions
are called from within SQL statement.
Functions can be called from procedure.Procedures cannot be called from function.
Exception can be handled in Procedure by try-catch block but try-catch block
cannot be used in a function.(error-handling)
Transaction management possible in procedure but not in function.
Simple Function
CREATE FUNCTION totalCustomers
RETURN number IS
total number(2) := 0;
BEGIN
SELECT count(*) into total
FROM customers;
RETURN total;
END; /
Calling function
DECLARE
c number(2);
BEGIN
c := totalCustomers();
dbms_output.put_line('Total no.
of Customers: ' || c);
END;
/
Example 2
CREATE FUNCTION circle_area (p_radius IN
NUMBER)
RETURN NUMBER AS
v_pi NUMBER := 3.14;
v_area NUMBER;
BEGIN
v_area := v_pi * POWER(p_radius, 2);
RETURN v_area;
END;
/
Calling function
select circle_area(12) from dual;
Recursive function
set serveroutput on
set echo on
CREATE FUNCTION Factorial(p_MyNum INTEGER)
RETURN NUMBER AS
BEGIN
IF p_MyNum = 1 THEN
RETURN 1;
ELSE
RETURN(p_MyNum * Factorial(p_MyNum-1));
END IF;
END;
/
Calling function
BEGIN
DBMS_OUTPUT.PUT_LINE(factorial(10));
END;
/
Create Table for function operation
create table Employee(
ID VARCHAR2(4 BYTE) NOT NULL,
First_Name VARCHAR2(10 BYTE),
Last_Name VARCHAR2(10 BYTE),
Start_Date DATE,
End_Date DATE,
Salary Number(8,2),
City VARCHAR2(10 BYTE),
Description VARCHAR2(15 BYTE)
)
/
Insert Rows
insert into Employee(ID, First_Name,
Last_Name, Start_Date,
End_Date, Salary, City, Description)
values ('01','Jason', 'Martin',
to_date('19960725','YYYYMMDD'),
to_date('20060725','YYYYMMDD'), 1234.56,
'Toronto', 'Programmer')
/
Example
CREATE FUNCTION average_salary RETURN
NUMBER AS
v_average_salary NUMBER;
BEGIN
SELECT AVG(salary)
INTO v_average_salary
FROM employee;
RETURN v_average_salary;
END;
/
Calling the Function
select average_salary from dual;
Example
Create table
create table employees(
empno NUMBER(4)
, ename VARCHAR2(8)
, init VARCHAR2(5)
, job VARCHAR2(8)
, mgr NUMBER(4)
, bdate DATE
, msal NUMBER(6,2)
, comm NUMBER(6,2)
, deptno NUMBER(2) ) ;
Insert Rows
insert into employees values(1,'Jason', 'N',
'TRAINER', 2, date '1965-12-18', 800 ,
NULL, 10);
insert into employees values(2,'Jerry', 'J',
'SALESREP',3, date '1966-11-19', 1600, 300,
10);
Function
create or replace function emp_count(p_deptno in
number)
return number is
cnt number(2) := 0;
begin
select count(*) into cnt
from employees e
where e.deptno = p_deptno;
return (cnt);
end;
/
Describing the function
describe emp_count;
Example
create or replace
function getArea (i_rad NUMBER)
return NUMBER
is
v_pi NUMBER:=3.14;
begin
return v_pi * (i_rad ** 2);
end;
/
Calling the function
Select getarea(20) from dual;
Example
CREATE OR REPLACE function exitfunc(myString VARCHAR2)
RETURN NUMBER IS
v_current_position INTEGER := 1;
v_counter NUMBER := 0;
BEGIN
WHILE v_current_position <= LENGTH(myString) LOOP
IF SUBSTR(myString,v_current_position,1) != ' ' THEN
v_counter := v_counter + 1;
ELSE
NULL;
END IF;
v_current_position := v_current_position + 1;
EXIT WHEN SUBSTR(myString,v_current_position,1) = ' ';
END LOOP;
RETURN v_counter ;
END exitfunc;
/
Calling the count Fuction
DECLARE
v_MYTEXT VARCHAR2(20) := 'THIS
IS A TEST';
BEGIN
DBMS_OUTPUT.PUT_LINE('Total
count is ' || exitfunc(v_MYTEXT));
END;
/
Squared Function
CREATE OR REPLACE FUNCTION
squareme(thenum number)
RETURN NUMBER IS
BEGIN
RETURN thenum * thenum;
END squareme;
/
calling
BEGIN
DBMS_OUTPUT.PUT_LINE('9 squared
is ' || squareme(9) );
END;
/
Local sub Function programs
DECLARE
CURSOR c_AllEmployees IS
SELECT first_name, last_name
FROM employee;
v_FormattedName VARCHAR2(50);
/* Function which will return the first and last name
concatenated together, separated by a space. */
FUNCTION FormatName(p_FirstName IN VARCHAR2,
p_LastName IN VARCHAR2)
RETURN VARCHAR2 IS
BEGIN
RETURN p_FirstName || ' ' || p_LastName;
END FormatName;
-- Begin main block.
BEGIN
FOR v_EmployeeRecord IN c_AllEmployees LOOP
v_FormattedName :=
FormatName(v_EmployeeRecord.first_name,
v_EmployeeRecord.last_name);
DBMS_OUTPUT.put_line(v_FormattedName);
END LOOP;
COMMIT;
END;
/
Concatenation of Fields of a table
CREATE OR REPLACE FUNCTION FullName (
p_ID employee.ID%TYPE)
RETURN VARCHAR2 IS
v_Result VARCHAR2(100);
BEGIN
SELECT first_name || ' ' || last_name
INTO v_Result
FROM employee
WHERE ID = p_ID;
RETURN v_Result;
END FullName;
/
Calling the function
select FULLName(id) from employee;
Checking Errors
Show errors function function_name;
Return value from function
CREATE or replace FUNCTION compute_discounts (order_amt NUMBER)
RETURN NUMBER IS
small_order_amt NUMBER := 400;
large_order_amt NUMBER := 1000;
small_disct NUMBER := 1;
large_disct NUMBER := 5;
BEGIN
IF (order_amt < large_order_amt
AND
order_amt >= small_order_amt)
THEN
RETURN (order_amt * small_disct / 100);
ELSIF (order_amt >= large_order_amt)
THEN
RETURN (order_amt * large_disct / 100);
ELSE
RETURN(0);
END IF;
END compute_discounts;
/
Calling the function
set serveroutput on
DECLARE
tiny NUMBER := 20;
med NUMBER := 600;
big NUMBER := 4550;
wrong NUMBER := -35;
BEGIN
dbms_output.put_line (' Order AND Discount ');
dbms_output.put_line (tiny || ' ' || compute_discounts(tiny));
dbms_output.put_line (med || ' ' || compute_discounts (med));
dbms_output.put_line (big || ' ' || compute_discounts (big));
dbms_output.put_line (wrong || ' ' || compute_discounts (wrong));
END;
/