04 - Functions

PL/SQL Functions

What is a Function in PL/SQL?

A function is a named PL/SQL Block which is similar to a procedure. The major difference between a procedure and a function is, a function must always return a value, but a procedure may or may not return a value.

General Syntax to create a function is

CREATE [OR REPLACE] FUNCTION function_name [parameters]

RETURN return_datatype;

IS

Declaration_section

BEGIN

Execution_section

Return return_variable;

EXCEPTION

exception section

Return return_variable;

END;

1) Return Type: The header section defines the return type of the function. The return datatype can be any of the oracle datatype like varchar, number etc.

2) The execution and exception section both should return a value which is of the datatype defined in the header section.

For example, let’s create a frunction called ''employer_details_func' similar to the one created in stored proc

1> CREATE OR REPLACE FUNCTION employer_details_func

2> RETURN VARCHAR(20);

3> IS

5> emp_name VARCHAR(20);

6> BEGIN

7> SELECT first_name INTO emp_name

8> FROM emp_tbl WHERE empID = '100';

9> RETURN emp_name;

10> END;

11> /

In the example we are retrieving the ‘first_name’ of employee with empID 100 to variable ‘emp_name’.

The return type of the function is VARCHAR which is declared in line no 2.

The function returns the 'emp_name' which is of type VARCHAR as the return value in line no 9.

How to execute a PL/SQL Function?

A function can be executed in the following ways.

1) Since a function returns a value we can assign it to a variable.

employee_name := employer_details_func;

If ‘employee_name’ is of datatype varchar we can store the name of the employee by assigning the return type of the function to it.

2) As a part of a SELECT statement

SELECT employer_details_func FROM dual;

3) In a PL/SQL Statements like,

dbms_output.put_line(employer_details_func);

This line displays the value returned by the function.

Shembull 1

a- Ndertoni nje funksion qe merr si argument kodin e nje departamenti dhe kthen numrin e punonjesve qe ka ai departament

create or replace function punonjes_ne_dept

(

dep_id number

)

return number

is

punonjes number;

begin

select count(*) into punonjes

from employees

where department_id=dep_id;

return punonjes;

end;

b- Duke perdorur funksioni e krijuar afishoni per cdo departament vetem per departamentet qe kane me shume se zero punonjes.

Kodi

Emri_Departamentit

Numri_punonjesve

select

department_id as Kodi,

department_name as Emri_Departamentit,

punonjes_ne_dept_endri(department_id) as Numri_Punonjesve

from departments

where punonjes_ne_dept_endri(department_id)>0;

c- Duke perdorur funksioni e krijuar afishoni perbri cdo departamenti departamentet qe kane me shume punonjes se ai, si me poshte

Hint: Funksionet ne kushtin e JOIN

select

te_vegjel.department_id as Kodi,

te_vegjel.department_name as Emri_Departamentit,

punonjes_ne_dept_endri(te_vegjel.department_id) as Numri_Punonjesve,

te_medhenj.department_id as Kodi2,

te_medhenj.department_name as Emri_Departamentit2,

punonjes_ne_dept_endri(te_medhenj.department_id) as Numri_Punonjesve2

from departments te_vegjel inner join departments te_medhenj

on punonjes_ne_dept_endri(te_vegjel.department_id)<

punonjes_ne_dept_endri(te_medhenj.department_id)

where punonjes_ne_dept_endri(te_vegjel.department_id)>0 ;

Shembull 2

Te ndertojme nje funksion qe merr si argument kodin e nje punonjesi dhe kthen numrin e hereve qe ai ka ndryshuar pune, pa llogaritur pozicioni korrent.

create or replace function ndryshim_pune

(

eid number

)

return number

is

here number;

begin

select count(*) into here

from job_history

where employee_id=eid

group by employee_id;

return here;

end;

Versioni i permiresuar i funsionit qe merr parasysh edhe vlerat NULL

create or replace function ndryshim_pune

(

eid number

)

return number

is

here number;

begin

select NVL(count(*),0) into here

from job_history

where employee_id=eid

;

return here;

