Proceduri form-level


Continutul acestui capitol:


Cu SQL*Forms, constructorul de aplicatie poate crea proceduri form-level sa poata retine codul comun folosit. Procedurile pot uti- liza parametrii care scad nevoia numelor obiect greu codificate din corpul procedurii.

Acest capitol acopera urmatoarele subiecte:


Proceduri form-level


Definirea procedurilor form-level



Transmiterea parametrilor la si de la procedura


Cum sa referim parametrii?


In scopul parametrizarii procedurii form-level, adaugati la numele procedurii o lista a parametrilor intre paranteze. Fiecare referinta a parametrului trebuie sa includa:


Exemplu de procedura parametrizata:


Urmatoarea procedura form-level executa un calcul cu doua valori de intrare si o valoare de iesire. Corpul procedurii nu contine nume de campuri sau valori 'hard-coded'; acestea sunt suplinite ca parametrii cand procedura este apelata de trigger.Aceasta adauga flexibilitatea ca diferite campuri de nume sau valori sa poata fi inlocuite cand procedura este apelata, astfel ca o singura procedura poate fi folosita pentru seturi multiple de campuri/valori si poate fi folosita de multa triggere.
        Exemplu:
                 PROCEDURE CALCULATE (val1 in number
                                      val2 in number
                                      val3 in out number) IS
                 BEGIN val3:=val1*val2;
                 END;

Procedura poate fi apelata dupa cum urmeaza:
                CALCULATE (:ITEM.QTY,
                           :ITEM.ACTUALPRICE,
                           :ITEM.ITEMTOT);

Poate fi utilizata pentru alte calcule similare:
                CALCULATE (:EMP.SAL,
                           12,
                           :EMP.SCR_ANNSAL);

Furnizarea valorilor implicite pentru argumente


Ori de cate ori PL/SQL compileaza un trigger sau o procedura care apeleaza o procedura, PL/SQL verifica daca lungimea si tipurile de date ale listelor de argumente se potrivesc.

Pentru a face o procedura mai flexibila puteti furniza valori gresite pentru cateva sau toate argumentele.
        Exemple:
                PROCEDURE PL_EDIT_FIELD
                        (width in number := 80,
                         height in number := 22,
                         x_pos in number := 1,
                         y_pos in number := 1) IS
                BEGIN
                  EDIT_FIELD(x_pos, y_pos, width, height)
        END;

Aceasta procedura poate fi apelata utilizand una din urmatoarele:
                PL_EDIT_FIELD;            -accepta toate lipsurile
                PL_EDIT_FIELD(60,10);     -defineste doar dimensiunea; pozitia
                                           lipseste
                PL_EDIT_FIELD(60,10,5,5); -defineste si dimensiunea si pozitia

Functii Form-Level


                FUNCTION function_name[(arg_list)]
                         RETURN datatype IS
                BEGIN
                .
                .
                RETURN(< expression>);
                [EXCEPTION exception_handlers;]
                END;

Declararea si folosirea functiilor PL/SQL

La proceduri(Form-Level), in plus, SQL*Forms ajuta de asemenea la utilizarea functiilor PL/SQL.

Sintaxa pentru declararea functiilor PL/SQL paralele ale unei proce- duri, care adaugata la 'RETURN datatype' cauzeaza identificarea tipu- rilor de valori pe care le intoarce functia:
        FUNCTION function_name (parameter_name mode [:=value],...)
                RETURN datatype IS

                BEGIN
                        procedure_statement[s];
                        RETURN(expression);

                EXCEPTION
                        RETURN(expression);

                END;

Instructiunea PL/SQL 'RETURN(expr)' intoarce expresia data ca valoare a functiei si se termina cu succes.

De cand o functie reprezinta expresia unui tip de date dat, ea poate fi folosita in acelasi mod ca o constanta sau variabila PL/SQL sau acelasi tip de date ar putea fi utilizat.
        Exemplu:
                FUNCTION which_page RETURN CHAR IS
                BEGIN
                     RETURN(FIELD_CHARACTERISTIC(SYSTEM.CURSOR_FIELD),PAGE));
                END;

