Sunteți pe pagina 1din 12

Facultatea de Cibernetic, Statistic i Informatic Economic

SGBD Oracle, an II, IDD seminar

Subprograme PL/SQL

Blocuri PL/SQL care au nume


Pot fi proceduri /functii
Se pot stoca la nivel de Oracle Server (proceduri/functii stocate) sau de aplicatie (Developer
Suite)
Se pot grupa in pachete de programe (PACKAGE)
Variabilele declarate in zona declarativa a procedurii se numesc parametri formali (formal
parameters). Pentru acestia se pot specifica valori implicite (DEFAULT)
Variabilele utilizate in apelul procedurii/functiei se numesc parametri actuali (actual
parameters)
Cnd procedura/functia e apelata, variabilele din procedura sunt incarcate cu valorile
variabilelor definite in zona declarativa a blocului anonim
In corpul procedurilor/functiilor nu se pot utiliza variabile globale sau de substitutie, acestea
vor fi transmise in subprograme cu ajutorul parametrilor
Pentru afisarea erorilor aparute la compilare se utilizeaza SHOW ERRORS

1. PROCEDURI

Parametrii utilizati in procedura (parametri formali) pot fi de tip:


IN (valoarea parametrului actual este transferata in variabila definita in procedura.
Aceasta variabila este considerata read-only). Cnd procedura se ncheie, controlul
revine mediului apelant. Parametrul actual nu se modifica. Este modul implicit.
OUT (valoarea parametrului formal este transferata in parametrul actual cnd
procedura se incheie)
IN OUT (valorile sunt transferate de la un tip de variabil la cellalt (la lansarea n
execuie/terminarea procedurii))
un parametru IN poate apare numai n partea dreapta a (:=)
un parametru OUT poate apare numai n partea stnga a (:=)
un parametru IN OUT poate apare n ambele pri ale (:=)

Sintaxa pentru crearea unei proceduri:


CREATE [OR REPLACE] PROCEDURE NUME_PROC
[(param1 [IN|OUT|IN OUT] TIP1,
Param2[IN|OUT|IN OUT] TIP2, ....) ]
-- 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
---[EXCEPTION]
-----END [NUME_PROC];
Pentru a sterge procedura:
DROP PROCEDURE NUME_PROC;
1

Facultatea de Cibernetic, Statistic i Informatic Economic


SGBD Oracle, an II, IDD seminar

Apelul unei proceduri se poate realiza in urmatoarele moduri:

prin nume dintr-un bloc PL/SQL anonim sau un alt subprogram;

prin apel direct cu EXECUTE nume_proc sau EXEC nume_proc sau CALL nume_proc;

din alt mediu Oracle (Oracle Developer Suite)


Exemple:
-- adauga o inregistrare noua in tabela Produse
SET SERVEROUTPUT ON
-- crearea procedurii:
CREATE OR REPLACE 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
insert into produse values (p_codp, p_denp, p_um, p_stoc);
exception
when dup_val_on_index then
dbms_output.put_line('Produs existent!');
END;
/
SHOW ERRORS
-- apelul procedurii prin bloc PL/SQL anonim:
begin
adauga_produs(100, 'cafea', 11, 10);
end;
/
-- apelul direct:
call adauga_produs(100, 'cafea', 11, 10);
-- mareste stocul unui produs specificat cu un procent dat. Daca produsul nu exista, se va
invoca o exceptie
SET SERVEROUTPUT ON
-- crearea procedurii:
CREATE or REPLACE PROCEDURE mareste_stoc
(codp IN produse.codprodus%type, procent IN number)
IS
v_stoc produse.stoc%type;
produs_invalid EXCEPTION;
BEGIN
Update produse
Set stoc=stoc*(1+procent/100)
2

Facultatea de Cibernetic, Statistic i Informatic Economic


SGBD Oracle, an II, IDD seminar

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';

Facultatea de Cibernetic, Statistic i Informatic Economic


SGBD Oracle, an II, IDD seminar

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

Facultatea de Cibernetic, Statistic i Informatic Economic


SGBD Oracle, an II, IDD seminar

-- 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

Facultatea de Cibernetic, Statistic i Informatic Economic


SGBD Oracle, an II, IDD seminar

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

Facultatea de Cibernetic, Statistic i Informatic Economic


SGBD Oracle, an II, IDD seminar

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

Facultatea de Cibernetic, Statistic i Informatic Economic


SGBD Oracle, an II, IDD seminar

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

Facultatea de Cibernetic, Statistic i Informatic Economic


SGBD Oracle, an II, IDD seminar

select 1 into v_unu


