CAPITOLUL 25
MAI MULTE DESPRE EXCEPTII
Am vazut deja cum exceptiile predefinite apar si cum le manuim. Acum
vom consolida aceste caracteristici uitandu-ne peste exceptiile
definite de utilizator si cum le putem asocia cu conditii interne.
CAND SUNT GENERATE EXCEPTIILE?
--printr-o conditie 'interna'
ex.:
Error- 1403 produce NO_DATA_FOUND
--prin generarea lor explicita
ex.:
RAISE my_exception;
Generarea exceptiilor
Exceptiile in general apar in doua moduri:
O eroare in ORACLE este asociata intern cu o exceptie.Aceasta exceptie
este "ridicata" automat ca un rezultat. De exemplu daca eroarea
ORA-0001 apare cand scriem in baza de date atunci exceptia
DUP_VAL_ON_INDEX este ridicata de PL/SQL.
O exceptie este generata implicit prin declaratia RAISE in cadrul unui
bloc.
Sintaxa :
RAISE exceptie_identificator;
Exceptia generata deliberat poate fi fie una definita de utlizator sau
o exceptie interna predefinita.
Este de dorit a genera o exceptie in conditii in care acea exceptie nu
ar aparea normal . De exemplu,sa presupunem ca o interogare
particulara are nevoie sa produca o eroare daca intoarce orice rand.
In mod normal numai cand mai mult de un rand este intors apare
exceptia TOO_MANY_ROWS:
BEGIN
SELECT 'anything' INTO PLVAR FROM emp
WHERE deptno = dept_number;
IF SQL%FOUND THEN
RAISE TOO_MANY_ROWS;
END_IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
Deasemenea observati cat timp 'NO_DATA_FOUND' este considerat normal
pentru aceasta interogare, declaratia SELECT poate sa primeasca un
sub_block in care exceptia are un identificator nul. Cealalta exceptie
TOO_MANY_ROWS va fi transmisa la blocul exterior.
EXCEPTII DEFINITE DE UTILIZATOR
--nume declarate de utilizatori
--RAISE cand trebuie sa termini procesarea
--permite definirea propriilor conditii
SINTAXA
identifier EXCEPTION
EXEMPLU
DECLARE
credit_exceeded EXCEPTION;
BEGIN
IF stock_ordered>credit_limit THEN
RAISE credit_exceeded;
END IF
Exceptii definite de utilizator
Exceptiile pot fi declarate impreuna cu alti identificatori la
inceputul unui bloc. Aceste exceptii user_defined pot fi generate
pentru situatii in care nici o procesare ulterioara a actiunilor
blocului nu trebuie sa apara. Exceptiile sunt declarate astfel :
identificator EXCEPTION;
Exceptiile user_defined ne permit sa definim identificatori
convenabili pentru propriile noastre conditii anormale. Cand apar
aceste conditii exceptiile pot fi generate a.i . controlul este trecut
la un identificator exceptie la sfarsitul blocului:
DECLARE
credit_exceeded EXCEPTION;
BEGIN
IF stock_ordered> credit_limit THEN
END IF;
EXCEPTION
WHEN credit_exceeded THEN ...
Declararea numelor pentru exceptii interne
Sa ne amintim ca PL/SQL are nume predefinite pentru cateva dintre
codurile exceptiilor interne dar nu pentru toate . Se pot prinde
exceptiile fara nume cu identificatorul WHEN OTHERS, dar se poate dori
declararea numelor propiilor exceptii pentru cateva coduri in mod
specific. PL/SQL furnizeaza o pragma numita EXCEPTION_INIT , care ne
permite specificarea unui nume de exceptie declarata, si numarul
erorii ORACLE de care este legat.
Sintaxa:
PRAGMA EXCEPTION_INIT( exception-identifier, number) ;
`Exception-identifier` trebuie sa fi fost deja declarat in partea de
declaratie a blocului.`Number` se refera la un numar de eroare tip
executie.
Exemplu:
DECLARE
fetch_failed EXCEPTION;
PRAGMA EXCEPTION_INIT (fetch_failed, -1002);
.
BEGIN
.
FETCH cursor1 INTO record1;
.
FETCH cursor1 INTO record1; /* Daca eroarea -1002 apare aici
atunci exceptia fetch_failed
este ridicata
automat */
EXCEPTION
WHEN fetch_failed THEN ...
Mai multe despre tratarea exceptiilor
Cind controlul este trecut partii EXCEPTION a unui bloc, numai o
exceptie va fi intr-o stare `generata`. Se poate totusi dori definirea
acelorasi actiuni pentru a minui mai mult de o exceptie:
WHEN invalid_number OR value_error THEN
INSERT INTO problems (...)
Identificatorul WHEN OTHERS prinde toate exceptiile neincluse deja.
Citeva instrumente ORACLE ca SQL*Forms au exceptiile lor predefinite
pe care le poti genera pentru a produce evenimente. WHEN OTHERS le va
prinde si pe acestea !
EXERCITII
1. Produceti un fisier SQL*Plus care accepta trei parametri (&1, &2,
&3) reprezentind numarul departamentului, numele departamentului si
locatia. Blocul PL/SQL din acest fisier trebuie sa produca o exceptie
USER-DEFINED daca nr. departamentului este 33 inregistrind un mesaj
adecvat in MESSAGES. Daca nu este 33 atunci numarul, numele si locatia
trebuie sa fie inregistrate ca un rind in tabelul NEWDEPT (care are
aceleasi coloane ca DEPT). Fisierul trebuie sa fie executabil in
urmatorul mod:
@FILENAME 50 TRAINING BRACKNELL
Daca aveti timp: 2. Produceti un bloc pentru a sterge toate rindurile
din tabelul PROJECTS. Definiti o exceptie care sa prinda eroarea
interna -2292 (Integrity violation), si includeti un identificator
care trimite un mesaj tabelului MESSAGES daca aceasta exceptie apare.
SOLUTII
1.
DECLARE
v_deptno NUMBER := &1;
dept_33 EXCEPTION;
BEGIN
IF v_deptno=33 THENRAISE dept_33;
END IF;
INSERT INTO newdept (deptno, dname, loc)
VALUES (&1, `&2`, `&3`);
EXCEPTION
WHWN dept_33 THEN
INSERT INTO messages (charcoll)
VALUES ('Attempt to create Department 33!');
END;
2.
DECLARE
integ_error EXCEPTION;
PRAGMA EXCEPTION_INIT (integ_error, -2292);
BEGIN
DELETE FROM projects;
EXCEPTION
WHEN integ_error THEN
INSERT INTO messages (charcol1)
VALUES (`Integrity Error`);
END;
BogSoft 1999