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 sunt trigger-ele ?
- Utilizarea SELECT pentru obtinerea valorilor din baza de date.
- Trigger-ele Post-Change si On-Validate-Field.
- Handle-uri de exceptii si exceptii.
- Obtinerea de informatii asupra erorilor SQL.
CE ESTE UN TRIGGER ?
- Cod de activare la aparitia unui eveniment:
- Entry
- Exit
- Change
- Query
- Key
- Folosirea trigger-elor include :
- validarea intrarilor
- popularea campurilor
- redefinirea cheilor
- verificarea integritatii referentiale
- controlul fluxului aplicatiei
- Trigge-rele sunt scrise in PL/SQL
- 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.
- 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 :
- A reliza validarile care nu pot puse odata cu definitiile de campuri
- Popularea campurilor de pe ecran cu date
- Verificarea integritati referentiale a unei baze de date
- Redefinire de chei
- Reactualizarea fluxului de control
- Controlul fluxului logic al aplicatiei
- 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. | |
| | | |
| |_____________________________________________________________________| |
| |
| |
|__________________________________________________________________________|
- Numele trigger-ului = evenimentul
- Block/Field = Scopul trigger-ului
- Stilul este V3 sau V2
- Textul este in format liber
CUM SA DEFINIM TRIGGER-E ?
Se creeaza si modifica trigger-e prin intermediul tabelei Trigger
Definition sau a form-ului Trigger Definition.
- Definirea trigger-elor:
Optiunea "Trigger" din meniul principal duce la tabela Spread Table
Trigger Display.
- 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
- Declaratiile de tip select sunt folosite pentru :
- obtinerea de valori din baza de date
- compararea de valori intre valorile de pe ecra si cele ale bazei
de date.
- Sintaxa trigger-elor Select PL/SQL :
SELECT expression [, expression,etc.]
INTO :block.field [,:block.field,etc.]
FROM table [,table,etc.]
[WHERE ...]
[HAVING...]
[GROUP BY...];
- O executie "normala" returneaza un singur rand.
- 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.
- Trigger-ul Select PL/SQL
- 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.
- Declaratiile SELECT trebuie sa se termine cu ';'.
- Toate referintele la campurile ecran,variabilele globale si
sistem trebuie precedate de ':'.
- 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).
- 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.
- 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.
- 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 :
- Popularea de campuri ecran.
- Validarea intrarilor de la utilizator.
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
- Formatul exceptiilor :
"Sectiunea executabila;"
EXCEPTION
WHEN nume_exceptie THEN
"actiuni de facut;"
WHEN alta_nume_de_exceptie THEN
"actiuni de facut;"
- Exemplu :
Post-Change on EMP.SAL
-----------------------------------------
SELECT GRADE
INTO :EMP.SCR_GRADE
FROM SALGRADE
WHERE :EMP.SAL BETWEEN LOSAL AND HISAL;
EXCEPTION
WHEN NO_DATA_FOUND THEN
MESSAGE ('Invalid Salary-Check and re-enter');
RAISE form_trigger_failure;
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 :
- esec datorita returnarii oricaror randuri intr-un query OR;
- gasirea mai multor randuri care verifica conditia de interogare.
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 :
- o exceptie apare in timpul procesarii sectiunii executabile.
- SI exceptia care apare se potriveste cu una din exceptiile testate.
CAND ALTE exceptii se vor potrivi cu alte exceptii anterioare
netratate.
Exceptiile netratate dau eroare:
FRM-40735: < trigger type> trigger raised unhandled exception
< exception name>
Tratarea exceptiilor :
- Executia normala a unui SELECT returneaza un singur rand .
- Exceptiile sunt intalnite daca :
-- daca o exceptie apare ;
SAU
-- raise < exception name>
- Cateva exceptii predefinite :
-- NO_DATA_FOUND;
-- TOO_MANY_ROWS;
-- OTHERS;
-- FORM_TRIGGER_FAILURE;
- FORM_TRIGGER_FAILURE :
-- oprire normala si esec trigger;
Exceptii predefinite :
Exista doua situatii in care exceptiile sunt intalnite :
- Daca instructiunea RAISE < exception_name> este executata;
- Daca o exceptie apare;
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
- Amandoua :
- se activeaza cand se schimba valoarea campului .
- sunt de obicei definite la nivel de camp .
- Post-Change :
- de asemenea se activeaza dupa interogare .
- folosit pentru popularea campurilor tabelelor non-base.
- nu se activeaza atunci cand valoarea campului se schimba in
null.
- On-Validate-Field :
- poate fi folosit pentru validari .
- nu se activeaza intr-o interogare.
- folosit pentru schimbarea valorilor campurilor unei tabele
base.
- se activeaza daca valoarea campului se schimba in null.
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
- Instructiunile se executa secvential :
- schimbarile sunt vizibile in instructunile urmatoare.
- se poate controla fluxul de executie.
- SQL*Forms prelucreaza o singura inregistrare la un moment dat :
- oricand un trigger este activat,numai inregistrarea curenta
este afectata .
- FIELD se refera la instanta curenta a campului :
- localizat in inregistrarea curenta SAU
- inregistrarea care urmeaza daca cursorul a fost in acel bloc.
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 :
- inregistrarea care a fost ultima cand cursorul a fost in bloc SAU
- prima inregistrare a blocului daca cursorul nu a fost inca in bloc.
FUNCTIILE PL/SQL PENTRU TRATAREA ERORILOR SQL
Doua functiii PL/SQL :
- SQLCODE
- folosita numai cand este tratata o exceptie.
- altfel este evaluata la zero.
- SQLERRM
- returneaza textul mesajului de eroare ORACLE.
- daca nu are nici un argument,textul este corespunzator
lui SQLCODE.
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
- Trigger-ele se termina cu succes sau esueaza :
- Cand un trigger esueaza :
- procesarea trigger-ului se opreste .
- SQL*Forms ia o actiune standard .
- de obicei actiunea care determina activarea trigger-ului
esueaza .
Un trigger poate esua sau se termina cu succes.El reuseste implicit.Un
trigger esueaza in unul din cele doua motive :
- FORM_TRIGGER_FAILURE este tratata .
- o exceptie netratata este intlnita .
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 ?
- o bucata de cod activata de catre un eveniment .
Cum sa definesti un trigger ?
- se foloseste formul Trigger Definition pentru un trigger nou.
- se foloseste Spread Table Trigger Definition pentru o editare
rapida a capurilor non-text.
- Folositi SELECT pentru a obtine valori din baza de date.
Sintaxa :
SELECT expresie [,expresie,etc.]
INTO :block.field,etc.]
FROM table [,table,etc.]
[WHERE ...]
[HAVING ...]
[GROUP BY...];
TRIGGER : SUMAR (2) :
- O exceptie intrerupe procesarea normala :
- cauzata de o eroare sau un eveniment 'anormal'
- Un handle de exceptie :
- proceseaza exceptiile specifice .
- exemple :
POST-CHANGE in EMP.DEPTNO
---------------------------------------------------------------
SELECT dname
INTO :emp.scr_dname
FROM dept
WHERE :emp.deptno = deptno;
EXCEPTION
WHEN NO_DATA_FOUND THEN
MESSAGE ('This departament does not exist.
Press < List> for help.');
RAISE FORM_TRIGGER_FAILURE ;
---------------------------------------------------------------
- Exceptiile predefinite includ :
NO_DATA_FOUND
TOO_MANY_ROWS
OTHERS
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 :
- 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.
- Testati formul dupa cum urmeaza :
- 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.
- Schimbati prodid pentru item-ul 1 la 100861 si apasati
[Next Field].Iarasi,trigger-ul POST-CHANGE se
activeaza.
- 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.
- Iesiti din form,descarcand toate schimbarile facute.
- 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 :
- 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.
- 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 :
- 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 :
- 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;
- Nici o solutie formala.
- 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 :
- 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;
- Nici o solutie formala.