FUNCTIONS :
===========
*)Function are stored programes .They are kept as an Object
within oracle database in compiled form. By using the function
xceute or call.
A Function has following features:
--> They can receive values in the form of parameters.
--> They return one value, and it is must.
--> They can be used in SQL statement also.
Name we can e
*)Why to use Function?
--------------------------------> Available in the form of Object.
--> Stored in the form of compiled code.
--> Security of code.
--> Modular Programming.
Modular:
-----------A large problem can be divided into smaller
problems and then they can be solved and
integrated by individual functions.
Function Syntax:
---------------------CREATE [OR REPLACE] FUNCTION
<function name > [(<parameter list>)]
RETURN <data type>
IS
<declare division>
BEGIN
<main division>
RETURN (<value>);
[EXCEPTION]
<exception division>
RETURN (<value>);
END [<function name>];
*)What is parameter?
---------------------------paramters are varible to receive / pass value from
functions and procedures. PL SQL provide three types of parameters :
IN
-->To receive values from outside.
OUT
-->To pass values Out of Program.
IN OUT -->To receive /pass values.
Note: In functions never use OUT or IN OUT
parameters , because functions pass/return
value using RETURN statement.
*)Syntax to define Parameters :
-----------------------------------------<parameter Name> [<type>] <data type> [:=<value>]
Default <type > will be IN.
Max 255 parameters can be defined with one
function or procedure.
1)Take a name and reverse it using functions?
------------------------------------------------------------CREATE OR REPLACE FUNCTION
MyReverse(pStr IN VARCHAR2) RETURN VARCHAR2
IS
vTemp VARCHAR2(2000);
BEGIN
FOR x IN REVERSE 1..LENGTH(pStr)
LOOP
vTemp :=vTemp||SUBSTR(pSTR,x,1);
END LOOP;
RETURN (vTemp);
END MyReverse;
/
*)Using the above function in PL SQL:
---------------------------------------------------BEGIN
FOR c1 IN (SELECT ename FROM emp)
LOOP
dbms_output.put_line(MyReverse(c1.ename));
END LOOP;
END;
/
2)Display ASCII chars between 128 to 255?
--------------------------------------------------------BEGIN
FOR x IN 128..255
LOOP
dbms_output.put_line(x||'='||CHR(x));
END LOOP;
END;
/
3)Find a Length of string using your attached character?
-----------------------------------------------------------------------CREATE
OR
REPLACE FUNCTION
MyLength(pStr IN VARCHAR2) RETURN NUMBER
IS
vStr VARCHAR2(200) := pStr||CHR(255);
vCount NUMBER :=1;
BEGIN
WHILE(SUBSTR(vStr,vCount,1)<> CHR(255))
LOOP
vCount := vCount+1;
END LOOP;
RETURN(vCount);
END MyLength;
/
testing:
--------select length(ename),MyLength(ename) from emp;
Note:
------Never try to change the value on parameter.
Ex: Take pStr and assign to som variable.
4)Prepare your own CEIL Function?
-----------------------------------------------CREATE OR REPLACE FUNCTION
MyCeil(vNum IN Number)
RETURN NUMBER
IS
vTemp NUMBER := abs(vNum);
v1 VARCHAR2(20) := ' ';
v2 VARCHAR2(20);
BEGIN
FOR x IN 1..LENGTH(vTEmp)
LOOP
IF SUBSTR(vTemp,x,1)<> '.' THEN
v1:=v1||SUBSTR(vTemp,x,1);
ELSE
FOR y IN x+1..LENGTH(vTEmp)
LOOP
v2:=v2||SUBSTR(vTemp,y,1);
END LOOP;
END IF;
END LOOP;
IF SIGN(vNum) =1 THEN
IF TO_NUMBER(v2) > 0 THEN
RETURN(v1+1);
ELSE
RETURN(v1);
END IF;
END IF;
IF sign(vNum) =-1 THEN
RETURN(v2*-1);
END IF;
END MyCeil;
/
Procedures:
==========
*)Is a stored program like Function. But it does not value directly.
*)To return value from procedure we can use OUT/IN OUT parameters.
*)Procedures are not allowed in SQL statements
*)How to decide FUNCTION or PROCEDURE?
--------------------------------------------------------------sol)If Function/Procedure is used by any programmer
(Front-end/Back-end) then create FUnctions.
IF user is End_User then use Procedures until user ask for
Function specially.
Note: Function we cannot execute from SQL*PLUS.
Procedure Syntax:
-----------------------CREATE [OR REPLACE] PROCEDURE
<prodcedure name> [(<Parameter List>)]
IS
<declare division>
BEGIN
<main divivion>
[ECEPTION]
<exception division>
END [<procedure name>];
How to execute / call a procedure:
---------------------------------------------1).From SQL*PLUS
EXECUTE <procedure name>[<value list>)]
2).From Any PLSQL Block:
<procedure Name> [(<Value List>)];
Q) Create PLSQL Program to insert new record in Dept Table with following valida
tions:
---------------------------------------------------------------------------------------------------------------------------------1)Dept must be Unique
2)Dept name must start with alphabet
3)Location must be 'boastan,new York or chicago.
and This program will be used by end_user.
figure
------*) Function to check Department Number?
--------------------------------------------------------CREATE OR REPLACE FUNCTION Check_Deptno
(pDeptno IN NUMBER) RETURN NUMBER
IS
CURSOR c1 IS
SELECT 'x' FROM dept
WHERE deptno=pDeptno;
vTemp CHAR(1);
BEGIN
OPEN c1;
FETCH c1 INTO vTemp;
CLOSE c1;
IF vTemp IS NULL THEN
RETURN (-1);
ELSE
RETURN(1);
END IF;
--Not Found
--Found
END Check_Deptno;
/
execution:
SELECT Check_Deptno(10),Check_Deptno(11) FROM dual;
*)Function to check deptname:
----------------------------------------CREATE OR REPLACE FUNCTION Check_Dname
(pDname IN VARCHAR2) RETURN NUMBER
IS
BEGIN
IF UPPER(SUBSTR(pDname,1,1))
BETWEEN 'A' AND 'z' THEN
RETURN (1);
ELSE
RETURN(-1);
END IF;
END Check_Dname;
/
execution:
SELECT check_dname ('sales'),check_dname('1sales') FROM dual;
*)Function to Check Location:
---------------------------------------CREATE OR REPLACE FUNCTION Check_Loc
(pLoc IN VARCHAR2) RETURN NUMBER
IS
BEGIN
IF UPPER(LTRIM(RTRIM(pLoc))) IN
('CHICAGO','BOSTON','NEW YORK')
THEN
RETURN(1);
ELSE
RETURN(-1);
END IF;
END Check_Loc;
execution:
SELECT Check_Loc('HYD'),Check_Loc('Chicago') FROM dual;
*) Using the above Three Function adding the department?
-------------------------------------------------------------------------------CREATE OR REPLACE PROCEDURE Add_Dept
(
pDeptno IN NUMBER,
pDname IN VARCHAR2,
pLoc IN VARCHAR2
)
IS
BEGIN
IF Check_Deptno(pDeptno)=1 THEN
dbms_output.put_line('Duplicate dept');
ELSIF Check_Dname(pDname) =-1 THEN
dbms_output.put_line('Invalid dname');
ELSIF Check_Loc(pLoc) =-1 THEN
dbms_output.put_line('Invalid location');
ELSE
INSERT INTO dept(deptno,dname,loc)
VALUES (pDeptno,pDname,pLoc);
COMMIT;
dbms_output.put_line('Dept Added');
END IF;
END Add_Dept;
/
executiuon:
SQL> EXECUTE Add_Dept(10,'Finance','Chicago');
Duplicate dept
SQL> EXECUTE Add_Dept(80,'PERSONNEL','BOSTON');
Dept Added
Note:
------To display the output to the front programmer instead of displaying the output o
n screen using procedure,the same above procedure is to be written in function.
It is to be executed like below:
BEGIN
dbms_output.put_line(Add_Dept(60,'Store','Boston));
END;
Note:
The following will not work.
SELECT ADD_Dept(60,'STORE','BOSTON') FROM dual;
Q) Create PLSQL Program to add new Record in employee
table with the following validations:
-Employee Number must be unique.
-Employee Name should not keep other than alphabet and space
-Job must be manager,clerk,salesmand,analyst
-manager number must be existing employee number
-hire date should not be future date
-salary must be witin the range of salgrade table.
-commison is only for salesmand
(other than salesman is has to take null value)
-dept number must be in dept table.
*)Function for knowing employee number must be unique:
-----------------------------------------------------------------------------CREATE OR REPLACE FUNCTION
Check_EmpNo(pEmpno IN NUMBER) RETURN NUMBER
IS
CURSOR c1 IS
SELECT 'x' FROM emp
WHERE empno=pEmpno;
vTemp CHAR(1);
BEGIN
OPEN c1;
FETCH c1 INTO vTemp;
CLOSE c1;
IF vTemp IS NULL THEN
RETURN(-1); --NOT FOUND
ELSE
RETURN(1); --FOUND
END IF;
END Check_Empno;
Checking:
SQL> SELECT Check_Empno(7638) FROM dual;
CHECK_EMPNO(7638)
-----------------1
*) Prepare a Function to maintain Employee name should not
--------------------------------------------------------------------------------keep other than Alphabet,space:
-------------------------------------------CREATE OR REPLACE FUNCTION
Check_Ename(pEname in Varchar2) RETURN NUMBER
IS
vEname varchar2(200) :=UPPER(REPLACE(pEname,' '));
vPos number(3) :=1;
vFlag boolean;
BEGIN
WHILE(vPos <= LENGTH(vEname))
LOOP
IF SUBSTR(vEname,vPos,1) BETWEEN 'A' AND
'Z' THEN
vFlag:=True;
vPos:=vPos+1;
ELSE
vFlag:=false;
vPos:=LENGTH(vEname)+1;
END IF;
END LOOP;
IF (vFlag) THEN
RETURN(1);
ELSE
RETURN(-1);
END IF;
END Check_Ename;
/
checking:
SQL> SELECT Check_Ename('SOMA9 SEKHAR') FROM dual;
CHECK_ENAME('SOMA9SEKHAR')
--------------------------1
*) Prepare a function to maintain the job must be in salesman,
--------------------------------------------------------------------------------clerk or analyst:
-------------------CREATE OR REPLACE FUNCTION
Check_Job(pJob in varchar2) RETURN NUMBER
IS
BEGIN
IF UPPER(LTRIM(RTRIM(pJob))) IN
('MANAGER','SALESMAN','CLERK','ANALYST') THEN
RETURN(1);
ELSE
RETURN(-1);
END IF;
END CHECK_JOB;
/
checking:
SQL> SELECT Check_Job('purchase') FROM dual;
CHECK_JOB('PURCHASE')
---------------------1
*)Create a function to check mgr number must be existing
------------------------------------------------------------------------------employee number:
------------------------CREATE OR REPLACE FUNCTION
Check_Mgr(pMgr IN NUMBER) RETURN NUMBER
IS
CURSOR c1 IS
SELECT 'x' FROM emp
WHERE empno=pMgr;
vTemp char(1);
BEGIN
OPEN c1;
FETCH c1 INTO vTemp;
CLOSE c1;
IF vTemp IS NULL THEN
RETURN (-1); --NOT FOUND
ELSE
RETURN(1);
--FOUND
END IF;
END Check_Mgr;
/
checking:
SQL>SELECT Check_Mgr(7839),Check_Mgr(1832) FROM dual
CHECK_MGR(7839) CHECK_MGR(1832)
--------------- --------------1
-1
*)Prepare a Function for cheking hiredate should not be
-------------------------------------------------------------------------futute date:
--------------CREATE OR REPLACE FUNCTION
Check_Hiredate(pHiredate IN DATE) RETURN NUMBER
IS
BEGIN
IF(TO_CHAR(pHiredate)>sysdate) THEN
RETURN(-1);
ELSE
RETURN(1);
END IF;
END Check_Hiredate;
/
checking:
SQL>SELECT Check_Hiredate('01-dec-2002'),
Check_Hiredate('01-jan-2002') FROM dual;
Check_Hiredate('01-DEC-2002') Check_Hiredate('01-JAN-2002')
---------------------------------------------------- ----------------------------1
1
*)Prepare aFunction to maintain sal within salgrade table:
---------------------------------------------------------------------------CREATE OR REPLACE FUNCTION
Check_Sal(pSal IN NUMBER) RETURN NUMBER
IS
CURSOR c1 IS
SELECT MIN(losal) ,MAX(hisal) FROM salgrade;
vMax NUMBER(7,2);
vMin NUMBER(7,2);
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO vMin,vMax;
EXIT WHEN c1 %NOTFOUND;
END LOOP;
CLOSE c1;
IF(pSal BETWEEN vMin and vMax) THEN
RETURN(1);
ELSE
RETURN(-1);
END IF;
END Check_Sal;
/
Checking:
SELECT Check_Sal(800),Check_sal(6000) FROM dual;
CHECK_SAL(800) CHECK_SAL(6000)
-------------- --------------1
1
*)Prepare a Function to Check Department Function must be
-------------------------------------------------------------------------------in Department table:
--------------------------CREATE OR REPLACE FUNCTION
Check_Deptno(pDeptno IN NUMBER) RETURN NUMBER
IS
CURSOR c1 IS
SELECT 'x' FROM dept
WHERE deptno=pDeptno;
vTemp CHAR(1);
BEGIN
OPEN c1;
FETCH c1 INTO vTemp;
CLOSE c1;
IF vTemp IS NULL THEN
RETURN(-1); --NOT FOUND
ELSE
RETURN(1); --FOUND
END IF;
END Check_Deptno;
/
Checking:
-------------SQL> SELECT Check_Deptno(10),Check_Deptno(60) FROM dual;
CHECK_DEPTNO(10) CHECK_DEPTNO(60)
---------------- ---------------1
-1
*) Prepare a Function to Check Comm is only for salesman:
------------------------------------------------------------------------------Other than salesman it has to take the null value:
-----------------------------------------------------------------CREATE OR REPLACE FUNCTION
Check_Comm(pJob IN VARCHAR2,
pComm IN NUMBER) RETURN NUMBER
IS
BEGIN
IF UPPER(pJob)='SALESMAN' THEN
IF pComm IS NOT NULL THEN
RETURN(1);
ELSE
RETURN(-1);
END IF;
ELSE
IF pComm IS NULL THEN
RETURN (1);
ELSE
RETURN(-1);
END IF;
END IF;
END Check_Comm;
/
Checking:
SQL>SELECT CHECK_COMM('ANALYST',500),
CHECK_COMM('salesman',200) FROM dual
Check_Comm('ANALYST',500) heck_Comm('SALESMAN',200)
------------------------- ------------------------------------------------------1
1
*)Add all the cheks and add the employee:
--------------------------------------------------------CREATE OR REPLACE PROCEDURE Add_Emp
(
pEmpno in NUMBER,
pEname IN VARCHAR2,
pJob IN VARCHAR2,
pMgr IN NUMBER,
pHiredate IN DATE,
pSal IN NUMBER,
pComm IN NUMBER,
pDeptno IN NUMBER
)
IS
BEGIN
IF Check_Empno(pEmpno) =1 THEN
dbms_output.put_line('Duplicate Empno');
ELSIF Check_Job(pJob)=-1 THEN
dbms_output.put_line('Invalid Job');
ELSIF Check_Ename(pEname)=-1 THEN
dbms_output.put_line('Invalid Name');
ELSIF Check_Mgr(pMgr)=-1 THEN
dbms_output.put_line('Invalid Manager');
ELSIF Check_Hiredate(pHiredate)=-1 THEN
dbms_output.put_line('Invalid Date');
ELSIF Check_Sal(pSal)=-1 THEN
dbms_output.put_line('Invalid Salary');
ELSIF Check_Comm(pJob,pComm)=-1 THEN
dbms_output.put_line('Comm not Valid');
ELSIF Check_Deptno(pDeptno)=-1 THEN
dbms_output.put_line('Invalid Department');
ELSE
INSERT INTO emp(empno,ename,job,mgr,hiredate,
sal,comm,deptno) VALUES
(pEmpno,pEname,pJob,pMgr,pHiredate,pSal,
pComm,pDeptno);
COMMIT;
dbms_output.put_line('Employee Added');
END IF;
END Add_Emp;
/
execution:
-----------execute Add_emp(8000,'SOMU','CLERK',7839,'12-jan-2002',6000,null,
30);