INTRODUCERE IN TRIGGER-E


CONTINUTUL ACESTUI UNIT :


Scopul acestui capitol este de a da un inteles a ceea ce sunt trigger-ele si a specifica rolul lor in cresterea functionalitatii forms-urilor.

Se vor trata :

CE ESTE UN TRIGGER ?



  1. Ce este un trigger ?

    Un trigger este o bucata de cod care se executa atunci cand un eveniment SQL*Forms Runform apare.Exista multe tipuri diferite de trigger-e,asa cum veti vedea in capitolele urmatoar,si multe cazuri de folosire a lor.

    Pentru o lista completa a tipurilor de trigger-e si cateva sugestii de folosire a lor se gaseste in Anexa B - Trriger-e pe scurt.

    O definitie completa a fiecarui tip de trigger se gaseste in SQL*Forms Designer's Reference.

  2. Utilizarea trigger-elor.

    Trigger-ele sunt folosite pentru a suplini(sau,in anumite cazuri,a intercepta) evolutia normala a SQLForms(Runform).Trigger-ele reprezinta principala optiune in modificarea modului in care SQL*Forms trateaza un eveniment particular.

    Trigger-ele sunt de obicei folosite pentru :



  3. Trigger-ele sunt scrise in PL/SQL

    PL/SQl este un limbaj 3GL.Asa cum o sugereaza su numele,PL/SQL este foarte apropiat de SQL.El ne permite sa "asezam" declaratii SQL intr-un "vehicul" pricedural.Acest unit se concentreaza asupra parti SQL a lui PL/Sql.Unit-urile ulterioare se vor ocupa declaratiile si sintaxa PL/SQL.

CUM SA DEFINIM TRIGGER-E ?


