TRIGGER-E DE INTEROGARE (QUERY TRIGGERS) SI SCOPUL TRIGGER-ELOR

Continutul acestui unit :


In acest capitol se vor extinde cunostintele despre tipurile de trigger-e si codul unui trigger. Subiecte atinse :


ATRIBUIRILE SI TASTARILE VALORILOR UNUI CAMP :




Atribuirea de valori campurilor :


In capitolul precedent ,ati folosit instructiuni SELECT pentru a popula si valida campuri,acolo unde erau necesare extrageri de valori din baza de date.

Instructiunea PL/SQL de atribuire este folosita atunci cand datele pot fi obtinute din campurile ecran sau din mediul SQL*Forms (adica SYSDATE,USER,si UID pot fi referite direct intr-o instructiune de atribuire).


Testarea valorilor campurilor utilizand IF :


PL/SQL are instructiunea IF pentru executarea conditionala a uneia sau mai multe instructiuni.Daca expresia din instructiunea IF este evaluata la TRUE,instructiunile care urmeaza sunt executate.Altfel,ele vor fi sarite.Un IF trebuie intotdeauna sa se termine printr-un END IF.

   Exemplu :
                IF :item.qty > 100 THEN
                        MESSAGE ( 'Large order - check stock on hand');
                END IF;


In exemplul de mai sus,utilizatorul primeste un mesaj numai daca cantitatea este mai mare de 100. Sintaxa completa a instructiunii IF este prezentata in ORACLE:SQL,SQL*Plus si PL/SQL,si este prezent in Anexa E.

TRIGGER-ELE QUERY





Exista doua tipuri de trigger-e asociate query-urilor:PRE-QUERY si POST-QUERY.Ele sunt in mod normal definite la nivel de bloc;asadar,ele apartin doar blocului particular al formului si sunt executate oricand utilizatorul executa o interogare (un query) asupra blocului.


Trigger-ul Pre-Query :



Un trigger de acest tip se executa doar DUPA ce utilizatorul a apasat tasta [Execute Query],dar inainte ca irice rand sa fi fost extras din baza de date.Acest tip de trigger permite conditii de cautare pe care utilizatorul le introduce in campurile de pe ecran. Aceste trigger-e sunt de obicei folosite pentrua valida conditiile stabilite de utilizator pentru query si/sau permiterea restrictiilor aditionale la query.

        Exemplul 1 :
        Pentru a stabili o interogare in blocul EMP daca nici un departament nu
        este afisat,se poate folosi urmatorul trigger :


                PRE-QUERY on EMP Block
                ---------------------------------------------------------------
                IF :dept.deptno IS NULL THEN
                        MESSAGE ('Interogati blocul de departament mai intai');
                   RAISE FORM_TRIGGER_FAILURE;
                END IF;
                ---------------------------------------------------------------

        Exemplul 2 :
        Acest al doilea exemplu previne orice interogare asupra blocului Dept.
                PRE-QUERY on DEPT Block
                ---------------------------------------------------------------
                IF TO_CHAR (:dept.deptno) || :dept.dname || :dept.loc IS NULL
                        THEN
                        MESSAGE ('Trebuie sa interogati un departament anume');
                   RAISE_TRIGGER_FAILURE;
                END IF;
                ---------------------------------------------------------------

        Daca utilizatorul da un query global asupra blocului Dept,mesajul este
        afisat si trigger-ul esueaza.Acest lucru inseamna ca formul va ramane
        in modl query asteptand pentru actiuni urmatoare ale utilizatorului.


Trigger-ul Post-Query



        Exemplu :
                POST-QUERY on EMP Block
                -----------------------------
                :emp.annsal := :emp.sal * 12;
                -----------------------------

Trigger-ul Post-Query este executat DUPA ce inregistrarile sunt extrase din baza de date in query.Se activeaza de fiecare data cand SQL*Forms afiseaza o nireegistrare in bloc.Daca trigger-ul esueaza,inregistrarea curenta ce este procesata nu este afisata. El este de obicei folosit pentru :


        Exemplu :
        Trigger-ul de mai jos va calcula o informatie statistica despre
        angajati corespunzator departamentului curent :

                POST-QUERY on DEPT Block
                -----------------------------------------------
                SELECT COUNT(empno),SUM(sal * 12 + NVL(comm,0))
                INTO :dept.scr_headcount,:dept.scr_deptcost
                FROM emp
                WHERE deptno = :DEPR.DEPTNO;
                -----------------------------------------------


