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:
- Scrierea procedurilor form-level
- Transmiterea parametrilor procedurilor
- Functii form-level
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:
- 'name' cu care va fi identificat de procedura
- 'in/out/in out' indicator pentru a specifica daca
parametrul este introdus in procedura(in) sau trans-
mis afara din procedura spre trigger-ul apelant(out)
sau ambele sensuri(in out)
- 'datatype' al parametrilor
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
- proceduri PL/SQL
- returneaza o valoare apelantului
- Sintaxa:
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
- Proceduri form-level:
PROCEDURE procedure_name [(arg_list)] is [declarations;]
BEGIN
procedure_statement;
[procedure_statements:]
[EXCEPTION
exception_handlers;]
END;
- Functii form-level:
FUNCTION function_name[(arg_list)]
RETURN datatype IS
[declarations;]
BEGIN
procedure_statement [S];
RETURN (expression);
[EXCEPTION
exception_handlers;]
END;
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.
- 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.
- 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:
- selecteaza MINPRICE pentru productie intr-o vari-
abila locala
- esecul trgger-ului sa fie insotit de un mesaj sem-
nificativ daca ACTUALPRICE este mai mic decat pre-
tul minim. Specificati pretul minim in mesaj.
- apelati CALC_ITEMTOT daca ACTUALPRICE introdus nu
este in urma pretului minim pentru productie.
Modificati existentul ON-VALIDATE-FIELD pe ITEM.
QTY pentru folosirea CALC_ITEMTOT.
CAPITOLUL 15: Solutii
-
FORM-LEVEL PROCEDURE named FAIL
--------------------------------
PROCEDURE FAIL IS
BEGIN
RAISE FORM_TRIGGER_FAILURE;
END;
---------------------------------
-
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;