Professional Documents
Culture Documents
Cursssor
Cursssor
- o procedura care va fi apelata din a doua procedura, care modifica salariile angaja?ilor, prin adunarea cu 10 la salariul
existent
- o procedura care preia angajatii dintr-un departament dat ca parametru si care va ntoarce numarul de angajati din
acel departament.
Calculul pentru modificarea salariilor se vor face n bucla, cu cursor;
Package-ul va fi verificat ntr-un bloc anonim PL/SQL, n care se va cere de la tastatura numarul departamentului si
tipul operatiei
(0 afisare salarii, 1 modificare salarii) si care va afisa numarul de angajati din departament (ntors de procedura din
package) si
salariile angaja?ilor din acel departament, modificate sau nu, functie de tipul operatiei.
Barem:
(1p) din oficiu
(1p) specificatia package-ului (n care se va scrie ntr-un comentariu argumentat care sunt constructiile publice si
private)
(5p) corpul package-ului (2p procedura de modificare a salariilor si 3p procedura care apeleaza procedura de
modificare a salariilor si ntoarce numarul de angajati)
(3p) blocul anonim PL/SQL*/
create or replace package emp_pack
is
procedure tk_empno(
v_deptno in emp.deptno%type,
nr_salariati out number);
end;
/
create or replace package body emp_pack
is
procedure modifica_salariu(
v_empno emp.empno%type)
is
begin
update emp
set sal=sal+10
where empno=v_empno;
end modifica_salariu;
procedure tk_empno(
v_deptno in emp.deptno%type,
nr_salariati out number)
is
cursor c1 is
select empno
from emp
where deptno=v_deptno;
begin
for c1_record in c1 loop
modifica_salariu(c1_record.empno);
nr_salariati:=c1%rowcount;
end loop;
end tk_empno;
end;
/
accept p_deptno prompt 'Dati nr dep: '
accept p_operatie prompt 'Dati tipul operatiei: '
declare
v_nr number(3);
v_deptno emp.deptno%type:=&p_deptno;
v_operatie number:=&p_operatie;
cursor c1 is
select ename,sal
from emp
where deptno=v_deptno;
begin
if v_operatie=1 then
emp_pack.tk_empno(v_deptno,v_nr);
dbms_output.put_line('Au fost modificati '||v_nr || ' angajati in dept. ' || v_deptno);
end if;
for c1_record in c1 loop
dbms_output.put_line(' ');
dbms_output.put_line(c1_record.ename||' '||c1_record.sal);
end loop;
rollback;
end;
--1.Afisati numele angajatilor care au 2 de 'L' in numele lor si sunt din departamentul 30 sau au manager cu marca
7782.
select ename
from emp
where ename like '%l%l%' and deptno=30 or mgr=7782
--2.Afisati numele si salariul tuturor angajatilor a caror salarii nu intra in intervalul 1500$ si 2850$.
select ename,lpad(sal,7)salary
from emp
where sal not between 1500 and 2850
order by salary
--3.Listati alfabetic numele si salariul celor care castiga mai mult de 1500$ si sunt in departamentele 10 sau 30.
Redenumiti
--coloanele Angajat si Salar Lunar
select ename Angajat,lpad(sal,7)Salar_Lunar
from emp
where sal > 1500 and deptno in(10,30)
order by Salar_Lunar
--4.Afisati codul, numele, salariul si salariul marit cu 15%. Denumiti ultima coloana Salar Nou. Adaugati o coloana in
care veti face
--diferenta dintre salariul nou si cel vechi. Denumiti noua coloana Crestere.
select empno,ename,lpad(sal,7)salary,lpad((sal+sal*0.15),7)Salar_Nou,lpad(sal+sal*0.15-sal,7)Crestere
from emp
order by sal
-select empno,ename,lpad(sal,7)salary,lpad((sal*1.15),7)Salar_Nou,lpad(sal*1.15-sal,7)Crestere
from emp
order by sal
--5.Pentru fiecare angajat afisati numele si calculati numarul de luni intre data de astazi si data angajarii, iar coloana sa
se
--denumeasca luni_de_activitate. Ordonati rezultatul dupa numarul de luni de lucru. Rotunjiti numarul de luni.
select ename,trunc(months_between(sysdate,hiredate)) luni_de_activitate
from emp
order by luni_de_activitate
--6.Scrieti o interogare care afiseaza numele, meseria, numarul departamentului si numele departamentului pentru
toti angajatii
--care lucreaza in Dallas.
select ename,job,lpad(e.deptno,7)department_id,dname
from emp e inner join dept d on e.deptno=d.deptno
and loc='Dallas'
order by dname
--7.Afisati numele angajatului si numarul lui impreuna cu numele managerului si numarul acestuia. Etichetati coloanele
--Employee, Emp#, Manager, Mgr#.
select e.ename Employee,e.empno Emp#,m.ename Manager,e.mgr Mgr#
from emp e inner join emp m on e.mgr=m.empno
order by e.mgr
--8.Creati o interogare care va afisa numele, meseria, numele departamentului, salariul si gradul pentru toti angajatii.
select distinct ename,job,dname,lpad(sal,7)salary,lpad(grade,7)grade_level
from emp e left outer join dept d
on e.deptno=d.deptno inner join salgrade s on e.sal between s.losal and s.hisal
order by salary
--9.Scrieti o interogare pentru afisarea numarului de angajati cu aceeasi meserie.
select job,count(empno)No_of_Employees
from emp
group by job
order by No_of_Employees
--10.Scrieti o interogare care sa afiseze diferenta dintre salariile cele mai mari si cele mai mici. Etichetati coloana
'Diferenta'.
select max(sal)-min(sal) Diferenta
from emp
--11.Afisati numarul managerului si salariul celui mai prost platit angajat pentru acel manager. Excludeti pe cei ce nu au
manager.
--Excludeti grupurile care au salariul mai mic decat 1000$. Sortati rezultatele in ordine descrescatoare dupa salar.
select e.mgr,m.ename,min(e.sal)Minimum_Salary
from emp e inner join emp m on e.mgr=m.empno
having min(e.sal)>1000
group by e.mgr,m.ename
minus
select e.mgr,m.ename,min(e.sal)
from emp e inner join emp m on e.mgr=m.empno
where e.mgr is null
group by e.mgr,m.ename
order by Minimum_Salary desc
--sau
select e.mgr,m.ename,min(e.sal)Minimum_Salary
from emp m inner join emp e on e.mgr=m.empno
having min(e.sal)>1000 and e.mgr is not null
group by e.mgr,m.ename
order by Minimum_Salary
--12.Sa se creeze o cerere pentru a afisa numarul angajatului si numele sau pentru toti angajatii care castiga mai mult
decat salariul
--mediu. Sa se sorteze rezultatele in ordinea descrescatoare a salariului.
select empno,ename,lpad(sal,7)salary
from emp
where sal>
(select avg(sal)
from emp)
order by salary
--13.Afisati numele si salariul tuturor angajatilor subordonati lui King
select ename,lpad(sal,7)salary
from emp
where mgr =
(select empno
from emp
where ename='King')
order by salary
--14.Scrieti o interogare care sa afiseze numele, numarul departamentului si salariul oricarui angajat al carui numar
--de departament si salariu sa se potriveasca cu numarul departamentului si salariul oricarui angajat care percepe un
comision.
select ename,d.deptno,lpad(sal,7)salary
from emp e inner join dept d on e.deptno=d.deptno
where (e.deptno,sal) in
(select e.deptno,sal
from emp
where comm is not null)
order by salary
--15.Scrieti o interogare care sa afiseze angajatii care castiga un salariu mai mare ca al oricarui angajat
functionar(clerks).
--Afisati salariile de la cel mai mare la cel mai mic.
select ename,job,lpad(sal,7)salary
from emp
where sal>all
(select sal
from emp
where job='Clerk')
order by salary desc
--16.Scrieti un script file pentru a afisa numele, functia si data angajarii pentru toti salariatii care au inceput sa lucreze
--intr-o anumita perioada. Se concateneaza numele si functia impreuna, separate de un spatiu si virgula si etichetati
coloana
--'Employees'. Datele calendaristice care delimiteaza perioada se vor introduce de la tastatura. Se utilizeaza formatul
MM//DD/YY.
accept dip date format 'MM/DD/YYYY' prompt 'Introduceti inceputul perioadei : '
accept dsp date format 'MM/DD/YYYY' prompt 'Introduceti sfarsitul perioadei : '
select ename ||', '|| job Employees, hiredate
from emp
where hiredate between to_date('&dip','MM/DD/YYYY') and to_date('&dsp','MM/DD/YYYY')
order by hiredate
--17.Creati un tabel numit employee cu structura de mai jos:
--drop table employee
create table employee(
id number(7)
constraint pk_employee primary key
constraint nn_employee not null,
last_name varchar2(25),
constraint nn_last_name not null,
first_name varchar2(25)
constraint nn_first_name not null,
userid varchar2(8)
constraint nn_userid not null
constraint un_userid unique,
salary number(10)
constraint ck_salary check(salary > 500 and salary < 20000),
department_id number(7)
constraint fk_department_id1 references departments(department_id));
--adaugarea de comentarii la nivelul tabelei si afisarea din dictionarul de date
comment on table employee is 'Employee Information: ';
column table_name format a15
column table_type format a10
column comments format a16
-select * from user_tab_comments
where table_name='employee';
--crearea secventei pentru introducerea automata a valorilor pentru campul ID
--drop sequence seq_id
CREATE SEQUENCE seq_id
MINVALUE 100
START WITH 100
INCREMENT BY 5
--introducere date in tabela employee, iar valorile coloanei id sunt introduse in mod automat pe baza secventei
construita anterior
insert into employee values(seq_id.nextval,'Ionescu','Ion',11,4000,10);
insert into employee values(seq_id.nextval,'Popescu','Ion',21,4000,10);
insert into employee values(seq_id.nextval,'Marinescu','Doru',31,5000,20);
insert into employee values(seq_id.nextval,'Vasilescu','Dumitru',41,500,10);
--mariti salariul angajatilor din departamentul 10 cu 5%
update employee
set salary = replace(salary,salary,salary*1.05)
where department_id=10
--verificare ca salariul a fost marit
select last_name,lpad(salary,7)old_salary,lpad(round(replace(salary,salary,salary*1.05)),7)new_salary
from employee
where department_id=10
--stergeti angajatii cu salariul mai mic de 800
delete from employee
where salary<800
--creati o vizualizare care sa afiseze urmatoarele informatii: nume si prenume (intr-o coloana), salariul lunar,
--salariul anual, numele departamentului si apoi interogati vizualizarea
create or replace view employees_view as
select first_name ||' '||last_name name, lpad(salary,7)salary, 12*salary as annual_salary,
department_name, d.department_id
from employees e inner join departments d on e.department_id=d.department_id
--interogarea vizualizarii
select * from employees_view
where salary between 3000 and 10000
order by department_id
--creati o vizualizare care sa afiseze suma salariilor, media salariilor, minimul si maximul salariilor pe departamente
create or replace view detalii_view as
select lpad(sum(salary),7)suma_salarii,lpad(round(avg(salary)),7)medie_salarii,
lpad(min(salary),7)salariul_minim,lpad(max(salary),7)salariu_maxim,department_id
from employees
where department_id is not null
group by department_id
order by department_id
--interogarea vizualizarii
select * from detalii_view
--creati sinonimul emp1 pentru employee si inserati inregistrari in noile obiecte
create or replace synonym emp1 for employee
-desc emp1
-insert into employee values(seq_id.nextval,'Dumitrescu','Marius',51,700,10);
insert into employee values(seq_id.nextval,'Vasile','Ionut',61,760,20);
insert into employee values(seq_id.nextval,'Murgoci','Ion',71,780,20);
--creati o tabela newemp cu structura si datele tabelei employee
create table newemp
as (select * from employee)
--afisati existenta tabelei in dictionarul de date
select table_name
from user_tables
--stergeti tabela si confirmati stergerea verificand in dictionarul de date
drop table newemp
--in tabela employee adaugati campul manager de tip numeric, latime 7, constrangere cheie externa de tip 'self
join'(coloana ID)
alter table employee
add manager number(7)
constraint fk_manager references employee(id)
--verificati existenta constrangerii in dictionarul de date
select * from user_constraints
--sa se creeze un index neunic pentru campul de tip foreign key din tabela employee
create index idxemployee_department_id on employee(department_id)
--verificati existenta indexului in dictionarul de date
select * from user_indexes
--1.Creati un bloc anonim si afisati urmatoarea fraza pe ecran: "My PL/SQL Block Works"
--set serveroutput on
declare
v_message varchar2(30);
begin
v_message:='My PL/SQL Block Works';
dbms_output.put_line(v_message);
end;
--2.Creati un bloc si declarati 2 variabile. Asignati valorile acestor variabile PL/SQL unor variabile de legatura si afisati-le
pe
--ecran.
declare
v_char varchar2(50);
v_num number(11,2);
begin
v_char:='9.57 a fost media mea la Baze de Date din anul III';
v_num:=to_number(substr(v_char,1,5));
dbms_output.put_line(v_char);
dbms_output.put_line(v_num);
end;
--3.Analizati blocul de mai jos si determinati urmatoarele valori:
--a.valoarea v_weight in sub-bloc
--b.valoarea v_new_locn in sub-bloc
--c.valoarea v_weight in blocul principal
--d.valoarea v_message in blocul principal
--e.valoarea v_new_locn in blocul principal
declare
v_weight number(3):=600;
v_message varchar2(255):='Product 11002';
begin
declare
v_weight number(3):=1;
v_message varchar2(255):='Product 11001';
v_new_locn varchar2(50):=' Europe';
begin
v_weight:=v_weight+1;
v_new_locn:='Western'||v_new_locn;
dbms_output.put_line(v_weight);
dbms_output.put_line(v_new_locn);
end;
v_weight:=v_weight+1;
v_message:=v_message || ' is in stock';
dbms_output.put_line(v_weight);
dbms_output.put_line(v_message);
end;
--4.Fie structura de mai jos, in care variabilele v_customer si v_credit_rating sunt declarate in blocul principal, iar
--1.Creati un bloc PL/SQL care sa selecteze numarul maxim al departamentului din tabela dept si sa il stocheze intr-o
variabila.
declare
v_max_deptno number;
begin
select max(deptno)
into v_max_deptno
from dept;
dbms_output.put_line('The maximum id for a department is ' || to_char(v_max_deptno));
end;
--2.Creati un bloc PL/SQL care sa insereze un nou departament in tabela dept.
--a.Folositi numarul departamentului returnat la punctul 1) si adunati 10 la acest numar ca fiind numarul
departamentului pentru
--noul departament.
--b.Folositi un parametru pentru numele departamentului.
--c.Lasati locatia nula deocamdata
--d.Executati blocul PL/SQL.
--e.Afisati noul departament creat.
declare
v_max_deptno dept.deptno%type;
v_dname dept.dname%type:='Finance';
v_result number(2);
begin
select max(deptno)
into v_max_deptno
from dept;
insert into dept(deptno,dname)values(v_max_deptno+10,v_dname);
v_result:=sql%rowcount;
dbms_output.put_line(v_max_deptno+10 ||' '||v_dname);
dbms_output.put_line(v_result || ' row(s) inserted');
end;
--3.Creati un bloc PL/SQL care sa actualizeze locatia pentru un departament existent.
--a.Folositi un parametru pentru nr departamentului.
--b.Folositi un parametru pentru locatia departamentului.
--c.Testati blocul PL/SQL.
--d.Afisati nr dept, numele dept si locatia pentru departamentul updatat.
--e.Afisati departamentul actualizat.
declare
v_deptno dept.deptno%type:=50;
v_dname dept.dname%type:='Finance';
v_loc dept.loc%type:='San Francisco';
v_result number(2);
begin
update dept
set loc = v_loc
where deptno=v_deptno;
v_result:=sql%rowcount;
dbms_output.put_line(v_deptno||' '||v_dname||' '||v_loc);
v_deptno number(2);
v_loc varchar2(15);
begin
select deptno,loc
into v_deptno,v_loc
from dept
where dname='Sales';
dbms_output.put_line('Numarul departamentului de vanzari este '||v_deptno||', iar acesta se afla in '||v_loc||'.');
end;
--2.Sa se returneze data comenzii si data de onorare pentru ordinea specificata
declare
v_orderdate ord.orderdate%type;
v_shipdate ord.shipdate%type;
begin
select orderdate,shipdate
into v_orderdate,v_shipdate
from ord
where ordid=617;
dbms_output.put_line('Data comenzii pentru produsul cu id-ul 157 este '||v_orderdate||', iar data onorarii este
'||v_shipdate);
end;
--3.Sa se returneze suma salariilor pentru toti angajatii dintr-un departament specificat
declare
v_sum_sal emp.sal%type;
v_deptno number not null:=10;
begin
select sum(sal)
into v_sum_sal
from emp
where deptno=v_deptno;
dbms_output.put_line('Suma salariilor angajatilor din departamentul '||v_deptno||' este '||v_sum_sal||' dollars per
month.');
end;
--4.Sa se adauge noi angajati in tabela emp
--mai intai se realizeaza o secventa
--increment by - specifica pasul de incrementare, implicit este 1
--start with - specifica prima valoare a secventei, implicit este 1
--maxvalue - valoarea maxima pe care secventa o poate genera
--cycle - secventa continua sa genereze valori dupa ce s-a atins valoarea maxima sau minima
--nocycle - nu genereaza valori aditionale, complementara lui cycle
--cache - specifica numarul de valori pe care serverul Oracle le va prealoca si le pastreaza in memorie, implicit sunt 20
de valori
create sequence empno_sequence
increment by 1
start with 8000
maxvalue 8100
nocache
nocycle
-declare
v_empno emp.empno%type;
v_result number(2);
begin
select empno_sequence.nextval
into v_empno
from dual;
insert into emp(empno,ename,job,deptno) values (v_empno,'Harding','Clerk',10);
v_result:=sql%rowcount;
dbms_output.put_line(v_result || ' row(s) inserted.');
end;
--verificare
select * from emp;
rollback;
select * from emp;
--5.Sa se mareasca salariul tuturor angajatilor din tabela emp care sunt analisti
declare
v_job emp.job%type:='Analyst';
v_sal_increase emp.sal%type:=2000;
v_result number(2);
begin
update emp
set sal=sal+v_sal_increase
where job=v_job;
v_result:=sql%rowcount;
dbms_output.put_line(v_result|| ' row(s) updated.');
end;
-select empno,ename,sal
from emp
where job='Analyst';
rollback;
select empno,ename,sal
from emp
where job='Analyst';
--6.Sa se stearga liniile care apartin departamentului 10 din tabela emp
declare
v_deptno emp.deptno%type:=10;
v_result number(2);
begin
delete from emp
where deptno=v_deptno;
v_result:=sql%rowcount;
dbms_output.put_line(v_result|| ' row(s) deleted.');
end;
--
select *
from emp
where deptno=10;
rollback;
select *
from emp
where deptno=10;
--7.Sa se stearga itemul a carui order este 605
declare
v_ordid ord.ordid%type:=605;
v_result number(2);
begin
delete from ord
where ordid=v_ordid;
v_result:=sql%rowcount;
dbms_output.put_line(v_result|| ' row(s) deleted.');
end;
-select *
from ord
where ordid=605;
rollback;
select *
from ord
where ordid=605;
--8.Sa se returneze data comenzii si data de onorare a comenzii din tabela ord unde data de onorare este azi.
declare
v_orderdate ord.orderdate%type:='01-08-1986';
v_shipdate ord.shipdate%type:='01-08-1987';
begin
select orderdate,shipdate
into v_orderdate,v_shipdate
from ord
where shipdate=v_shipdate;
dbms_output.put_line('Data comenzii este '||v_orderdate||', iar data onorarii este'||v_shipdate);
end;
--9.Sa se stearga liniile care au nr de ordine specificat in tabela item
declare
v_ordid number:=620;
v_result number(2);
begin
delete from item
where ordid=v_ordid;
v_result:=sql%rowcount;
dbms_output.put_line(v_result ||' row(s) deleted.');
end;
--
select *
from item
where ordid=620;
rollback;
select *
from item
where ordid=620;
--alta varianta
variable v_result number
declare
v_ordid number:=614;
begin
delete from item2
where ordid=v_ordid;
:v_result:=sql%rowcount;
end;
print v_result
--1.Creati tabela messages (text varchar2(50)). Scrieti un bloc PL/SQL pentru a insera numere in tabela messages.
--a.Inserati numerele de la 1 la 10 excluzand 6 si 8.
--b.Realizati commit inainte de finalul blocului
--c.Faceti un select pe tabela messages pentru a verifica daca blocul a functionat bine
drop table messages
-create table messages(
text varchar2(50))
-declare
v_result number(2);
begin
for i in 1..10 loop
if i=6 or i=8 then
null;
else
insert into messages values(i);
end if;
v_result:=sql%rowcount;
dbms_output.put_line(v_result || ' row(s) inserted.');
commit;
end loop;
end;
-select * from messages
--2.Creati tabela emp2 care are aceeasi structura ca si emp. Creati un bloc PL/SQL care calculeaza valoarea
comisionului
--pentru un angajat dat folosind salariul acestuia.
--a.Inserati un nou angajat in tabela emp2. Angajatul va avea salariul null.
--b.Acceptati nr angajatului ca intrare cu o variabila de substitutie.
--c.Daca salariul angajatului este mai mic ca 1000$ fixati comisionul angajatului la 10% din salar.
--d.Daca salariul angajatului este intre 1000$ si 1500$ fixati comsionul la 15% din salar.
--e.Daca salariul angajatului este mai mare ca 1500$ fixati comsionul la 20% din salar.
--f.Daca salariul angajatului este null fixati comisionul angajatului la 0
--g.commit
--h.Testati blocul PL/SQL pentru fiecare caz folosind urmatoarele cazuri de test:
--nr.angajatului este (7369, 7934, 7499, 8000)
--salariul este (800, 1300, 1600, null)
--comisionul este (80, 195, 320, null)
drop table emp2
-create table emp2 as select * from emp
insert into emp2(empno) values(8000);
-accept p_empno prompt 'Introduceti marca angajatului: '
declare
v_empno emp2.empno%type:=&p_empno;
v_sal emp2.sal%type;
v_comm emp2.comm%type;
v_result number(2);
begin
select sal
into v_sal
from emp2
where empno=v_empno;
if v_sal < 1000 then
v_comm:=.10;
elsif v_sal between 1000 and 1500 then
v_comm:=.15;
elsif v_sal > 1500 then
v_comm:=.20;
else
v_comm:=0;
end if;
update emp2
set comm = sal * v_comm
where empno=v_empno and sal=v_sal;
v_result:=sql%rowcount;
dbms_output.put_line(v_result || ' row(s) updated.');
commit;
end;
--verificare
select empno,ename,lpad(sal,7)salary,lpad(comm,7)comm
from emp2
where empno in(7369,7934,7499,8000)
order by comm
--3.Modificati exercitiul 1 pentru a insera textul "Numarul este par" sau "Numarul este impar", in functie de paritatea
sau imparitatea
--numarului, in tabela messages. Interogati tabela pentru a vedea daca blocul construit a functionat corect.
declare
v_char varchar2(20);
v_number number(10,2);
v_result number(2);
begin
delete
from messages;
v_char:='101 is the number';
v_number:=to_number(substr(v_char,1,4));
if mod(v_number,2)= 0 then
insert into messages values(v_number,'Numar par');
else
insert into messages values(v_number,'Numar impar');
end if;
v_result:=sql%rowcount;
dbms_output.put_line(v_char);
dbms_output.put_line(v_number);
dbms_output.put_line(v_result ||' row(s) inserted.');
end;
--sau
--drop table messages
create table messages
(result number(6),
text varchar2(25));
-declare
v_result number(2);
begin
for i in 1..10 loop
if mod(i,2)=0 then
insert into messages values (i,'par');
else
insert into messages values (i,'impar');
end if;
end loop;
commit;
end;
-select * from messages
--4.Adaugati o coloana noua numita stars la tabela emp2 pentru a stoca (*)
alter table emp2 add stars varchar2(100);
--5.Creati un bloc PL/SQL care recompenseaza un angajat concatenand un asterisc in coloana stars pentru fiecare 100$
din salariul angajatului.
--Rotunjiti salariul angajatului la cel mai apropiat nr intreg.
--a.Acceptati id-ul angajatului ca intrare intr-o variabila de substitutie.
--b.Initializati o variabila pentru a contine un sir de asteriscuri.
--c.Concatenati un asterisc la sir pentru fiecare 100$ din salar. De exemplu daca un angajat are un salar de 800$, sirul
de
--asteriscuri va contine 8 asteriscuri.
--d.Revizuiti coloana stars pentru angajat dupa metoda de la punctul anterior.
--e.realizati commit
--f.testati blocul pentru un angajat care are salariu.
accept p_empno prompt 'Dati marca angajatului: '
declare
v_empno emp2.empno%type:=&p_empno;
v_stars emp2.stars%type;
v_sal emp2.sal%type;
v_ename emp2.ename%type;
v_result number(2);
begin
select ename,nvl(sal/100,0)
into v_ename,v_sal
from emp2
where empno=v_empno;
for i in 1..v_sal loop
v_stars:=v_stars||'*';
end loop;
update emp2
set stars=v_stars
where empno=v_empno;
v_result:=sql%rowcount;
dbms_output.put_line(v_result || ' row(s) updated.');
commit;
end;
--verificare
select empno,lpad(sal,7)salary,stars
from emp2
where empno = 7839
order by stars
--Exemple din cartea de laborator
--1.Schimbati denumirea meseriei cu Salesman, numarul departamentului cu 35 si comisionul cu 20% a salariului
curent
--daca numele angajatului este Miller.
declare
v_ename emp2.ename%type;
v_job emp2.job%type;
v_deptno emp2.deptno%type;
v_sal emp2.sal%type;
v_comm emp2.comm%type;
v_result number;
begin
select ename,job,deptno,sal,comm
into v_ename,v_job,v_deptno,v_sal,v_comm
from emp2
where ename='Miller';
if v_ename='Miller' then
v_job:='Salesman';
v_deptno:=35;
v_comm:=v_sal*0.20;
end if;
update emp2
set job=v_job,deptno=v_deptno,sal=v_sal,comm=v_comm
where ename=v_ename;
v_result:=sql%rowcount;
dbms_output.put_line(v_result || ' row(s) updated.');
end;
--verificare
select ename,deptno,job,sal,comm
FROM emp2
where ename='Miller'
--2.Setati un flag pentru comenzi cand sunt mai putin de 5 zile intre data comenzii si data expedierii
desc ord
alter table ord add (ship_flag varchar2(25))
v_comm emp2.comm%type;
v_result number(2);
begin
select comm
into v_comm
from emp2
where deptno=v_deptno;
if v_deptno=10 then
v_comm:=5000;
elsif v_deptno=20 then
v_comm:=7500;
else
v_comm:=2000;
end if;
update emp2
set comm=v_comm
where deptno=v_deptno;
v_result:=sql%rowcount;
dbms_output.put_line(to_char(v_result)||' row(s) updated');
end;
--5.Pentru o anumita valoare data calculati o alta valoare
accept p_start prompt 'Dati o valoare numerica: '
declare
v_start number(12,2):=&p_start;
begin
if v_start > 100 then
v_start:=2*v_start;
elsif v_start>=50 then
v_start:=0.5*v_start;
else
v_start:=0.1*v_start;
end if;
dbms_output.put_line(v_start);
end;
v_hiredate ||
v_hiredate ||
end;
--alta varianta in care nu este nevoie sa se declare cursorul
begin
for emp_record in (select empno,ename from emp) loop
if emp_record.empno=7839 then
dbms_output.put_line(emp_record.empno||' - '|| emp_record.ename);
end if;
end loop;
end;
--3.Sa se preia angajatii pe baza numarului departamentului si a numelui meseriei
declare
cursor c_deptno_job
(v_deptno number,v_job varchar2)is
select empno,ename
from emp
where deptno=v_deptno and job=v_job;
emp_record c_deptno_job%rowtype;
begin
open c_deptno_job(30,'Salesman');
loop
fetch c_deptno_job into emp_record;
exit when c_deptno_job%notfound;
dbms_output.put_line(emp_record.empno||' - '||emp_record.ename);
end loop;
close c_deptno_job;
end;
--4.Sa se determine marca si numele angajatilor in functie de nr departamentului
declare
cursor c_empno_ename
(v_deptno number)is
select empno,ename
from emp
where deptno=v_deptno;
begin
for emp_record in c_empno_ename(30)
loop
dbms_output.put_line(emp_record.empno|| ' - ' ||emp_record.ename);
end loop;
end;
--varianta clasica, fara for
declare
cursor c_empno_ename
(v_deptno number)is
select empno,ename
from emp
where deptno=v_deptno;
emp_record c_empno_ename%rowtype;
begin
open c_empno_ename(30);
loop
fetch c_empno_ename into emp_record;
exit when c_empno_ename%notfound;
dbms_output.put_line(emp_record.empno||' - ' ||emp_record.ename);
end loop;
close c_empno_ename;
end;
--5.Sa se afle numele angajatilor pe baza marcii si job-ului acestora.
--se folosesc acum doi parametri in definirea cursorului
declare
cursor cursor_emp_details
(v_empno number,v_job char)is
select empno,ename,job
from emp
where empno=v_empno and job=v_job;
begin
for emp_record in cursor_emp_details(7792,'Manager')
loop
dbms_output.put_line(emp_record.empno||' ' ||emp_record.ename||' '||emp_record.job);
end loop;
end;
--varianta clasica, fara for
declare
cursor cursor_emp_details
(v_empno number,v_job char)is
select empno,ename,job
from emp
where empno=v_empno and job=v_job;
emp_record cursor_emp_details%rowtype;
begin
open cursor_emp_details(7792,'Manager');
loop
fetch cursor_emp_details into emp_record;
exit when cursor_emp_details%notfound;
dbms_output.put_line(emp_record.empno||' ' ||emp_record.ename||' '||emp_record.job);
end loop;
end;
--6.Exemplu de utilizare a cursoarelor pentru actualizare
--Se actualizeaza salariile angajatilor care au salariul sub 2000 dolari pe luna
--uneori se doreste blocarea liniilor inainte de o operatiune de stergere sau de actualizare, iar pentru acest lucru
--se foloseste clauza for update in cadrul cursorului, care trebuie asezata ca ultima clauza, chiar si dupa order by, daca
exista
--nowait returneaza o eroare daca liniile sunt blocate de o alta sesiune
--mai intai sunt blocate liniile ce se doresc a fi actualizate pentru clauza for update, iar apoi pentru actualizare este
--utilizata clauza where current of (este actualizata fiecare linie procesata de fetch)
declare
cursor c_update_sal is
select empno,sal
from emp2
where sal<=2000 for update nowait;
emp_record c_update_sal%rowtype;
v_result number(2);
begin
open c_update_sal;
loop
fetch c_update_sal into emp_record;
exit when c_update_sal%notfound;
update c_update_sal
set sal=emp_record.sal*1.1;
where current of c_update_sal;
end loop;
v_result:=sql%rowcount;
dbms_output.put_line(v_result ||' row(s) updated.');
close c_update_sal;
commit;
end;
--varianta cu for
declare
cursor c_update_sal is
select empno,sal
from emp2
where sal < 2000 for update nowait;
emp_record c_update_sal%rowtype;
v_result number(2);
begin
for emp_record in c_update_sal
loop
update emp2
set sal=emp_record.sal*1.1
where current of c_update_sal;
end loop;
v_result:=sql%rowcount;
dbms_output.put_line(v_result ||' row(s) updated.');
commit;
end;
--7.Sa se creeze un raport pe mai multe nivele, in care sa se afiseze angajatii pe departamente
declare
cursor c_dept is
select deptno,dname
from dept
order by dname;
cursor c_emp
(v_deptno number)is
select ename
from emp
where deptno=v_deptno
order by ename;
v_dept c_dept%rowtype;
v_emp c_emp%rowtype;
begin
open c_dept;
loop
fetch c_dept into v_dept;
exit when c_dept%notfound;
dbms_output.put_line(v_dept.dname||'--');
open c_emp (v_dept.deptno);
loop
fetch c_emp into v_emp;
exit when c_emp%notfound;
dbms_output.put_line(v_emp.ename);
end loop;
close c_emp;
end loop;
close c_dept;
end;
--8.Construiti un cursor care sa afiseze marca si salariul angajatilor, dand cate o steluta la fiecare 100 de dolari din
salariu.
accept p_empno prompt 'Dati marca angajatului: '
declare
v_empno emp.empno%type:=&p_empno;
v_stars emp.stars%type:=null;
cursor c1 is
select empno,nvl(round(sal/100),0)sal
from emp
where empno=v_empno
for update nowait;
begin
for emp_record in c1 loop
begin
for i in 1..c1.sal loop
v_stars:=v_stars||'*';
end loop;
update emp
set stars=v_stars
where current of c1;
v_stars:=null;
end;
end loop;
commit;
end;
--1.Scrieti un bloc PL/SQL care sa selecteze numele angajatului cu o valoare data a salariului:
--a.Daca salariul introdus returneaza mai mult de un rand, tratati exceptia cu o exceptie tratata asemanatoare si
introduceti
--in tabelul messages, mesajul "Mai mult de un angajat cu salariul < salariu >".
--b.Daca salariul introdus nu returneaza nici un rand, tratati exceptia cu o exceptie tratata asemanatoare si introduceti
--in tabloul messages, mesajul "Nu este nici un angajat cu salariul < salariu >".
--c.Daca salariul introdus returneaza numai un rand, introduceti in tabloul messages numele angajatului si valoarea
salariului
--d.Tratati orice alta exceptie cu o exceptie tratata asemanatoare si introduceti in tabloul messages, mesajul
--"S-au mai produs alte erori".
--e.Testati blocul pentru mai multe cazuri (situatii).
accept p_sal prompt 'Introduceti valoarea salariului: '
declare
v_ename emp.ename%type;
v_sal emp.sal%type:=&p_sal;
begin
delete from messages;
select ename
into v_ename
from emp
where sal=v_sal;
insert into messages(results)values(v_ename || ' ' || v_sal);
exception
when too_many_rows then
insert into messages(results)values('Mai mult de un angajat cu salariul '||to_char(v_sal));
when no_data_found then
insert into messages(results)values('Nu este nici un angajat cu salariul '||to_char(v_sal));
when others then
insert into messages(results)values('S-au mai produs alte erori.');
end;
--2.Creati un bloc PL/SQL care sa actualizeze locatia pentru un departament existent.
--a.Folositi o variabila citita de la tastatura pentru nr departamentului
--b.Introduceti de la tastatura locatia departamentului
--c.Tratati cazul in care departamentul introdus nu exista in tabela
--d.Testati blocul PL/SQL
--e.Afisati nr departamentului, numele departamentului si locatia pentru departamentul actualizat sau mesajul de
eroare
accept p_deptno prompt 'Introduceti numarul departamentului: '
accept p_loc prompt 'Introduceti locatia departamentului: '
declare
e_invalid_dept exception;
v_deptno dept.deptno%type:=&p_deptno;
v_loc dept.loc%type:='&p_loc';
begin
update dept
set loc=v_loc
where deptno=v_deptno;
if sql%notfound then
raise e_invalid_dept;
else
dbms_output.put_line(v_deptno|| ' ' ||v_loc);
rollback;
end if;
exception
when e_invalid_dept then
dbms_output.put_line('Departamentul '||to_char(v_deptno)||' nu exista !');
end;
--3.Scrieti un bloc PL/SQL care tipareste numele angajatilor care au cu 100$ mai mult sau mai putin la salar fata de
valoarea
--salariului introdus:
--a.Daca nu este nici un angajat al carui salar sa se incadreze in aceasta valoare, tipariti un mesaj utilizatorului
--indicandu-i acest lucru. Folositi o exceptie pentru acest caz.
--b.Daca sunt unul sau mai multi angajati ale caror salarii se incadreaza in aceasta valoare, mesajul va trebui sa indice
--cati angajati au un salar ce se incadreaza in valoarea respectiva.
--c.Tratati orice alta exceptie cu o exceptie asemanatoare, mesajul va trebui sa indice daca au mai aparut si alte erori.
accept p_sal prompt 'Introduceti valoarea salariului: '
declare
v_sal emp.sal%type:=&p_sal;
v_sub_sal emp.sal%type:=v_sal-100;
v_peste_sal emp.sal%type:=v_sal+100;
v_ename emp.ename%type;
v_nr number(1);
v_current_sal emp.sal%type;
v_last_sal emp.sal%type;
e_no_emp exception;
e_more_than_one_emp exception;
e_one_emp exception;
cursor c1 is
select ename,sal
from emp
where sal is not null
order by sal desc;
begin
select count(*)
into v_nr
from emp
where sal between v_sub_sal and v_peste_sal;
if v_nr=0 then
raise e_no_emp;
elsif v_nr=1 then
raise e_one_emp;
elsif v_nr>1 then
raise e_more_than_one_emp;
end if;
exception
when e_no_emp then
declare
v_prodid item.prodid%type:=100860;
e_products_invalid exception;
--pragma exception_init(e_products_invalid,-2292);
error_message varchar2(100);
begin
delete from item
where prodid=v_prodid;
raise e_products_invalid;
exception
when e_products_invalid then
error_message:='Produsul cu id-ul '||v_prodid||' nu exista in baza de date !';
dbms_output.put_line(error_message);
end;
select * from product
select * from item
rollback;
query_emp(7654,v_ename,v_sal,v_comm);
dbms_output.put_line('Name: ' || v_ename);
dbms_output.put_line('Salary: ' || v_sal);
dbms_output.put_line('Commission: ' || v_comm);
end;
--sau
declare
v_empno emp.empno%type:=7654;
v_ename emp.ename%type;
v_sal emp.sal%type;
v_comm emp.comm%type;
begin
query_emp(v_empno,v_ename,v_sal,v_comm);
dbms_output.put_line('Marca: ' || v_empno);
dbms_output.put_line('Name: ' || v_ename);
dbms_output.put_line('Salary: ' || v_sal);
dbms_output.put_line('Commission: ' || v_comm);
end;
--3.Procedura care afiseaza formatul unui nr de telefon
create or replace procedure format_phone
(v_phone_no in out varchar2)
is
begin
v_phone_no:='(' || substr(v_phone_no,1,3) || ')' || substr(v_phone_no,4,3) || '-' || substr(v_phone_no,7);
end format_phone;
--executia
declare
a_phone_no varchar2(15):=589858475664334;
begin
dbms_output.put_line('Telefon number: ' || a_phone_no);
end;
--4.Procedura pentru adaugarea unui departament pe baza unei secvente
--se creeaza mai intai secventa
create sequence dept_deptno
increment by 1
start with 41
maxvalue 100
nocache
nocycle
-create or replace procedure add_dept
(v_dname in dept.dname%type default 'unknown',
v_loc in dept.loc%type default 'unknown')
is
begin
insert into dept values(dept_deptno.nextval,v_dname,v_loc);
end add_dept;
--executia
begin
--add_dept;
--add_dept('training','New York');
--add_dept(v_loc=>'Dallas',v_dname=>'Education');
add_dept(v_loc=>'Boston');
end;
--verificare
select *
from dept;
rollback;
select *
from dept;
--5.Invocarea unei proceduri (cresterea salariului pe baza unei proceduri deja existente)
create or replace procedure process_emps
is
cursor emp_cursor is
select empno
from emp;
begin
for emp_record in emp_cursor loop
raise_salary(emp_record.empno);
end loop;
end process_emps;
--executie
begin
raise_salary(7369);
end;
--verificare
select sal
from emp
where empno=7369;
rollback;
select sal
from emp
where empno=7369;
--Exercitii propuse in cartea de laborator
--1.Creati si apelati procedura add_prod astfel:
--a.add_prod va insera un produs nou in tabela product
--b.apelati procedura si apoi interogati tabela pentru a vedea rezultatele
--c.apelati procedura cu prodid avand valoarea 100860
create or replace procedure add_prod
(v_prodid in product.prodid%type,
v_descrip in product.descrip%type)
is
e_exist exception;
pragma exception_init(e_exist,-0001);
begin
insert into product values(v_prodid,v_descrip);
exception
when e_exist then
dbms_output.put_line('Produsul cu codul ' ||v_prodid||' exista in baza de date! ');
dbms_output.put_line(sqlerrm);
end;
/
--begin
--add_prod(100860,'Ace Tennis Racket I');
--end;
/
--sau
begin
add_prod(200011,'Minge fotbal World Cup 2014');
end;
-select * from product
where prodid=200011;
rollback;
select * from product
where prodid=200011;
--varianta cu secventa
create sequence product_prodid
increment by 1
start with 200400
maxvalue 200500
nocache
nocycle
-create or replace procedure add_prod1
(v_descrip in product.descrip%type default 'unknown')
is
begin
insert into product values(product_prodid.nextval,v_descrip);
end add_prod1;
/
begin
add_prodd1;
--add_prodd1('Armani Jeans');
--add_prodd1('Valentino Shoes');
end;
/
select * from product;
rollback;
select * from product;
--2.Creati procedura upd_prod astfel:
--a.upd_prod va actualiza descrierea unui produs dat ca parametru. Includeti cod si pentru tratarea exceptiilor
--b.Apelati procedura cu diversi parametri si apoi interogati tabela pentru a vedea rezultatele. Testati si cazurile
--corespunzatoare pentru tratarea exceptiilor
end;
-select * from item;
rollback;
select * from item;
--4.Creati procedura query_emp astfel:
--a.query_emp va extrage salariul si meseria pentru un angajat dat.
--b.Testati procedura pentru angajatul cu nr 7839
--c.Testati procedura pentru angajatul cu nr 98989
create or replace procedure query_emp
(v_empno in emp.empno%type,
v_sal out emp.sal%type,
v_job out emp.job%type)
is
begin
select sal,job
into v_sal,v_job
from emp
where empno=v_empno;
dbms_output.put_line('Angajatul cu marca '||v_empno||' are salariul '||v_sal||' si este '||v_job);
exception
when no_data_found then
dbms_output.put_line('Angajatul cu marca '||v_empno||' nu exista in baza de date!');
end;
--executia
declare
v_sal emp.sal%type;
v_job emp.job%type;
begin
query_emp(7839,v_sal,v_job);
dbms_output.put_line('Salary: '||v_sal);
dbms_output.put_line('Job: '||v_job);
query_emp(98989,v_sal,v_job);
dbms_output.put_line('Salary: '||v_sal);
dbms_output.put_line('Job: '||v_job);
end;
--Alte exercitii
--1.Scrieti o procedura stocata pentru calculul impozitului pt.salariu atunci cnd acesta este calculat pe baza transelor
de
--impozitare si nu ca procent fix dedus din salariu. Adaugati si salariul net ca diferenta dintre salariul brut si impozit.
CREATE OR REPLACE PROCEDURE calcul_impozit_salariu_net
(v_sal emp.sal%type)
IS
v_impozit number(10):=0;
v_salar_net number(10):=0;
BEGIN
delete from messages;
IF v_sal between 3001 and 9999 THEN
--o prima procedura care preia angajatii dintr-un departament dat ca parametru de intrare si de asemenea sa se mai
determine si nr
--de angajati care isi modifica salariul
--a doua procedura (cea de la punctul 2.a) care este apelata din prima si modifica salariile angajatilor din
departamentul dat ca parametru in
--prima procedura prin adunarea la salariul existent al angajatilor a inca 10% din valoarea departamentului acestora.
create or replace procedure preluare_angajati(
v_deptno in emp.deptno%type,
v_nr out number)
is
cursor c1 is
select empno
from emp
where deptno=v_deptno;
begin
for emp_record in c1 loop
modifica_salariu(emp_record.empno,v_deptno);
v_nr:=c1%rowcount;
end loop;
end preluare_angajati;
/
create or replace procedure modifica_salariu(
v_empno emp.empno%type,
v_deptno emp.sal%type)
is
begin
update emp
set sal=sal+v_deptno/10
where empno=v_empno;
end modifica_salariu;
--apelul
/
declare
v_nr number(3);
v_deptno emp.deptno%type:=10;
begin
preluare_angajati(v_deptno,v_nr);
dbms_output.put_line('Au fost modificati '||v_nr|| ' angajati in departamentul '||v_deptno);
end;
/
select ename,sal
from emp
where deptno=10;
/
rollback;
/
select ename,sal
from emp
where deptno=10;
--3.a)Sa se realizeze o procedura care calculeaza suma platilor pe fiecare client (se va folosi campul total din tabela
ord).
create or replace procedure suma_plati_per_client
(v_custid in customer.custid%type,
v_sum out ord.total%type)
is
cursor c1 is
select total
from ord
where custid=v_custid;
begin
v_sum:=0;
for c1_record in c1 loop
v_sum :=v_sum+c1_record.total;
end loop;
end;
/
declare
v_sum ord.total%type;
begin
suma_plati_per_client(100,v_sum);
dbms_output.put_line('Suma platilor pentru clientul cu marca 100 este: ' || v_sum);
end;
--3.b)Pentru un agent de vanzari dat sa se afiseze clientul care are cea mai mare suma a platilor facute catre clientii
acelui agent.
--Se cere: o procedura care primeste marca agentului de vanzari, trimitand clientii catre procedura de la
--punctul 3.a)(se folosesc campurile custid si repid - ce corespunde marcii agentului de vanzari, empno, din customer)
--care calculeaza suma platilor pe fiecare client si apoi foloseste aceasta suma
--pentru a vedea care este maximul si la ce client. In final procedura intoarce marca clientului si suma aferenta in apel.
--In apel vor fi afisate numele clientului si suma platilor aferente.
--Calculele pentru sumele platilor, respectiv maximul se vor face in bucla, cu cursori
create or replace procedure suma_plati_per_client
(v_custid customer.custid%type,
v_sum out ord.total%type)
is
cursor c1 is
select total
from ord
where custid=v_custid;
begin
v_sum:=0;
for ord_record in c1 loop
v_sum :=v_sum+ord_record.total;
end loop;
end;
/
create or replace procedure maxim_client
(v_repid customer.repid%type,
v_custid
out customer.custid%type,
begin
max_client(7844,v_custid,v_sum);
dbms_output.put_line('Agentul cu marca 7844 a vandut clientului cu marca '||v_custid||' produse in valoare de
'||v_sum);
end;
--4.a)Realizati o procedura care primeste codul ordinului de plata si intoarce suma de pe ordin (campul total din ord)
create or replace procedure get_total
(v_ordid
ord.ordid%type,
v_custid
out ord.custid%type,
v_total out ord.total%type)
is
begin
select total,custid
into v_total,v_custid
from ord
where ordid=v_ordid;
end;
/
declare
v_custid ord.custid%type;
v_total
ord.total%type;
begin
get_total(610,v_custid,v_total);
dbms_output.put_line('Ordinul de plata cu nr 610 apartine clientului '|| v_custid || ' si are valoarea de ' || v_total);
end;
--4.b)Pentru un produs dat sa se afle ordinul de plata cel mai mic din punct de vedere valoric care il contine, valoarea
acestuia si clientul
--aferent. Se cere o procedura care primeste codul produsului (campul prodid din item) si trimite codul ordinelor de
plata (campul ordid din item)
--care il contin spre procedura de la punctul 4.a) care intoarce totalul de pe respectivul ordin (total din ord).
--Pe baza acestei valori se determina ordinul de plata cu valoarea minima si clientul aferent (campul custid din ord)
--In apel veti afisa codul ordinului de plata (ordid din ord) cu valoarea cea mai mica, valoarea in sine si clientul care a
platit
--cu respectivul ordin de plata.
create or replace procedure get_total
(v_ordid
ord.ordid%type,
v_custid
out ord.custid%type,
v_total out ord.total%type)
is
begin
select total,custid
into v_total,v_custid
from ord
where ordid=v_ordid;
end;
/
create or replace procedure min_order
(v_prodid
item.prodid%type,
declare
v_total
ord.total%type;
begin
suma_plati_per_client(100,v_total);
dbms_output.put_line('Clientul cu nr 100 are plati in valoare de '||v_total);
end;
--5.b)Sa se afiseze numele agentilor de vanzari, comisionul vechi si comisionul nou calculat ca fiind 5% din totalul
vanzarilor fiecaruia.
--Se cere o procedura care calculeaza suma platilor clientilor fiecarui agent de vanzari, pe care-i trimite (campul custid
din customer) spre
--procedura de la punctul 5.a)care calculeaza suma pe fiecare client. Apoi calculeaza suma pe toti clientii agentului pe
care o trimite
--in final spre apel unde se calculeaza noul comision.
create or replace procedure suma_plati_per_client
(v_custid ord.custid%type,
v_total out ord.total%type)
is
cursor c1 is
select total
from ord
where custid=v_custid;
begin
v_total:=0;
for c1_record in c1 loop
v_total:=v_total+c1_record.total;
end loop;
end;
/
create or replace procedure total_plati_clienti_per_agent
(v_repid
customer.repid%type,
v_total out ord.total%type)
is
cursor c1 is
select custid
from customer
where repid=v_repid;
v_plati ord.total%type;
begin
v_total:=0;
for c1_record in c1 loop
suma_plati_per_client(c1_record.custid,v_plati);
v_total:=v_total+v_plati;
end loop;
end;
/
declare
cursor c1 is
select empno,ename,comm
from emp
--b.pentru restul departamentelor se vor afisa numele angajatilor si salariile modificate prin adaugarea ultimelor 2
cifre ale marcii
--dar nu mai putin de 20
--Se cer urmatoarele doua proceduri:
--a.o procedura care primeste numele departamentului, determina angajatii, calculeaza media salariala, pe care o
intoarce in apel unde va fi
--afisat un mesaj semnificativ
--b.o procedura care primeste numele departamentului, marca salariatilor si intoarce spre apel valoarea cu care se
modifica salariul. In apel
--se vor afisa numele, marca angajatilor, salariul vechi si noul salariu.
--calculele pentru media salariilor se vor face in bucla, folosind un cursor
create or replace procedure avg_dept
(v_dname
dept.dname%type,
v_nr_angajati out number,
v_medie_salariala
out number)
is
cursor c1 is
select sal
from emp e inner join dept d
on e.deptno=d.deptno
and dname=v_dname;
v_sum emp.sal%type:=0;
begin
for c1_record in c1 loop
v_sum:=v_sum+c1_record.sal;
v_nr_angajati:=c1%rowcount;
end loop;
v_medie_salariala:= v_sum/v_nr_angajati;
end;
/
create or replace procedure modifica_salariu
(v_empno
emp.empno%type,
v_salariu_modificat out number)
is
begin
v_salariu_modificat:= mod(v_empno,100);
if v_salariu_modificat <20 then
v_salariu_modificat:=20;
end if;
end;
/
accept p_dname prompt 'Dati numele departamentului: '
declare
v_dname dept.dname%type:='&p_dname';
v_medie_salariala
number(8,2);
v_nr_angajati number(3);
v_mod number(3);
new_sal
emp.sal%type;
cursor c1 is
select empno,ename,sal
--c.Testati procedura new_emp prin adaugarea unui nou angajat numit Harris in departamentul 99. Lasati toti ceilalti
parametri impliciti.
--Care este rezultatul?
--d.Testati procedura new_emp prin adaugarea unui nou angajat numit Harris in departamentul 30. Lasati toti ceilalti
parametri impliciti.
--Care este rezultatul?
create or replace function valid_deptno
(v_deptno in dept.deptno%type)
return boolean
is
e_dept boolean;
v_number number;
begin
select count(*)
into v_number
from dept
where deptno=v_deptno;
if v_number=0 then
dbms_output.put_line('Departamentul cu marca '||v_deptno||' nu exista !');
e_dept:=false;
else
e_dept:=true;
end if;
return e_dept;
end valid_deptno;
--alta varianta a functiei
/*create or replace function valid_deptno
(v_deptno in dept.deptno%type)
return boolean
is
v_number number;
e_dept boolean;
begin
select count(*)
into v_number
from dept
where deptno=v_deptno;
if v_number=0 then
dbms_output.put_line('Departamentul cu marca '||v_deptno||' nu exista !');
return false;
else
return true;
end if;
return e_dept;
end valid_deptno; */
-create sequence seq_empno
minvalue 8000
start with 8000
increment by 1
end;
/
select * from emp
where ename='Harris'
/
delete from emp
where ename='Harris'
/
--Alte exercitii
--4.Returnati salariul unui angajat pe baza id-ului sau
create or replace function get_sal
(v_empno in emp.empno%type)
return number
is
v_sal emp.sal%type:=0;
begin
select sal
into v_sal
from emp
where empno=v_empno;
return v_sal;
exception
when no_data_found then
return null;
end get_sal;
--invocarea functiei
declare
v_sal emp.sal%type;
begin
v_sal := get_sal(7839);
dbms_output.put_line('Angajatul cu marca 7839 are salariul '|| get_sal(7839));
end;
--alta varianta de apel
accept p_empno prompt "Dati marca angajatului: "
begin
dbms_output.put_line('Angajatul cu marca '||&p_empno ||' are salariul: '||get_sal(&p_empno));
end;
--5.Calculul impozitului, cu ajutorul unei functii, pt.salariu atunci cnd acesta este
--calculat pe baza transelor de impozitare si nu ca procent fix
--dedus din salariu.
CREATE OR REPLACE FUNCTION calculeaza_impozit
(v_sal emp.sal%type)
RETURN NUMBER IS
impozit NUMBER := 0;
BEGIN
IF v_sal between 3001 and 9999 THEN
impozit := (v_sal * 0.6);
ELSIF v_sal between 2001 and 3000 THEN
v_sal_nou:=sal_datang(c1_record.empno);
update emp
set sal=sal+v_sal_nou
where empno=c1_record.empno;
end loop;
end;
/
select ename,hiredate,sal
from emp
/
rollback
/
select ename,hiredate,sal
from emp
/