Documente Academic
Documente Profesional
Documente Cultură
Subprograme PL/SQL
1. PROCEDURI
prin apel direct cu EXECUTE nume_proc sau EXEC nume_proc sau CALL nume_proc;
Where codprodus=codp;
if SQL%notfound then
raise produs_invalid;
end if;
dbms_output.put_line('S-au modificat '||SQL%rowcount||' inregistrari');
exception
when produs_invalid then dbms_output.put_line('Nu exista produsul cu codul '||codp);
END;
/
-- apelul direct:
call mareste_stoc(111, 10);
--verificare executie
select * from produse where codprodus =111;
Stergerea unei proceduri se realizeaza prin comanda:
DROP PROCEDURE nume_procedura;
Vizualizarea procedurilor in dictionarul metadatelor se realizeaza prin:
Select object_name
From user_objects
Where object_type='PROCEDURE';
Iar pentru a vizualiza corpul procedurii:
Select text
From user_source
Where name='NUME_PROC' and type='PROCEDURE';
Exemplu:
Select text
From user_source
Where name='MARESTE_STOC' and type='PROCEDURE';
2. FUNCII:
Sintaxa pentru crearea unei functii:
CREATE [OR REPLACE] FUNCTION nume_functie
[(param1 [IN] TIP1,
Param2[IN] TIP2, ....) ]
RETURN TIP_DATA
-- tipul variabilelor este precizat fara dimensiune (ex: NUMBER sau VARCHAR2)
IS|AS
-- zona de declarare a variabilelor utilizate in subprogram
-- nu se utilizeaza DECLARE
BEGIN
---RETURN VALOARE;
[EXCEPTION]
-----END [NUME_FUNCTIE];
Pentru vizualizarea tipului returnat se utilizeaza:
DESCRIBE nume_functie;
Pentru a sterge functia:
DROP FUNCTION nume_functie;
Exemplu:
-- afiseaza denumirea unui produs al carui cod este precizat drept parametru:
CREATE OR REPLACE FUNCTION afiseaza_denumire
(p_codp produse.codprodus%type)
RETURN varchar2
IS
v_denp produse.denprodus%type;
BEGIN
select denprodus into v_denp
from produse
where codprodus=p_codp;
return v_denp;
EXCEPTION
when no_data_found then
dbms_output.put_line('Nu exista produsul cu codul specificat!');
when too_many_rows then
dbms_output.put_line('Prea multe produse cu acest cod!');
END;
/
show errors;
-- vizualizarea tipului returnat:
describe afiseaza_denumire;
4
-- apelul functiei:
declare
v_nume varchar2(20);
begin
v_nume:= afiseaza_denumire(111);
dbms_output.put_line(v_nume);
end;
Utilizarea functiilor PL/SQL in expresii SQL
CREATE OR REPLACE FUNCTION tva (valoare IN NUMBER)
RETURN NUMBER
IS
BEGIN
RETURN (valoare*0.19);
END;
/
--apelul funciei
SELECT codprodus, cant * pret as valoare, tva (cant * pret) as tva
FROM rindcom;
Observatii!
Functiile utilizate in expresii SQL trebuie sa accepte doar parametrii de tip IN si sa returneze
numai tipuri de date specifice PL/SQL.
Functiile nu trebuie sa contina comenzi DML (update, delete, insert) sau comenzi DDL si nici
comenzi pentru controlul tranzactiilor (commit, rollback) si nici nu trebuie sa apeleze alte
subprograme care sa incalce aceste restrictii.
Functiile apelate in cadrul expresiilor SQL pot fi continute in pachete.
Stergerea unei functii se realizeaza utilizand comanda:
DROP FUNCTION nume_functie;
Vizualizarea functiilor in dictionarul metadatelor se realizeaza prin:
Select object_name
From user_objects
Where object_type='FUNCTION';
Iar pentru a vizualiza corpul functiei:
Select text
From user_source
Where name='NUME_FUNCTIE' and type=' FUNCTION '
ORDER BY line;
Exemplu:
Select text
From user_source
Where name='TAX' and type='FUNCTION'
ORDER BY line;
5
Pachete de subprograme
Grupeaza variabile, subprograme, tipuri de date PL/SQL care sunt corelate logic.
Sunt formate din 2 parti:
- specificatia pachetului zona publica
- corpul pachetului zona privata
Specificatia pachetului:
CREATE [OR REPLACE] PACKAGE nume_pachet
IS|AS
--declaratii de variabile si tipuri publice, sunt initializate cu NULL implicit
--specificatii ale subprogramelor publice
END [nume_pachet];
Corpul pachetului:
CREATE [OR REPLACE] PACKAGE BODY nume_pachet
IS|AS
--declaratii de variabile si tipuri private
--definitii ale subprogramelor publice si private
[BEGIN
-- Este optional si se executa o singura data la primul apel si la incarcarea pachetului in memorie
END [nume_pachet];
Observatie: In cadrul pachetelor pentru a utiliza o functie/procedura in cadrul unui subprogram,
aceasta trebuie declarata inainte (principiul forward declarations);
In zona de specificatii a pachetului se pot declara:
proceduri;
funcii;
variabile;
cursoare;
excepii.
Corpul pachetului defineste complet procedurile, functiile si cursoarele.
Supraincarcarea subprogramelor
Se poate realiza numai pentru functii/proceduri din cadrul pachetelor, nu si pentru subprograme
singulare (stocate direct in baza de date);
Nu se pot supraincarca 2 subprograme care au paramentrii de tipuri asemanatoare (ex:
NUMBER si DECIMAL sau VARCHAR2 si VARCHAR);
Exemplu:
CREATE OR REPLACE PACKAGE actualizare_produse IS
procedure adauga_produs
(p_codp produse.codprodus%type,
p_denp produse.denprodus%type,
p_um produse.um%type,
6
p_stoc produse.stoc%type);
procedure modifica_produs
(p_codp produse.codprodus%type,
p_denp produse.denprodus%type,
p_um produse.um%type,
p_stoc produse.stoc%type);
procedure modifica_produs
(p_codp produse.codprodus%type,
p_stoc produse.stoc%type);
procedure sterge_produs
(p_codp produse.codprodus%type);
function exista_cod
(p_codp produse.codprodus%type)
return boolean;
exceptie exception;
END;
/
CREATE OR REPLACE PACKAGE BODY actualizare_produs IS
procedure adauga_produs
(p_codp produse.codprodus%type,
p_denp produse.denprodus%type,
p_um produse.um%type,
p_stoc produse.stoc%type)
is
begin
if exista_cod(p_codp) then
raise exceptie;
else
insert into produse values (p_codp, p_denp, p_um, p_stoc);
end if;
exception
when exceptie then
dbms_output.put_line('Produs existent!');
end;
procedure modifica_produs
(p_codp produse.codprodus%type,
p_denp produse.denprodus%type,
p_um produse.um%type,
p_stoc produse.stoc%type)
is
begin
if exista_cod(p_codp) then
7
update produse
set denprodus=p_denp, um=p_um, stoc=p_stoc
where codprodus=p_codp;
else
raise exceptie;
end if;
exception
when exceptie then
dbms_output.put_line('Produsul cu aceast cod nu exista!');
end;
procedure modifica_produs
(p_codp produse.codprodus%type,
p_stoc produse.stoc%type)
is
begin
if exista_cod(p_codp) then
update produse
set stoc=p_stoc
where codprodus=p_codp;
else
raise exceptie;
end if;
exception
when exceptie then
dbms_output.put_line('Produsul cu aceast cod nu exista!');
end;
procedure sterge_produs
(p_codp produse.codprodus%type)
is
begin
if exista_cod(p_codp) then
delete from produse
where codprodus=p_codp;
dbms_output.put_line('Produsul cu codul '||p_codprodus||' a fost sters!');
else
raise exceptie;
end if;
exception
when exceptie then
dbms_output.put_line('Produsul cu aceast cod nu exista!');
end;
function exista_cod
(p_codp produse.codprodus%type)
return boolean
is
v_unu number;
begin
8
BEGIN
dbms_output.put_line('triggerul s-a executat');
END;
/
Triggeri la nivel de rand FOR EACH ROW
In triggerul la nivel de rnd se poate accesa rndul curent procesat folosind doua pseudo-records (
:old, :new). Tipul lor este:
nume_tabela_pe_care_actioneaza_triggerul%ROWTYPE
Valorile pentru :old si :new
Operatie
Valoare pt Old
Valoare pt New
INSERT
NULL
valoarea noua, inserata
UPDATE
valoare veche, anterioara lui valoare noua, modificata
update
DELETE
valoare veche, anterioara lui NULL
delete
(:OLD) nu este definit pentru INSERT i (:NEW) nu e definit pentru DELETE
Dei sintactic sunt tratate ca tip de dat record, n realitate ele nu sunt i operaiile de atribuire
directa var_record:=:old ce sunt valide pentru record nu sunt valide pentru (:new) i (:old). Din
acest motiv trebuie precizate exact campurile din pseudo-record :old.camp sau :new.camp.
Exemple:
--Se creeaz un trigger care asigur unicitatea codului produsului folosind valorile generate de o
secven
CREATE SEQUENCE produse_secv
START WITH 1
INCREMENT BY 1
MAXVALUE 100
NOCYCLE;
CREATE OR REPLACE TRIGGER generare_codprodus
BEFORE INSERT ON produse
FOR EACH ROW
BEGIN
SELECT produse_secv.nextval INTO :new.codprodus FROM dual;
END;
/
show errors;
--Trigger care sa actualizeze cod client si in COMENZI cand el e modificat in FIRME.
CREATE OR REPLACE TRIGGER inlocuieste_cod
AFTER UPDATE OF codfirma ON firme
FOR EACH ROW
BEGIN
update comenzi
set codfirma = :new.codfirma
11
12