Se foloseste TRIGGER DEFINITON FORM .

    --------------------------------------------------------------------------
   |   ---------------------------------------------------------------------  |
   |  | Trigger: POST-CHANGE                | -----For Key TriggersOnly---- | |
   |  | Block:   DEPT                       | [   ] Show Keys               | |
   |  | Field:   DEPTNO                     | Descript:                     | |
   |  | Trigger Style: V3                   |                               | |
   |  | --------------------------------------------------------------------| |
   |  |    ----------------------Trigger text---------------------------    | |
   |  |  SELECT COUNT(empno)                                                | |
   |  |         SAL(sal=12 + NVL(comm,0)                                    | |
   |  |  INTO   :dept.scr_headcount,                                        | |
   |  |         :dept.scr_cost                                              | |
   |  |  FROM emp                                                           | |
   |  |  WHERE :emp.deptno = deptno;                                        | |
   |  |                                                                     | |
   |  | _________________________________________________________________   | |
   |  |   ________________________Comment___________________________        | |
   |  |   Whenever the DEPTNO changes,the employee statistics will          | |
   |  |   be calculated aadn written into display-only fields in the        | |
   |  |   DEPT block.                                                       | |
   |  |                                                                     | |
   |  |_____________________________________________________________________| |
   |                                                                          |
   |                                                                          |
   |__________________________________________________________________________|



CUM SA DEFINIM TRIGGER-E ?


Se creeaza si modifica trigger-e prin intermediul tabelei Trigger Definition sau a form-ului Trigger Definition.

  1. Definirea trigger-elor:

    Optiunea "Trigger" din meniul principal duce la tabela Spread Table Trigger Display.

  2. Caracteristicile trigger-elor :

    Numele trigger-ului (Trigger:)
    Fiecare trigger trebuie sa aiba un nume.In cele mai multe cazuri,numele descrie evenimentul care determina activarea trigger-ului.(ON-DELETE, KEY-NXFLD,PRE-FORM).Daca nu sunteti sigur de nume, folositi Lista de Valori.Se observa ca aceste nume de trigger-e predefinite contin caracterul "-",un caracter nepermis pentru denumirea de obiecte SQLForms.
    Scopul Trigger-ului
    Un trigger poate apartine unui camp,bloc sau form.Daca se lasa aceste doua campuri goale, trigger-ul apartine form-ului,daca ,campul este gol atunci trigger-ul este setat la nivel de bloc.
    Proprietarul unui trigger determina scopul in care opereaza el.Un trigger Post-Change intr-un camp este activat numai atunci cand se schimba campul;daca el apartine unui bloc, trigger-ul se va activa atunci cand ORICARE camp ce apartine blocului se schimba.
    Stilul trigger-ului
    Stilul trigger-ului este fie V3(implicit), fie V2.Stilul V2 exista pentru a asigura compatibilitatea cu form-urile mai vechi.
    Textul trigger-ului
    Daca este un trigger V3, se foloseste aceasta fereastra pentru a unsera text direct.Este o regiune cu scroll ce da posibilitatea de a accesa toate cheile de editare.Daca este un trigger V2,codul trebuie sa fie organizat in anumiti pasi.Apasati [Zoom] din fereastra Trigger Text pentru a defini acesti pasi.
    Comentarii
    Documentarea trigger-elor este foarte importanta pentru a clarifica un trigger logic complet.Campul de comentarii este si el o regiune cu scroll.

Se vor oferi informatii suplimentare asupra Key TriggerOnly mai tarziu in acest capitol.

DECLARATIILE DE TIP SELECT IN SQL*FORMS



  1. Declaratia SELECT :

    O declaratie SELECT trebuie sa fie folosita oricand un trigger are nevoie sa adreseze o valoare a unei baze de date.SQL*Forms paseaza toate declaratiile SQL catre ORACLE RDBMS pentru parcurgere si executie.

  2. Trigger-ul Select PL/SQL

    1. Declaratia Select intr-un trigger este similara ca sintaxa cu acele form-uri executabile din SQL*Plus.Sintaxa este descrisa mai jos :
      
                             SELECT name,breed,sex
                             INTO   :dog.name,:dog.bread,:dog.breed,:dog.sex
                             FROM   canines
                             WHERE  regno = :dog.regno;
      
      

      Se pot selecta atatea articole cate se doresc cat timp aveti tot atatea obiecte in clauza INTO ca si in lista specificata in declaratia SELECT.

    2. Declaratiile SELECT trebuie sa se termine cu ';'.

    3. Toate referintele la campurile ecran,variabilele globale si sistem trebuie precedate de ':'.

    4. Se preced toate numele de campuri cu numele blocului(si numele de coloane cu numele tabelelor sau al alias-urilor daca este folosita vreo conditie de join).

    5. Aproape toata sintaxa SQL poate fi folosita in codul trigger-elor. Cateva exceptii sunt notate mai jos.Evitati aceste clauze:
                         ORDER BY,CONNECT BY< START WITH.
      
      

      Nu folositi substitutii de variabile.

    6. O declaratie Select returneaza de obicei un singur rand din baza de date oricand este executat.Cand se scrie cod Select intr-un trigger,sunt doua "exceptii" pe care trebuie sa le preveniti:
                          * select-ul esueaza la returnarea  randului.
      
                          * select-ul gaseste mai mult de un rand care se potriveste
                            criteriului.
      
      
    7. cand se selecteaza date din baza de date este important sa restrictionez query-ul pentru a umple campuri relevante pe ecran.

THE POST-CHANGE TRIGGER


      Exemplu :

            Post-Change on EMP.SAL
            ________________________________________

            SELECT GRADE
            INTO :EMP.SCR_GRADE
            FROM SALGRADE
            WHERE :EMP.SAL BETWEEN LOSAL AND HISAL;
            ________________________________________


Acest tip de trigger poate avea ca scop un camp,bloc sau form si de obicei este setat la nivel de camp.El se activeaza cand valoarea intr-un camp se schimba la un insert,update sau cand o valoare este regasita intr-un camp al query-ului.Un trigger Post-Change nu se va activa daca o valoare existenta intr-un camp se schimba in null.

Doua utilizari frecvente ale declaratiilor Select in cazul trigger-elor Post-Change sunt :

Folosirea cursoarelor explicite :


Executia oricarei declaratii Sql va ocupa un loc intr-un buffer deseori referit ca un cursor.In PL/SQL se poate obtine un cursor explicit sau i se permite lui PL/SQL sa obtina cursoare implicite. Exemplele SQL din aceasta documentatie ilustreaza modul de folosire al cursoarelor implicite.
Cursoarele explicite pot fi folosite pentru a oferi o amnumita eficienta in anumite situatii.de acest lucru se ocupa unitul 21 "Consderatii de Eficienta si Design" si in detaliu in cursul :"Oracle:SQL,SQL*Plus and PL/SQL,Code SPL".

TRATAREA EXCEPTIILOR



Tratarea exceptiilor :


O exceptie este o conditie anormala de executie a unui trigger.executia normala a unui Select returneaza 1 rand,in oricealta situatie o exceptie aparand si ea trebuie sa fie tratata.Cele mai intalnita exceptii in cazul instructiunii SELECT sunt :


O exceptie trbuie gandita ca ointrerupere a executiei normale a unui trigger.Cand este intalnita o exceptie,procesarea blocului curent de cod este oprita si controlul este dat sectiunii de tratare a exceptiei,daca acesta exista.
Controlul poate sa nu mai revina la punctul in care a fost intalnita exceptia;pentru aceasta,sectiunea de tratare a intreruperii trebuie sa ofere posibilitatea alternativelor de procesare.Codul din sectiunea de tratare a exceptiei consta din una sau mai multe handle-uri ("pointeri") de exceptie care trateaza exceptia.
Daca nu exista nici un handle de exceptie pentru exceptia intalnita la un moment dat,SQL*Forms returneaza eroare catre form.


Ce este un handle la o exceptie ?


In general,un handle la o exceptie reprezinta o exceptie anume,apoi contine instructiunile care urmeaza a fi executate la intilnirea acelei exceptii.Se reaminteste ca sectiunea de tratare a exceptiilor URMEAZA dupa sectiunea executabila.Controlul i se da unui handler de exceptie pana nu :


Exceptiile netratate dau eroare:
        
        FRM-40735: < trigger type> trigger raised unhandled exception
        < exception name>


Tratarea exceptiilor :



Exceptii predefinite :


Exista doua situatii in care exceptiile sunt intalnite :
SQL*Forms are multiple exceptii predefinite,cateva fiind listate in continuare :
        
        EXCEPTIE :                      CAUZA:
        ______________________________________________________________________

        - NO_DATA_FOUND:                apare cand un cursor implicit SELECT
                                        returneaza zero randuri;
        - DUP_VAL_ON_INDEX              apare cand un INSERT sau UPDATE urmeaza
                                        sa creeze doua randuri cu valori
                                        duplicate in coloana(e) constransa
                                        de un index UNIQUE .
        - TOO_MANY_ROWS                 apare cand un cursor implicit SELECT
                                        returneaza mai mult de un rand;
        - INVALID_NUMBER                apare cand conversia unui sir de
                                        caractere la un numar esueaza deoarece
                                        sirul nu era un numar valid literal.
        - OTHERS                        este valabil pentru orice alte exceptii
                                        netratate explicit.


NOTA : Daca OTHERS este folosit trebuie sa fie ultima exceptie mentionata !

Pentru o lista completa ,vedeti "PL/SQL User's Guide and Reference".


Exceptia FORM_TIGGER_FAILURE :


Exceptiile de mai sus sunt valabile in orice implementare de PL/SQL. Exceptia FORM_TRIGGER_FAILURE poate fi folosita pentru fortarea esecului unui trigger.Cand exceptia Form_Trigger_Failure este intalnita , SQL*Forms cauta un handle de exceptie de acelasi nume.Daca il gaseste, executia trigger-ului se opreste si el esueaza.

Nota : Cand este intalnit un handle de exceptie de tipul 'WHEN OTHERS' atunci se va intercepta o exceptie de tipul 'Form_Trigger_Failure'. Cu alte cuvinte,daca este intalnita o exceptie de tipul 'Form_Trigger_Failure' in afara sectiunii de tratare a exceptiilor si se intalneste o exceptie de tipul 'When OTHERS',controlul este dat codului 'when Others'.


COMPARATIE ON-VALIDATE-FIELD SI POST-CHANGE



Un alt trigger de validare : On-validate-Field :


Trigger-ul On-Validate-Field inlocuieste trigger-ul Post-Change pentru scopuri de validare.On-Validate-Field se activeaza cand valoarea unui camp se schimba.Spre deosebire de Post-Change, el nu se activeaza dupa interogare.Deseori o combinatie intre On-Validate-Field si Post-Query poate inlocui Post-Change.


Deosebiri On-Validate-Field si Post-Change :


Amandoua se activeaza in conditii similare.Post-Change se activeaza cand valoarea campului se schimba intr-o valoare nenula.El se activeaza deasemenea oricand alte inregistrari extrase din tabela sunt aficate pe ecran.Spre deosebire de Post-Change,On-Validate-Field se va activa daca o valoare este setata la o valoare nula.El de asemenea se activeaza pentru noi sau actualizate inregistrari,dar nu pentru inregistrari fetched.Aceasta permite diferentierea intre procesul de validare si cel de fetch al inregistrarilor.Daca amandoua trigger-ele Post-Change si On-Validate-Field sunt definite pentru campul ENAME,in ce conditii se va activa fiecare ?
        Actiune         Veche           Noua            Post    On-Validate
                        valoare         valoare         Change  Field
                        camp            camp            fire ?  fire ?
        *******         *******         *******         ******  ************

        Insert                          JONES           yes     yes
        Update          SMITH           JONES           yes     yes
        Delete          SMITH                           no      yes
        Fetch                           SMITH           yes     no
        ********************************************************************



Nota : Amandoua trigger-ele trebuie sa fie tratate;un trigger Post-Change se va activa INAINTE de un trigger On-Validate-Field.

MAI MULTE EXEMPLE DESPRE VALIDAREA TRIGGER-ELOR


        Exemplul 1 :

                ON-VALIDATE-FIELD on EMP.MGR
                ---------------------------------------------------------------
                SELECT 0
                INTO :GLOBAL.dummy
                FROM EMP
                WHERE :EMP.MGR = EMP.MGR;
                EXCEPTION
                        WHEN NO_DATA_FOUND THEN
                                MESSAGE ('Invalid manager number;
                                                please re-enter');
                                RAISE FORM_TRIGGER_FAILURE;
                        WHEN TOO_MANY_ROWS THEN NULL;
                ---------------------------------------------------------------

Explicatii :
Acest trigger verifica daca numarul managerului intodus de utilizator este o valoare valida pentru campul MGR in tabela EMP.Fiecare insturctiune SELECT trbuie sa aiba o lista de selectie si o clauza INTO.pentru a satisface cerintele, codul utilizat arata astfel :
                        SELECT 0
                        INTO :GLOBAL.dummy


GLOBAL.dummy este este o variabila 'throw away" folosita de programator doar pentur a respecta sintaxa SELECT.Prefixul GLOBAL este folosit pentru definirea de variabile utilizator.

Daca GLOBAL.dummy nu exista,SQL*Forms o va crea.Daca nici un numar de manager nu se potriveste cu cel introdus de utilizator,controlul este dat tratarii exceptiei NO_DATA_FOUND si trigger-ul esueaza.Daca,pe de alta parte,numarul este valid,nici o schimbare nu este facuta asupra formului si cursorul se muta la urmatorul camp.

Se observa ca exista si tratarea exceptiei TOO_MANY_ROWS.Daca mai mult de un rand este gasit controlul este transmis aici.NULL este o instuctiune PL/SQl care spune "Fa nimic"("do nothing").acest trigger este implicat efectiv doar in validare. Nu este o necesitate ca el sa se activeze cand inregistrarea este fetched.

        Exemplul 2 :

                POST-CHANGE ON ITEM.PRODID
                ---------------------------------------------------------------
                SELECT STDPRICE
                INTO :ITEM.SCR_STDPRICE
                FROM PRICE
                WHERE :ITEM.PRODID = PRODID
                AND ENDDATE IS NULL;
                EXCEPTION
                        WHEN TOO_MANY_ROWS THEN
                                MESSAGE ('More than one row matches product
                                        code - contact support');
                        WHEN NO_DATA_FOUND THEN
                                MESSAGE ('Invalid Product Code');
                                RAISE FORM_TRIGGER_FAILURE;
                ---------------------------------------------------------------


Observatii:
Primul trigger citeste pretul curent pentru un produs in campul SCR_STDPRICE.Daca mai multe inregistrari satisfac interogarea,controlul va fi transferat catre handle-ul de tratare a exceptiei si utilizatorului i se va spune sa apeleze la serviciile unui specialist.In mod frecvent,faptul ca un trigger gaseste mai mult de un rand este greseala organizarii formului si nu a utilizatorului.

Daca codul produsului este invalid (i.e.,nici o intrare in tabela Price nu contine codul produsului curent),utilizatorul este informat SI trigger-ul esueaza.Deoarece acest trigger populeaza un camp al unei tabele non-base si in plus valideaza o intrare de la utilizator,un trigger POST-CHANGE este mai util dacat unul ON-VALIDATE-FIELD.


PROCESAREA TRIGGER-ELOR



Cand un trigger este activat,SQL*Forms proceseaza toate instructiunile in ordine,una cate una.Orice schimbare pe care o face o instuctiune asupra unui camp sau variabila este vizibila oricaror instructiuni urmatoare instructiunii curente.Salturile,ciclurile si tratarea exceptiilor pot afecta fluxul de procesare al trigger-ului.


Conceptele de Bloc Curent,Inregistrare si Camp Curente:


SQL*Forms(Runform) prelucreaza intotdeauna o singura inregistrare la un moment dat.Nu se vad inregistrarile dintr-un bloc ca un vector.Oricand se refera un camp de pe ecran intr-un trigger,SQL*Forms refera numai instanta curenta a campului.

Localizarea cursorului determina blocul curent,inregistrarea si campul curente.Se considera urmatorul trigger :

                SELECT grade
                INTO :emp.scr_grade
                FORM salgrade
                WHERE :emp.sal BETWEEN losal and hisal;

Daca cursorul este in blocul EMP cand trigger-ul se activeaza,numai campul GRADE din inregistrarea curenta este afectat. Sa presupunem ca cursorul este in blocul DEPT,cand se activeaza trigger-ul.Ce instanta a lui EMP.SCR_GRADE va fi schimbata ?Raspunsul este :campul inregistrarii care ar fi fost curenta daca cursorul era in bloc.

SQL*Forms intotdeauna pastreaza urma cu inregistrarile care ar fi curente daca un bloc dat ar fi curent.Stabilirea este facuta dupa cum urmeaza :


FUNCTIILE PL/SQL PENTRU TRATAREA ERORILOR SQL


Doua functiii PL/SQL :


PL/SQL ofera doua functii care permit evaluarea rezultatului celei mai recent executate instructiuni SQL.SQLCODE si SQLERRM sunt disponibile in orice mediu PL/SQL.
SQLCODE :
Returneaza (numeric) codul erorii ORACLE al exceptiei predefinite intern ce paseaza controlul handle-ului de tratare a ei.In afara unui handle de exceptie este evaluata la zero. Este folosita in special in tatarea exceptiilor de tip 'OTHERS' deoarece permite identificarea exceptiei interne intalnite. Daca este folosita cu un mesaj,se va folosi functia TO_CHAR pentru a converti la tipul caracter. Se indica folosirea ei doar in instructiuni PL/SQL;nu se poate apela direct intr-o instructiune SQL.
SQLERRM :
Daca nu are nici un argument ,functia intoarce intregul mesaj de eroare ORACLE asociat cu valoarea curenta a lui SQLCODE.Daca este dat ca argument o valoare de cod de eroare,se va intoarce mesajul asociat cu acel cod. Textul "normal,successful completion" este intotdeauna returnat cand SQLERRM este referit in afara unui handle de exceptie cu nici un argument. SQLERRM este utilizata pentru interceptarea erorilor PL/SQL care nu pot fi tratate ca exceptii predefinite.

Exemplu SQLERRM :


Exemplul de mai jos defineste un handle general de exceptii care va afisa mesajul erorii ORACLE care determina trecerea in sectiunea de tratare a exceptiei.De asemenea trigger-ul esueaza.
                EXCEPTION
                        WHEN OTHERS THEN MESSAGE ( SQLERRM );
                        RAISE FORM_TRIGGER_FAILURE ;


REZULTATUL TRIGGER-ELOR



Un trigger poate esua sau se termina cu succes.El reuseste implicit.Un trigger esueaza in unul din cele doua motive :

Ce se intampla daca un trigger esueaza ?


SQL*Forms opreste procesarea trigger-ului si preia o actiune implicita pentru tipul trigger-ului care a esuat.Tratarea dupa aparitia erorii inseamna in general esuarea actiunii care a cauzat activarea trigger-ului,in primul rand.

        Trigger                 Actiune care            Ce se intampla
        Tip :                   determina activarea     la esuarea
                                trigger-ului:           trigger-ului :
        ******************************************************************

        Post-Change----------\                          Cursorul ramane
                              \ Mutarea cursorului      in campul curent.
                               /in afara campului
        On-Validate-Field-----/ schimbat

        ******************************************************************


TRIGGER : SUMAR (1)


Ce este un trigger ?



Cum sa definesti un trigger ?



Sintaxa :


                SELECT expresie [,expresie,etc.]
                INTO :block.field,etc.]
                FROM table [,table,etc.]
                [WHERE ...]
                [HAVING ...]
                [GROUP BY...];


TRIGGER : SUMAR (2) :



Mai multe exemple despre trigger-e :



Exemplul 1 :


Acest trigger populeaza doua campuri dintr-o tabela non-base in blocul DEPT oricand campul DEPTNO se schimba :

                POST-CHANGE on DEPT.DEPTNO
                ---------------------------------------------------------------
                SELECT SUM(sal * 12 + nvl (comm,0)), COUNT (*)
                INTO :dept.scr_cost,
                     :dept.scr
                ---------------------------------------------------------------
        0 headcount
        FROM emp
        WHERE :dept.deptno = deptno ;
        -----------------------------


Exemplul 2 :


Sectiunea de tratare a exceptiilor a acestui trigger foloseste functia SQLERRM pentru a returna un cod de eroare ORACLE oricand o exceptie apare.

                POST-CHANGE on ITEM.PRODID
                ---------------------------------------------------------------
                SELECT STDPRICE
                INTO ;ITEM.SCR_STDPRICE
                FROM PRICE
                WHERE :ITEM.PRODID = PRODID
                AND ENDDATE IS NULL;
                EXCEPTION
                        WHEN OTHERS THEN
                                MESSAGE ( SQLERRM );
                                RAISE FORM_TRIGGER_FAILURE;
                ---------------------------------------------------------------


UNIT 9 : EXERCITII :


Folosirea Insstuctiunii SELECT in Trigger-e :


Utilizati tasta [Insert Record] pentru a crea un nou trigger Aveti grija sa nu suprascrieti trigger-e deja existente.Generati si testati dupa fiecare intrebare :

Exercitiul A :


  1. Scrieti un trigger in campul ITEM.PRODID pentru a popula campurile SCR_DESCRIB si SCR_STDPRICE cu informatii referitoare la valoarea curenta a lui PRODID.Alegeti tipul de trigger care se va activa cand inregistrarea este extrasa si cand un PRODID este inserat/modificat.Fiti sigur ca scrieti instructiunea Select a.i. sa restrictioneze data returnata la un singur rand.
    Nu includeti nici un fel de cod pentru tratarea exceptiilor.
  2. Testati formul dupa cum urmeaza :

    1. Interogati toate inregistrarile pornind de la numarul 610. Numeroase trigger-e se vor activa,incluzand-ul si pe cel generat de SQL*Forms cand blocurile sunt create.Observati ca trigger-ul scris se activeaza de fiecare data cand un item este afisat.

    2. Schimbati prodid pentru item-ul 1 la 100861 si apasati [Next Field].Iarasi,trigger-ul POST-CHANGE se activeaza.

    3. Inserati un nou item.Incercati un prodid cu 9999.Mesajul de eroare "unhandled exception" indica ,in acest caz,ca instructiunea select a trigger-ului a esuat la returnarea oricarui rand.Apasati [Clear Record] pentru a renunta la operatia de inserare.

    4. Iesiti din form,descarcand toate schimbarile facute.

  3. Imbunatatiti trigger-ul a.i. sa trateze exceptiile de tipul NO_DATA_FOUND si fortati esecul.

    Aveti nevoie de un handle la exceptii de tipul TOO_MANY_ROWS ?

    Exercitiul B :


    1. Scrieti un trigger in ORD.CUSTID pentru a copia respectiva baza de date in campurile SCR_NAME,SCR_REPID si SCR_ENAME ale aceluiasi bloc al tabelelor CUS si EMP.Acest trigger trebuie sa se activeze la o interogare de tipul insert/update.

    2. Includeti un handle de exceptie pentru tipul NO_DATA_FOUND. Adaugati si exceptiile WHEN OTHERS pentru tratarea celorlalte tipuri de exceptii prin tiparirea unui mesaj de eroare pentru eroarea curenta.


    Daca mai aveti timp :

    Exercitiul C :


    1. In blocul Cus,scrieti un trigger in campul REPID pentru a va asigura ca valoarea introdusa este numarul unui angajat care este vanzator. Acest trigger este diferit de cele precedente deoarece se doreste DOAR validarea si nu popularea campului.Folositi o variabila 'dummy',:GLOBAL.DUMMY ca un obiect in clauza INTO.


    UNIT 9 : SOLUTII :


    Exercitiul A :


    1. Trigger Post-Change in ITEM.PRODID :
                              SELECT P.DESCRIP,PR.STDPRICE
                              INTO :ITEM.SCR_DESCRIP, ;:ITEM.SCR_STDPRICE
                              FROM PRODUCT P,
                                   PRICE PR
                              WHERE :ITEM.PRODID = P.PRODID AND
                                    :ITEM.PRODID = PR.PRODID AND
                                    PR.ENDDATE IS NULL;
      
      
    2. Nici o solutie formala.

    3. Adaugati acest cod la sfarsitul trigger-ului Post-Change in
      
                        ITEM.PRODID :
                              EXCEPTION
                                      WHEN NO_DATA_FOUND THEN
                                              MESSAGE ('Error :Invalid product code .
                                                      Use [List] for help');
                                              RAISE FORM-TRIGGER_FAILURE;
      
      

    Deoarece este posibil ca mai mult de un singur pret pentru un produs sa aiba o valoare nula pentru enddate,s-ar putea sa doriti sa aveti si codul pentru exceptii de tipul TOO_MANY_ROWS.

    Exercitiul B :


                    Trigger Post-Change in ORD.CUSTID :
    
                    SELECT  C.NAME,C.REPID,E.ENAME
                    INTO    :ORD.SCR_NAME,:ORD.SCR_REPID,:ORD.SCR_ENAME
                    FROM    CUS C,
                            EMP E
                    WHERE   :ORD.CUSTID = C.CUSTID AND
                            C.REPID = E.EMPNO;
                    EXCEPTION
                            WHEN NO_DATA_FOUND THEN
                                    MESSAGE ('ERROR : Invalid custid-press < list>
                                            for help');
                                    RAISE FORM_TRIGGER_FAILURE;
                            WHEN OTHERS THEN
                                    MESSAGE (SQLERRM);
    
    

    Exercitiul C :


    1. On-Validate-Field in CUSTOMER.REPID :
      
                              SELECT  'x'
                              INTO    :GLOBAL.DUMMY
                              FROM    EMP
                              WHERE   EMP.EMPNO = :CUS.REPID
                                      AND JOB = 'SALESMAN';
                              EXCEPTION
                                      WHEN NO_DATA_FOUND THEN
                                              MESSAGE ('ERROR : No salesman has this
                                                      ID;please re-enter');
                              RAISE FORM_TRIGGER_FAILURE;
      
      
    2. Nici o solutie formala.