Académique Documents
Professionnel Documents
Culture Documents
curseur trigger
Programme PL/SQL
unit de base : le bloc PL/SQL n'interprte pas une commande mais un ensemble de commandes contenues dans un bloc PL/SQL
BEGIN [<<nom_bloc>>]
/* instructions SQL et PL/SQL */
[EXCEPTION
/* traitement des exceptions (des erreurs) */ ]
END [nom_bloc] ;
les sections DECLARE et EXCEPTION sont facultatives chaque instruction, de n'importe quelle section est termine par un ; dans la section BEGIN, possibilit de sous-blocs (imbrication de blocs) aucune instruction du LCD n'est autorise ( CREATE, ALTER, DROP TABLE) traitement spcial de l'instruction SELECT
pas de distinction entre maj. et min. pour tre excut, le programme doit tre suivi
une ligne avec un point et une ligne avec une instruction RUN
Variables
pour transmettre des donnes entre un programme PL/SQL et la base de donnes Variables : locales PL/SQL de l'environnement extrieur :
SQL*FORMS, PRO*, SQL*Plus
type PL/SQL :
boolean (valeur true, false ou null),
type du dictionnaire de donnes (type d'un attribut, d'un n-uplet de la base, d'une autre variable)
Variables : dfinition
Dans la partie DECLARE avec la syntaxe: pour des types "simples"
nom_var [CONSTANT] type_var [[NOT NULL] := exp] ;
variable de mme type ou structure que celle d' une colonne d'une table da la base
nom_var table.colonne%TYPE ;
visibilit
dans le bloc o elle a t dclare dans les blocs imbriqus (si non redfinie)
Commande SELECT
syntaxe
SELECT col1, col2 INTO var1, var2 FROM table [] ;
rgle
clause INTO : obligatoire le SELECT doit obligatoirement ramener une seule ligne et une seule, sinon erreur (plusieurs lignes : emploi de curseur)
Traitement conditionnel
Syntaxe : IF condition THEN instructions [ELSE instructions] END IF; IF imbriqus autoriss oprateurs utiliss dans la cd identiques ceux de SQL :
=, <, >, !=, <=, >= IS [NOT] NULL, BETWEEN, LIKE, AND, OR,
DECLARE emploi char(10) ; nom varchar2(15) := 'Miller' ; mes char(30) ; BEGIN select job into emploi from emp where ename = nom ; if emploi is null then mes := nom || ' n''a pas d"emploi' ; elsif emploi = 'Salesman' then update emp set com = 1000 where ename = nom ; mes := nom || ' commission modifie' ; else update emp set com = 0 where ename = nom ; mes := nom || ' pas de commission' ; end if; insert into resultat values (mes) ; commit; END;
Traitements rptitifs
boucle de base : LOOP boucle FOR boucle WHILE
Boucle : LOOP
[ <<label>> ] LOOP instructions; END LOOP [ label ] ; sortie de la boucle par la commande EXIT [ label ] [ WHEN condition ] o label est le nom de la boucle
exemple
DECLARE nbre number(2) := 1 ; BEGIN LOOP insert into resultat values (nbre); nbre := nbre +1 ; exit when nbre > 10 ; END LOOP ; END ;
Boucle : FOR
[ << label >> ] FOR indice IN [ REVERSE ] exp1 .. exp2 LOOP instructions ; END LOOP [ label ] ; Rgles : dclaration implicite de la variable indice exp1, exp2 : constantes, expressions ou variables sans REVERSE : indice varie de exp1 exp2, pas de 1 avec REVERSE : indice varie de exp2 exp1, pas de -1
FOR : exemple
DECLARE fact number := 1 ; BEGIN FOR i IN 1..9 LOOP fact := fact * i ; END LOOP; insert into resultat values( fact, 'factorielle de 9' ) ; END;
Boucle : WHILE
[ << label>> ] WHILE condition LOOP instructions ; END LOOP [ label ] ;
condition : combinaison d'expressions, oprateurs : <, >, =, !=, AND, OR, LIKE,
WHILE : exemple
DECLARE reste number := 7324 ; BEGIN WHILE reste >= 9 LOOP reste := reste - 9 ; END LOOP; insert into resultat values(reste,'reste divison 7324 par 9') ; END;
CURSEUR
Zone de mmoire de taille fixe, utilise par le noyau d'Oracle pour analyser et interprter tout ordre SQL. Les statuts d'excution de l'ordre se trouvent dans le curseur. curseur implicite : cr et gr par Oracle chaque ordre SQL curseur explicite : cr et gr par l'utilisateur afin de pouvoir traiter un SELECT qui retourne plusieurs lignes
Curseur explicite
L'utilisation d'un curseur explicite ncessite 4 tapes : 1. 2. 3. 4. dclaration du curseur ouverture du curseur traitement des lignes fermeture du curseur
Fermeture du curseur
Aprs le traitement des lignes, pour librer la place mmoire. CLOSE nom_curseur ;
DECLARE CURSOR dpt_10 IS SELECT ename, sal FROM emp WHERE deptno=10 order by sal ; nom emp.ename%TYPE ; salaire emp.sal%TYPE ; BEGIN OPEN dpt_10 ; LOOP FETCH dept_10 INTO nom, salaire ; IF salaire > 2500 THEN insert into resultat values (nom, salaire) ; END IF; EXIT WHEN salaire = 5000 ; END LOOP ; CLOSE dpt_10 ; END;
SQL% %FOUND insert, update, delete : 1 ligne traite select into : 1 seule ligne insert, update, delete , select into : 0 ligne false (curseur toujours ferm aprs utilisation)
nom_curseur% dernier FETCH a ramen 1 ligne dernier FETCH n'a pas ramen de ligne true si curseur ouvert nime ligne traite par le FETCH
%NOTFOUND %ISOPEN
%ROWCOUNT insert, update, delete : nombre de lignes traites select into : valeur 0,1ou 2 si 0,1, 1 ligne(s) traite(s)
DECLARE CURSOR c1 IS select ename, sal+NVL(comm,0) saltot FROM emp ; c1_res c1%ROWTYPE ; BEGIN OPEN c1 ; LOOP FETCH c1 INTO c1_rec ; EXIT WHEN c1%NOTFOUND ; IF c1_rec.saltot > 2000 THEN insert into temp values (c1_rec.ename, c1_rec.saltot) ; END IF ; END LOOP ; CLOSE c1 ; END;
Curseur paramtr
Pour utiliser un mme curseur avec des val. diffrentes, dans un mme bloc PL/SQL DECLARE CURSOR nom_c (par1 type, par2 type,) IS ordre_select ; BEGIN OPEN nom_c(val1, val2,) ;
Type : char, number, date, boolean SANS spcifier la longueur. Passage des valeurs des paramtres l'ouverture du curseur.
Exemple : recherche des n plus gros salaire en tenant compte des doublons
DECLARE CURSOR grosal IS select distinct sal from emp order by sal desc ; CURSOR c1(psal number) IS select ename, sal, empno from emp where sal = psal; BEGIN FOR vgrosal IN grosal LOOP EXIT WHEN grosal%rowcount > &Nombre ; -- Nombre est une variable SQL*Plus FOR employe IN c1(vgrosal.sal) LOOP insert into resultat values ( employe.sal, employe.ename || ' de numero : ' || to_char(employe.empno) ) ; END LOOP; END LOOP; END;
CURRENT OF
CURRENT OF permet d'accder directement en modification ou suppression du n-uplet rcupr par FETCH. Il faut au pralable rserver les lignes lors de la dclaration du curseur par un verrou d'intention (SELECT FOR UPDATE [OF nom_colonne,] ).
Exemple : augmenter les employs dont le salaire est suprieur 1500. DECLARE CURSOR c1 IS select ename, sal from emp FOR UPDATE OF sal ; BEGIN FOR c1_rec IN c1 LOOP IF c1_rec.sal > 1500 THEN insert into resultat VALUES (c1_rec.ename, c1_rec.sal * 1.3) ; update emp set sal = sal * 1.3 WHERE CURRENT OF c1 ; END IF; END LOOP; END;
DECLARE pas_comm EXCEPTION ; salaire emp.sal%TYPE ; commi emp.comm%TYPE ; numero emp.empno%TYPE; BEGIN select sal, comm, empno into salaire, commi, numero from emp where empno := :num_emp ; /* num_emp fait rf. une var. extrieure au bloc PL/SQL */ IF commi = 0 or commi is null THEN RAISE pas_comm ; ELSE /* traitement */ END IF ; EXCEPTION WHEN pas_comm THEN insert into resultat values (numero, salaire, 'pas de commission'); END.
Erreur
Oracle : syntaxe
DECLARE nom_erreur EXCEPTION ; PRAGMA EXCEPTION_INIT(nom_erreur, code_erreur); BEGIN ds que l'erreur Oracle est rencontre, passage automatique la section EXCEPTION pour raliser le traitement appropri EXCEPTION WHEN nom_erreur THEN (traitement) ; [WHEN OTHERS THEN (traitement) ;] ; Note : Sortie du bloc aprs excution du traitement. Il existe des erreurs prdfinies pas besoin de les dclarer, ni de les associer un code erreur