Trigger-ul apelant poate arata cam asa:
                (ANCHOR_VIEW(which_page,1,1);

NOTA: Orice poate fi facut cu o functie poate fi de asemenea facut cu o procedura care include un parametru OUT pentru a intoarce valoarea dori ta. Este de preferat ca proiectantul sa aleaga sintaxa dorita.

Proceduri si programe de intretinere


Proceduri care functioneaza ca blocuri "cuiburi" PL/SQL

                                Begin
                                ...
                                    ...
                                    Begin
                        1.          ...
                                    ...
                        2.          Exception
                                    ...
                                    End;
                        3.  ...
                            ...
                        4.  Exception
                            ...
                            ...
                            End;



                Calling Trigger                 Procedure
                ---------------                 ----------
                     BEGIN
                     ...                        PROCEDURE FRED IS
                  1. fred;                      BEGIN
                  4. ...                     2. ...
                     ...                     3. EXCEPTION
                     EXCEPTION                  ...
                     ...                        END;
                     ...
                     END;

Cand o exceptie are loc intr-o procedura form-level, cercetarea pentru o exceptie este aceeasi ca si cand procedura cod a fost un bloc cuib in apelarea trigger-ului.


Exceptii ale intretinerii in blocuri cuib


Blocurile PL/SQL pot fi imbricate. Daca o exceptie este in blocul initial, PL/SQL va cauta cel mai apropiat program de tratare a excep- tiei pornind cu sectiunea EXCEPTION a blocului curent.

In diagrama opusa, daca a aparut o exceptie intr-un bloc cuib(#1), controlul se transfera sectiunii EXCEPTION a acelui bloc(#2). Dupa ce programul de tratare a exceptiei este procesat, controlul se rezuma la primul stagiu urmat de sfarsitul blocului curent.(#3).

Daca nu exista program de tratare a exceptiei definit in blocul ini- tial pentru a intretine exceptia particulara care a fost intalnita, controlul se transfera la iesirea sectiunii de exceptie(#4).

Daca nici un program de tratare a exceptiei nu este furnizat catre exceptia care a fost intalnita, utilizatorul primeste o eroare PL/SQL Unhandled Exception.


Programe de tratare a exceptiilor pentru proceduri


In a doua diagrama, procedura Fred este apelata dintr-un trigger(#1). O exceptie este intalnita in procedura(#2). Controlul se transfera sectiunii de exceptie a procedurii(#3). Dupa ce programul de tratare exceptiei este procesat, controlul este returnat trigger-ului ape- lant in prima etapa urmand apelarea procedurii(#4).

Daca nu exista nici un program de tratare a exceptiei definit in pro- cedura pentru a trata exceptia particulara care a fost dezvoltata, controlul se va transfera sectiunii de exceptie a trigger-ului care a aelat procedura.

Iarasi, daca daca nici un program de tratare a exceptiei nu este fur- nizat pentru exceptia care a fost dezvoltata, utilizatorul primeste o eroare PL/SQL Unhandled Exception.

Sintaxa procedurilor



CAPITOLUL 15: Exercitii


Proceduri form-level


Cand scrierea procedurii utilizeaza structura Procedure Definition nu aveti un tabel destul de intins care va da un mic spatiu pentru introducerea textului.

  1. Scrieti o procedura numita FAIL care dezvolta FORM_TRIGGER_ FAILURE. Modificati cateva din trigger-ele voastre existen- te pentru a va folosi procedura in loc de RAISE FORM_ TRIGGER_FAILURE.
  2. Daca doriti update ITEMTOA de fiecare data cantitatea sau pretul actual se schimba. Pentru a realiza aceasta, scrieti o singura procedura form-level, CALC_ITEMTOT, care este apelata de la trigger-ul ON-VALIDATE-FIELD pe ITEM.QTY si ITEM.ACTUALPRICE. Corpul procedurii n-ar trebui sa contina nume de campuri 'hard-coded'. Aceasta ar trebui sa fie su- plinite prin parametrii cand CALC.ITEMTOT este apelat. Scrieti un trigger ON-VALIDATE-FIELD pe ITEM.ACTUALPRICE astfel incat sa faca de asemenea urmatoarele:


CAPITOLUL 15: Solutii


  1.            FORM-LEVEL PROCEDURE named FAIL
               --------------------------------
               PROCEDURE FAIL IS
               BEGIN
                     RAISE FORM_TRIGGER_FAILURE;
               END;
               ---------------------------------
    

  2.            FORM-LEVEL PROCEDURE named CALC_ITEMTOT
               -----------------------------------------
               PROCEDURE CALC_ITEMTOT          (VAL1 IN NUMBER,
                                                VAL2 IN NUMBER,
                                                VAL3 IN NUMBER) IS
               BEGIN
                     VAL3:=VAL1*VAL2;
               END;
               ---------------------------------------------------
    
    
               ON-VALIDATE-FIELD on ITEM.QTY
               --------------------------------------------------
               CALC_ITEMTOT(:item.qty,:item.actualprice,:item.itemtot);
               IF :ITEM.QTY = 100 THEN
                  DISPLAY_FIELD('item.qty','underline');
                    MESSAGE('Large order-please check stock on hand');
               ELSE
                    DISPLAY_FIELD('item.qty','normal');
               END IF;
               ----------------------------------------------------------
    
               ON-VALIDATE-FIELD on ITEM.ACTUALPRICE
               -------------------------------------------------------
               DECLARE MINIMUM NUMBER;
               BEGIN
                     SELECT         MINPRICE INTO MINIMUM
                     FROM           PRICE
                     WHERE          :ITEM.PRODID = PRODID
                     AND            ENDDATE IS NULL;
               IF :ITEM.ACTUALPRICE< MINIMUM THEN
                    MESSAGE('Actual price cannot be less than'
                           ||TO_CHAR (MINIMUM));
                           FAIL;
                    ELSE
                         CALC_ITEMTOT (:item.qty,:item.actualprice,:item.itemtot);
                END IF;
              END;