You are on page 1of 30

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;
 /

You might also like