end;

Sqarime

Funksioni NVL(shprehje,vlere) kthen shprehje nese shprehja nuk eshte NULL ose vlere nese shprehja eshte NULL

IF shprehje IS NULL THEN

--return vlere

ELSE

--return shprehje

END IF

a.

Duke perdorur funksionin e krijuar afishoni listen e punonjesve qe nuk kane ndryshuar pune asnjehere.

select First_name,ndryshim_pune(employee_id)

from employees

where ndryshim_pune(employee_id)=0;

b.

Duke perdorur funksionin e krijuar afishoni perbri cdo punonjesi ata punonjes qe kane ndryshuar pune me shpesh se ai. Kerkesa shtrohet per punonjesit qe kane ndryshuar pune te pakten nje here

select stabel.First_name,stabel.Last_name,ndryshim_pune(stabel.employee_id),

jo_stabel.First_name,JO_STABEL.LAST_NAME,ndryshim_pune(jo_stabel.employee_id)

from employees stabel inner join employees jo_stabel

on ndryshim_pune(stabel.employee_id)<ndryshim_pune(jo_stabel.employee_id)

where ndryshim_pune(stabel.employee_id)>0;

c.

Duke perdorur funksionin e krijuar afishoni sa here punonjesit kane ndryshuar pune si me poshte:

Here

1

...

Punonjes

100

...

select ndryshim_pune(employee_id),count(*) as Punonjes

from employees group by ndryshim_pune(employee_id);

Ushtrim 1

A) Ndertoni nje funksion me emrin ndryshime_strukturore i cili merr si argument kodin e nje departamenti dhe kthen ndryshimet qe ka pesuar ai ne numerin e punonjesve.

Zgjidhje

create or replace function ndryshime_strukturore

(

dep_id number

)

return number IS

total number(4) :=0;

ka number(4):=0;

ka_patur number(4):=0;

BEGIN

SELECT count(*) INTO ka

FROM Employees

where department_id=dep_id;

SELECT count(*) INTO ka_patur

FROM job_history

WHERE department_id=dep_id;

total:=ka-ka_patur;

return total;

END;

b) Afishoni nje liste me departamentet dhe me ndryshimet e tyre strukturore si me poshte

Kodi

Emer_Departamenti

Ndryshime_Nr_Punonjes

Zgjidhje

Ushtrim 2 (*)

A)Duam te dime sa punonjes ka patur nje departament ne nje date te caktuar.

Punonjesit e departamentit ne nje date te caktuar jane:

ata qe ndodhen ne tabelen employees me hire_date me te vogel se data per te cilen interesohemi

ata qe ndodhen ne tabelen job_history me kusht qe data per te cilen e interesohemi te jete midis start_date dhe end_date

Ndertoni nje funksion qe merr si argument nje date dhe nje kod departamenti dhe kthen sa punonjes ka patur ai departament ne ate date.

b) Ndertoni nje query qe afishon sa punonjes ka patur cdo departament ne nje date x.

Zgjidhje

Ushtrim 3

A-- Ndertoni nje funksion qe merr si argument kodin e nje punonjesi dhe kthen numrin e viteve te punes qe ai ka na pozicionin aktual.

Sqarime:

funksioni MONTHS_Between(dt1,dt2) kthen numrin e muajve midis dy datave dt1,dt2. Nese pjesesohet me 12 atehere gjejme numrin e viteve si numer me presje.

Funksioni ROUND(shprehje,precizion) ben rrumbullakosjen e nje numri me precizionin perkates. ROUND(shpreshje,0) e rrumbullakos ne numer te plote.