from produse
where codprodus=p_codprodus;
return true;
exception
when no_data_found then
return false;
end;
END;
/
Apelul procedurilor / functiilor din cadrul pachetului:
execute actualizare_produse.adauga_produs(449,'ceai', 12, 200);
select * from produse;
execute actualizare_produse.modifica_produs(449,'gogosi', 10, 200);
select * from produse;
execute actualizare_produse.modifica_produs(444, null);
select * from produse;
execute actualizare_produse.sterge_produs(449);
select * from produse;
Stergerea pachetului se realizeaza cu comenzile:
DROP PACKAGE nume_pachet;
DROP PACKAGE BODY nume_pachet;
Vizualizarea specificatiilor pachetelor in dictionarul metadatelor se realizeaza prin:
Select text
From user_source
Where name='NUME_PACHET' and type='PACKAGE'
Iar pentru a vizualiza corpul pachetului:
Select text
From user_source
Where name='NUME_PACHET' and type='PACKAGE BODY'
Exemplu:
Select text
From user_source
Where name='ACTUALIZARE_PRODUSE' and type='PACKAGE BODY';

Facultatea de Cibernetic, Statistic i Informatic Economic


SGBD Oracle, an II, IDD seminar

Triggeri pe baza de date


Sunt asociati cu o tabela, view, schema sau database
Sunt stocai n baza de date
Se execut cnd are loc un eveniment. Tipuri de evenimente:
operatii LMD pe o tabela (insert/ update/ delete)
operatii LMD pe o tabela virtuala (view) cu clauza INSTEAD OF
operatii LDD (Create, Alter, Drop) la nivel de database sau schema
evenimente la nivelul schemei sau bazei de date (shutdown sau logon/off)
Se folosesc pentru gestionarea restriciilor de integritate complexe, monitorizare, centralizarea

operatiilor. Nu se recomanda construirea in exces a triggerilor.


Pentru fiecare trigger se stabilete:
comanda care-l declaneaz (insert| update| delete) - Un trigger poate fi declanat de mai
multe comenzi
momentul de timp la care se declaneaz (before| after| instead of). Pentru view se
utilizeaza instead of, actiunile DML vor fi inlocuite de corpul triggerului si vor fi afectate
tabelele din care este construit view-ul.
nivelul (row| statement) - dac triggerul este la nivel de rnd se execut pentru fiecare
rnd afectat de comenzile: insert| update| delete. Daca nu este afectat nici un rand
triggerul nu se executa.
Din acest motiv, o tabel poate avea 12 tipuri de triggeri.
Dimensiunea unui trigger nu poate depasi 32 kb! Se poate include apelul unei proceduri in
corpul triggerului pentru a micsora dimensiunea acestuia.
Pentru a vedea erorile la compilare:
SHOW ERRORS TRIGGER nume_trigger;

Sintaxa de creare a unui trigger:

CREATE [OR REPLACE] TRIGGER nume_trigger


[BEFORE| AFTER| INSTEAD OF]
[INSERT| [OR] | UPDATE [OF coloana,]| [OR] | DELETE]
ON tabela
[FOR EACH ROW ]
[WHEN conditie]
corp_trigger
Corp_trigger poate fi un bloc PL/SQL (BeginEnd) sau un apel de procedura. Procedura poate
fi implementata in PL/SQL, C sau JAVA, iar apelul se realizeaza: CALL nume_proc (fara ; dupa
numele sau!!!)
Exemplu:
--Se creeaz un trigger care se declaneaz naintea fiecrei operaii de inserare n tabela
PRODUSE.
CREATE OR REPLACE TRIGGER produse_trig
BEFORE INSERT ON produse
10

Facultatea de Cibernetic, Statistic i Informatic Economic


SGBD Oracle, an II, IDD seminar

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

Facultatea de Cibernetic, Statistic i Informatic Economic


SGBD Oracle, an II, IDD seminar

where codfirma = :old.codfirma;


END;
/
cnd un trigger e creat, codul surs al triggerului este stocat n dicionarul de date in

user_triggers si se poate afisa:


SELECT trigger_type, trigger_name, triggering_event
FROM user_triggers
WHERE table_name='PRODUSE';
Gestiunea triggerilor:
Un trigger poate fi dezactivat

ALTER TRIGGER nume_trigger DISABLE|ENABLE;


Sau:
ALTER TABLE nume_tabela
DISABLE|ENABLE ALL TRIGGERS;
Exemplu:
ALTER TABLE produse
ENABLE ALL TRIGGERS;
Recompilarea unui trigger se realizeaza prin:

ALTER TRIGGER nume_trigger COMPILE;


Un trigger se terge cu:

DROP TRIGGER nume_trigger;


Observatie: In momentul stergerii unei tabele se sterg automat toti triggerii asociati acelei tabele.
PL/SQL stocheaz triggerii n forma compilat la fel ca procedurile, funciile i pachetele.
Aceasta permite triggerilor s fie apelai fr recompilare.

12

S-ar putea să vă placă și