Trigger-ele Post-Query si On-Validate-Field


Asa cum s-a vazut in capitolul precedent,trigger-ul On-Validate-field poate inlocui trigger-ul Post-Change pentru validarea scopurilor,dar esueaza asupra unei interogari (query).O combinatie intre Post-Query si On-Validate-Field poate fi folosita pentru a inlocui complet pe Post-Change.Acest lucru permita ca chiar daca continutul unui camp se schimba la valoarea NULL,executia respectiva nu esueaza.

Mai multe exemple la trigger-e :


        Exemplul 1:

        Acest trigger previne un query asupra blocului EMP daca nici un
        departament nu este afisat in blocul DEPT :

                PRE-QUERY on EMP Block
                ------------------------------------------------------------
                IF :dept.deptno IS NULL THEN
                        MESSAGE ('Interogati blocul referitor la departament
                                mai intai');
                        RAISE FORM_TRIGGER_FAILURE;
                END IF;
                ------------------------------------------------------------

        
        Exemplul 2:

        Acest trigger calculeaza intervalul de timp in care un angajat a lucrat
        la firma si scrie valoarea intr-un camp al unei tabele non-base :

                POST-QUERY on EMP Block
                ----------------------------------------------------------
                :emp.scr_month  := months_between (sysdate, ;emp.hiredate);
                ----------------------------------------------------------

Acest trigger se activeaza doar la interogare.Pentru a calcula acelasi lucru cu ajutorul operatiilor insert/update,scrieti un trigger On-Validate-Field (continand un cod similar) in EMP.HIREDATE.


SUMAR : DESCHIDERE QUERY SI EXECUTARE EXTRAGERI DIN BAZA DE DATE :



  1. Utilizatorul apasa [Execute Query]
  2. Se activeaza trigger-ele Pre-Query.
  3. "Exemple record" flushed din bloc.
  4. Inregistrarile sunt extrase din baza de date.
  5. Valorile dintr-un rand sunt citite in campurile inregistrarilor tabelei de baza.
  6. Pentru fiecare camp not-null din inregistrare,se activeaza trigger-ul Post-Query.
  7. Inregistrarea este marcata ca valida.
  8. Triger-ul Post-Query se activeaza;daca esueaza,inregistrarea este eliminata din bloc.
  9. Daca mai este spatiu in bloc SI mai sunt si alte randuri in buffer, urmatoarea inregistrare este procesata(tratata).


Nota : daca un trigger Post-query esyeaza inregistrarea NU VA FI afisata.

SCOPUL TRIGGER-ELOR



Definirea trigger-elor la nivelul corespunzator:


In exercitiile de pana acum,v-a fost indicat sa definiti trigger-ul la un camp sau bloc particular.Anumite trigger-e,ca P-C + o-V-F sunt de obicei folosite la nivel de camp;altele,ca Pre-Q sau Post-Q nu pot apartine unui camp si sunt de obicei definite la nivel de bloc .



Scopul Triger-ului :



Scopul trigger-ului este domeniul sau intervalul in care opereaza.Scopul este determinat de proprietarul(nivelul de definitie al trigger-ului) trigger-ului.Apartine el unui camp,bloc sau form?

Cand apare un eveniment-apasarea unei taste sau schimbarea valorii unui camp-SQL*Forms cauta trigger-ul asociat acelui eveniment.De exemplu,daca utilizatorul schimba campul EMPNO al blocului EMP si apasa [Next Field]. SQL*Forms cauta dupa un trigger P-c sau O-V-F.Daca exista un O-V-F definit,il executa.

Daca este definit un tigger O-V-F pentru campul EMPNO Si un al doilea trigger pentru blocul EMP?Cand acelasi tip de trigger este definit la mai mult de un nivel,particularul il inlocuieste pe cel general.Cu alte cuvinte,cu cursorul in campul EMPNO,trigger-ul O-V-F apartinand lui EMPNO se va activa in locul lui O-V-F pentru blocul proprietar.O-V-F in blocul EMP este implicit pentru alte campuri care nu au propriul trigger O-V-F.

Deseori,trigger-ele pot fi definite la orice nivel(camp,bloc,form),dar:

COMPILAREA :




Compilarea in PL/SQL :



COMENTARIILE IN PL/SQL :


        * -- indica o linie (sau partial o linie) de comentariu.

        :total := NVL (:total,0) + 1 --increment counter

        * /* */ incadreaza textul unui comentariu.

        /******
        * Acesta este un mod de a scrie
        * un comentariu!
        ******/


EXERCITII



  1. Scrieti un trigger in blocul ORD care sa afiseze urmatorul measaj de fiecare data cand o inregistrare are campul COMMPLAN null.Trigger-ul nu trebuie sa esueze.
                    WARNING: COMMPLAN is null; please update with A,B or C.
    


  2. Generati si testati formul.

  3. Scrieti un trigger in blocul ITEM care esueaza afisand un mesaj corespunzator,daca o inregistrare nu este afisata in blocul ORD cand se realizeaza interogarea.
            Idee : Deoarece campul ORD.ORDID este automat generat,el nu va fi
            niciodata null.Trebuie sa testati ALT camp decat ORDID in acest trigger.
    
            Pentru a testa trigger-ul :
                    -> executati formul Orders.
                    -> apasati [Next Block].
                    -> Apasati [Execute Query].
    


  4. Scrieti un trigger la nivel de camp in ITEM.QTY si ITEM.ACTUALPRICE care sa calculeze ITEM.ITEMTOT inmultind :ITEM.QTY cu :ITEM.ACTUALPRICE.ITEMTOT este un camp base-table,deci trigger-ul nu trebuie sa se activeze la interogare(query).


UNIT 10 : SOLUTII :



        1.
         ____________________________________________________________________
        | Trigger: POST-QUERY           | -------For Key Triggers Only------ |
        | Block:   ORD                  |  [  ] Show Keys                    |
        | Field:                        |  Describ :                         |
        | Trigger Style: V3             |                                    |
        |-------------------------------|------------------------------------|
        |     -----------------------Trigger text-----------------------     |
        |     IF :ORD.COMMPLAN IS NULL THEN                                  |
        |       MESSAGE ('WARNING:Commplan is null - please update with A,   |
        |                               B or C');                            |
        |     END IF;                                                        |
        |                                                                    |
        |                                                                    |
        |____________________________________________________________________|

        2.
          Nici o solutie formala.

        3.
         ____________________________________________________________________
        | Trigger: PRE-QUERY            | -------For Key Triggers Only------ |
        | Block:   ITEM                 |  [  ] Show Keys                    |
        | Field:                        |  Describ :                         |
        | Trigger Style: V3             |                                    |
        |-------------------------------|------------------------------------|
        |     -----------------------Trigger text-----------------------     |
        |     IF :ORD.CUSTID IS NULL THEN                                    |
        |       MESSAGE ('ERROR: Please display an order first');            |
        |       RAISE FORM_TRIGGER_FAILURE;                                  |
        |     END IF;                                                        |
        |                                                                    |
        |                                                                    |
        |____________________________________________________________________|


        Nota : CUSTID nu este un camp null;oricand este afisat,CUSTID nu va fi
               null.


        4.
         ____________________________________________________________________
        | Trigger: ON-VALIDATE-FIELD    | -------For Key Triggers Only------ |
        | Block:   ITEM                 |  [  ] Show Keys                    |
        | Field:                        |  Describ :                         |
        | Trigger Style: V3             |                                    |
        |-------------------------------|------------------------------------|
        |     -----------------------Trigger text-----------------------     |
        |     :ITEM.ITEMTOT := :ITEM.QTY * :ITEM.ACTALPRICE;                 |
        |                                                                    |
        |                                                                    |
        |                                                                    |
        |                                                                    |
        |                                                                    |
        |____________________________________________________________________|