{me shume https://sites.google.com/a/ictedu.info/oracle-1z0-051/home/chapter-05}

CREATE OR REPLACE FUNCTION vite_pune_tani

(

emp_id number

)

RETURN number IS

total number(4) := 0;

BEGIN

SELECT round(months_between(sysdate,hire_date)/12,0) into total

FROM employees where employee_id=emp_id;

RETURN total;

END;

--B

Afishoni te dhenat e punonjesve dhe vjetersine ne vite pune qe ka sejcili ne pozicionin aktual te punes

Ushtrim 4

A-- Ndertoni nje funksion qe merr si argument kodin e nje punonjesi dhe nje date. Funksioni kthen numrin e viteve te punes qe ka punonjesi ne pozicionin e aktual te punes duke nisur llogaritjen nga data qe merr si argument.

CREATE OR REPLACE FUNCTION vite_pune_ne_date

(

emp_id number,

deri_me date

)

RETURN number IS

total number(4) := 0;

BEGIN

SELECT round(months_between(deri_me,hire_date)/12,0) into total

FROM employees where employee_id=emp_id;

RETURN total;

END;

--B

Funksioni vite_pune_ne_date duhet te ktheje vitet e punes deri ne daten korrente (sysdate) nese kur therrit nuk i jepet argumenti date

CREATE OR REPLACE FUNCTION vite_pune_ne_date

(

emp_id number,

deri_me date:=sysdate

)

RETURN number IS

total number(4) := 0;

BEGIN

SELECT round(months_between(deri_me,hire_date)/12,0) into total

FROM employees where employee_id=emp_id;

RETURN total;

END;

--C

Afishoni te dhenat e punonjesve dhe vjetersine ne vite pune qe ka sejcili ne pozicionin aktual te punes ne daten 1-JAN-2012.

select employee_id,first_name,last_name,vite_pune_ne_date(employee_id,'1-JAN-2001')

from employees;

--D

Afishoni te dhenat e punonjesve dhe vjetersine ne vite pune qe ka sejcili ne pozicionin aktual te punes ne daten e sotme

select employee_id,first_name,last_name,vite_pune_ne_date(employee_id)

from employees;

Ushtrim 4

Ndertoni nje funksion qe merr si argument kodin e nje shteti (CHAR(2)) dhe kthen numrin e punonjesve qe punojne ne ate shtet.

Zgjidhje

create or replace function punonjes_ne_shtetin

(

shteti CHAR

)

return number

is

punonjes number;

begin

select count(*) INTO punonjes

from employees e inner join departments d on e.department_id=d.department_id

inner join locations l on d.location_id=l.location_id

where country_id=shteti

group by country_id;

return punonjes;

end;

a. Afishoni per cdo shtet kodin,emrin dhe numrin e punonjesve ne ate shtet. Ne vend te vlerave nukk per punonjesit te vendoset 0.

Country_id

US

Country_Name

United States of America

Punonjes

2

Zgjidhje

select country_id,COUNTRY_NAME,NVL(punonjes_ne_shtetin(country_id),0) as punonjes

from countries;

b. Afishoni per cdo shtet kodin,emrin dhe numrin e punonjesve ne ate shtet.

dhe perbri tij kodin emrin dhe numrin e punonjesve te shteteve qe kane me shume punonjes se ai.

select small.country_id,small.COUNTRY_NAME,NVL(punonjes_ne_shtetin(small.country_id),0) as punonjes,

big.country_id,big.COUNTRY_NAME,NVL(punonjes_ne_shtetin(big.country_id),0) as punonjes

from countries small inner join countries big on NVL(punonjes_ne_shtetin(small.country_id),0)<NVL(punonjes_ne_shtetin(big.country_id),0) ;

Ushtrim 5

Ndertoni nje funksion qe kthen 1 nese punonjesi eshte rikthyer ne pozicionin e punes dhe 0 nese jo.

zgjidhje

create or replace function rikthim

(

eid number

)

return number

is

rezultat number;

here number;

p varchar2(20);

begin

select job_id into p

from employees where employee_id=eid;

select count(*) into here

from job_history

where employee_id=eid and job_id=p;

if here>0 then

rezultat:=1;

else

rezultat:=0;

end if;

return rezultat;

end;

a. Afishoni per cdo punonjes kodin,emrin dhe 0 ose 1 nese eshte rikthyer ne pozicionin e meparshem

select employee_id,first_name,nvl(rikthim(employee_id),0) from employees

where nvl(rikthim(employee_id),0)>0 ;