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;

Inapoi la cuprins.

BogSoft 1999