Vous êtes sur la page 1sur 13

‰ Avertissement : cette partie du cours n’est

qu’un survol du langage PL/SQL, utile pour


écrire des procédures stockées simples
PL/SQL ‰ Elle laisse de côté de nombreuses
fonctionnalités du langage
Université de Nice Sophia-Antipolis
Version 0.6.3 – 3/12/06
Richard Grin

R. Grin PL/SQL page 2

Pourquoi PL/SQL ?
‰ SQL est un langage non procédural
‰ Les traitements complexes sont parfois
difficiles à écrire si on ne peut utiliser des
Introduction variables et les structures de programmation
comme les boucles et les alternatives
‰ On ressent vite le besoin d’un langage
procédural pour lier plusieurs requêtes SQL
avec des variables et dans les structures de
programmation habituelles

R. Grin PL/SQL page 3 R. Grin PL/SQL page 4

Principales caractéristiques de PL/SQL Utilisation de PL/SQL


‰ Extension de SQL : des requêtes SQL ‰ PL/SQL peut être utilisé pour l’écriture des
cohabitent avec les structures de contrôle procédures stockées et des triggers (Oracle
habituelles de la programmation structurée accepte aussi le langage Java)
(blocs, alternatives, boucles)
‰ Il convient aussi pour écrire des fonctions
‰ La syntaxe ressemble au langage Ada
utilisateurs qui peuvent être utilisées dans les
‰ Un programme est constitué de procédures requêtes SQL (en plus des fonctions
et de fonctions prédéfinies)
‰ Des variables permettent l’échange ‰ Il est aussi utilisé dans des outils Oracle,
d’information entre les requêtes SQL et le Forms et Report en particulier
reste du programme
R. Grin PL/SQL page 5 R. Grin PL/SQL page 6

1
Normalisation du langage
‰ PL/SQL est un langage propriétaire de Oracle
‰ PostgreSQL utilise un langage très proche
‰ Ressemble au langage normalisé PSM
(Persistant Stored Modules) Structure d’un programme
‰ Tous les langages L4G des différents SGBDs se
ressemblent

R. Grin PL/SQL page 7 R. Grin PL/SQL page 8

Blocs Structure d’un bloc


‰ Un programme est structuré en blocs DECLARE
d’instructions de 3 types : -- définitions de variables
n procédures anonymes BEGIN
n procédures nommées -- Les instructions à exécuter
n fonctions nommées EXCEPTION
‰ Un bloc peut contenir d’autres blocs -- La récupération des erreurs
END; Les blocs, comme les
instructions, se terminent
Seuls BEGIN et END
par un « ; »
sont obligatoires
R. Grin PL/SQL page 9 R. Grin PL/SQL page 10

Variables
‰ Identificateurs Oracle :
n 30 caractères au plus

n commence par une lettre


Les variables n peut contenir lettres, chiffres, _, $ et #

‰ Pas sensible à la casse


‰ Portée habituelle des langages à blocs
‰ Doivent être déclarées avant d’être utilisées

R. Grin PL/SQL page 11 R. Grin PL/SQL page 12

2
Commentaires Types de variables
‰ -- Pour une fin de ligne ‰ Les types habituels correspondants aux types
‰ /* Pour plusieurs SQL2 ou Oracle : integer, varchar,…
lignes */ ‰ Types composites adaptés à la récupération
des colonnes et lignes des tables SQL :
%TYPE, %ROWTYPE
‰ Type référence : REF

R. Grin PL/SQL page 13 R. Grin PL/SQL page 14

Déclaration d’une variable Déclaration %TYPE


‰ identificateur [CONSTANT] type [:= valeur]; ‰ On peut déclarer qu’une variable est du
‰ Exemples : même type qu’une colonne d’une table ou
n age integer;
d’une vue (ou qu’une autre variable) :
nom emp.nome.%TYPE;
n nom varchar(30);

n dateNaissance date;

n ok boolean := true;

‰ Déclarations multiples interdites :


i, j integer;

R. Grin PL/SQL page 15 R. Grin PL/SQL page 16

Déclaration %ROWTYPE Exemple d’utilisation


employe emp%ROWTYPE;
‰ Une variable peut contenir toutes les
nom emp.nome.%TYPE;
colonnes d’une ligne d’une table
select * INTO employe
‰ employe emp%ROWTYPE; from emp
déclare que la variable employe contiendra where matr = 900;
une ligne de la table emp nom := employe.nome;
employe.dept := 20;

insert into emp
values employe;

R. Grin PL/SQL page 17 R. Grin PL/SQL page 18

3
Type RECORD Utilisation du type RECORD
‰ Equivalent à struct du langage C TYPE emp2 IS RECORD (
‰ TYPE nomRecord IS RECORD ( matr integer,
champ1 type1, nom varchar(30));
champ2 type2, employe emp2;
…); employe.matr := 500;

R. Grin PL/SQL page 19 R. Grin PL/SQL page 20

Affectation Conflits de noms


‰ Plusieurs façons de donner une valeur à une
variable : ‰ Si une variable porte le même nom qu’une
colonne d’une table, c’est la colonne qui
n :=
l’emporte
n par la directive INTO de la requête
‰ DECLARE
SELECT
nome varchar(30) := 'DUPOND';
‰ Exemples : BEGIN
n dateNaissance := ’10/10/2004’; delete from emp where nome = nome;
n select nome INTO nom ‰ Pour éviter ça, le plus simple est de ne pas
from emp donner de nom de colonne à une variable !
where matr = 509;
R. Grin PL/SQL page 21 R. Grin PL/SQL page 22

Alternative
‰ IF condition THEN ‰ IF condition1 THEN
instructions; instructions1;
END IF; ELSEIF condition2 THEN
Structures de contrôle ‰ IF condition THEN instructions2;
instructions1; ELSEIF …
ELSE …
instructions2; ELSE
END IF; instructionsN;
END IF;

R. Grin PL/SQL page 23 R. Grin PL/SQL page 24

4
Choix Boucle « tant que »
‰ CASE expression ‰ WHILE condition LOOP
WHEN expr1 THEN instructions1; instructions;
WHEN expr2 THEN instructions2; END LOOP;

ELSE instructionsN;
END CASE;
‰ expression peut avoir n’importe quel type
simple (ne peut pas par exemple être un
RECORD)

R. Grin PL/SQL page 25 R. Grin PL/SQL page 26

Boucle générale Boucle « pour »


‰ LOOP ‰ FOR compteur IN [REVERSE] inf..sup LOOP
instructions; instructions;
EXIT [WHEN condition]; END LOOP;
instructions; ‰ Exemple :
END LOOP; for i IN 1..100 LOOP
somme := somme + i;
end loop;

R. Grin PL/SQL page 27 R. Grin PL/SQL page 28

Mise au point Exemple


set serveroutput on -- sous SQLPLUS
‰ Pour la mise au point il est utile de faire
declare
afficher les valeurs des variables
nb integer;
‰ On peut le faire en activant sous SQL*PLUS
la sortie sur l’écran et en utilisant le begin
paquetage DBMS_OUTPUT delete from emp
‰ Un paquetage est un regroupement de where matr in (600, 610);
procédures et de fonctions ; notion pas vue nb := sql%rowcount; -- curseur sql
dans ce cours dbms_output.put_line('nb = ' || nb);
end;

R. Grin PL/SQL page 29 R. Grin PL/SQL page 30

5
Extraire des données
‰ select expr1, expr2,… into var1, var2,…
met des valeurs de la BD dans une ou
plusieurs variables
Interactions simples avec la base ‰ Le select ne doit renvoyer qu’une seule ligne
‰ Avec Oracle il n’est pas possible d’inclure un
select sans « into » dans une procédure ;
pour ramener des lignes, voir la suite du
cours sur les curseurs

R. Grin PL/SQL page 31 R. Grin PL/SQL page 32

Extraire des données – erreurs Exemple


‰ Si le select renvoie plus d’une ligne, une DECLARE
exception « TOO_MANY_ROWS » (ORA-01422) v_nom emp.nome%TYPE;
est levée (voir exceptions plus loin dans ce v_emp emp%ROWTYPE;
support de cours) BEGIN
select nome into v_nom
‰ Si le select ne renvoie aucune ligne, une
from emp
exception « NO_DATA_FOUND » (ORA-01403) where matr = 500;
est levée select * into v_emp
from emp
where matr = 500;

R. Grin PL/SQL page 33 R. Grin PL/SQL page 34

Modification de données Insertions


DECLARE
‰ Les requêtes SQL (insert, update, delete,…) v_emp emp%ROWTYPE;
peuvent utiliser les variables PL/SQL v_nom emp.nome%TYPE;
BEGIN
‰ Les commit et rollback doivent être explicites ;
v_nom := 'Dupond';
aucun n’est effectué automatiquement à la insert into emp (matr, nome)
sortie d’un bloc values(600, v_nom);
‰ Voyons plus de détails pour l’insertion de v_emp.matr := 610;
v_emp.nome := 'Durand';
données
insert into emp (matr, nome)
values(v_emp.matr, v_emp.nome);
commit;
END;

R. Grin PL/SQL page 35 R. Grin PL/SQL page 36

6
Autre exemple
declare
v_emp emp%rowtype;
begin
select * into v_emp from emp
where nome = 'LEROY';
Curseurs
v_emp.matr := v_emp.matr + 5;
v_emp.nome := 'Toto';
insert into emp
values v_emp;
end;

R. Grin PL/SQL page 37 R. Grin PL/SQL page 38

Fonctionnalités Attributs des curseurs


‰ Tous les curseurs ont des attributs que
‰ Toutes les requêtes SQL sont associées à un l’utilisateur peut utiliser
curseur n %ROWCOUNT : nombre de lignes traitées
‰ Ce curseur représente la zone mémoire par le curseur
utilisée pour parser et exécuter la requête n %FOUND : vrai si au moins une ligne a été

‰ Le curseur peut être implicite (pas déclaré traitée par la requête ou le dernier fetch
par l’utilisateur) ou explicite n %NOTFOUND : vrai si aucune ligne n’a

‰ Les curseurs explicites servent à retourner


été traitée par la requête ou le dernier fetch
n %ISOPEN : vrai si le curseur est ouvert
plusieurs lignes avec un select
(utile seulement pour les curseurs
explicites)
R. Grin PL/SQL page 39 R. Grin PL/SQL page 40

Curseur implicite Exemple de curseur implicite


DECLARE
‰ Les curseurs implicites sont tous nommés
nb_lignes integer;
SQL
BEGIN
delete from emp
where dept = 10;
nb_lignes := SQL%ROWCOUNT;
. . .

R. Grin PL/SQL page 41 R. Grin PL/SQL page 42

7
Curseur explicite Exemple (déclaration)
‰ Pour traiter les select qui renvoient plusieurs DECLARE
lignes CURSOR salaires IS
‰ Ils doivent être déclarés select sal
from emp
‰ Le code doit les utiliser explicitement avec les
where dept = 10;
ordres OPEN, FETCH et CLOSE
salaire numeric(8, 2);
‰ Le plus souvent on les utilise dans une
total numeric(10, 2) := 0;
boucle dont on sort quand l’attribut
NOTFOUND du curseur est vrai

R. Grin PL/SQL page 43 R. Grin PL/SQL page 44

Exemple (corps du bloc)


BEGIN
Type « row » associé à un curseur
open salaires;
loop Attention ! ‰ On peut déclarer un type « row » associé à un
fetch salaires into salaire; curseur
exit when salaires%notfound; ‰ Exemple :
if salaire is not null then declare
total := total + salaire; cursor c is
DBMS_OUTPUT.put_line(total); select matr, nome, sal from emp;
end if; employe c%ROWTYPE;
end loop; begin
open c;
close salaires; -- Ne pas oublier
fetch c into employe;
DBMS_OUTPUT.put_line(total); if employe.sal is null then …
END;
R. Grin PL/SQL page 45 R. Grin PL/SQL page 46

Boucle FOR pour un curseur Exemple


declare
‰ Elle simplifie la programmation car elle évite
cursor c is
d’utiliser explicitement les instruction open,
select dept, nome from emp
fetch, close
where dept = 10;
‰ En plus elle déclare implicitement une
begin
variable de type « row » associée au curseur FOR employe IN c LOOP
dbms_output.put_line(employe.nome);
END LOOP;
end;
Variable de type
c%rowtype
R. Grin PL/SQL page 47 R. Grin PL/SQL page 48

8
Curseur paramétré Exemple
declare
‰ Un curseur paramétré peut servir plusieurs cursor c(p_dept integer) is
fois avec des valeurs des paramètres select dept, nome from emp
différentes where dept = p_dept;
begin
‰ On doit fermer le curseur entre chaque for employe in c(10) loop
utilisation de paramètres différents (sauf si on dbms_output.put_line(employe.nome);
utilise « for » qui ferme automatiquement le end loop;
curseur)
for employe in c(20) loop
dbms_output.put_line(employe.nome);
end loop;
end;
R. Grin PL/SQL page 49 R. Grin PL/SQL page 50

Ligne courante d’un curseur FOR UPDATE


‰ La ligne courante d’un curseur est déplacée à ‰ FOR UPDATE [OF col1, col2,…]
chaque appel de l’instruction fetch
‰ On est parfois amené à modifier la ligne
‰ Cette clause bloque toute la ligne ou
courante pendant le parcours du curseur seulement les colonnes spécifiées
‰ Pour cela on peut utiliser la clause « where ‰ Les autres transactions ne pourront modifier
current of » pour désigner cette ligne les valeurs tant que le curseur n’aura pas
courante dans un ordre LMD (insert, update, quitté cette ligne
delete)
‰ Il est nécessaire d’avoir déclaré le curseur
avec la clause FOR UPDATE pour que le bloc
compile
R. Grin PL/SQL page 51 R. Grin PL/SQL page 52

Exemple Fonction qui renvoie un curseur


sous Oracle
DECLARE
CURSOR c IS
select matr, nome, sal
from emp ‰ Question : comment écrire une fonction (ou
where dept = 10 une procédure) qui renvoie un curseur ?
FOR UPDATE OF emp.sal; 1. Créer un type pour la référence de curseur
… qu’on va renvoyer
if salaire is not null then
2. Créer la fonction qui renvoie la référence de
total := total + salaire;
else -- met 0 à la place de null
curseur
update emp set sal = 0 ‰ Attention, solution propriétaire d’Oracle !
where current of c;
end if;
R. Grin PL/SQL page 53 R. Grin PL/SQL page 54

9
Créer le type référence de curseur Créer la fonction
create or replace
‰ Pour utiliser ensuite le type, il faut le créer dans function listdept(num integer)
un paquetage : return Types.curseur_type
create or replace package Types AS is
type curseur_type is ref cursor;
empcurseur Types.curseur_type;
end Types;
begin
open empcurseur for
select dept, nomE
from emp where dept = num;
return empcurseur;
end;

R. Grin PL/SQL page 55 R. Grin PL/SQL page 56

Utiliser la fonction dans JDBC


CallableStatement cstmt =
conn.prepareCall("{ ? = call list(?) }");
cstmt.setInt(2, 10);
cstmt.registerOutParameter(1,
Exceptions
OracleTypes.CURSOR);
cstmt.execute(); Ne marche que sous Oracle !
ResultSet rs =
((OracleCallableStatement)cstmt)
.getCursor(1);
while (rs.next()) {
System.out.println(rs.getString("nomE")
+ ";" + rs.getInt("dept"));
}
R. Grin PL/SQL page 57 R. Grin PL/SQL page 58

Présentation Rappel de la structure d’un bloc


‰ Une exception est une erreur qui survient DECLARE
durant une exécution -- définitions de variables
‰ 2 types d’exception :
BEGIN
n prédéfinie par Oracle
-- Les instructions à exécuter
n définie par le programmeur
EXCEPTION
-- La récupération des erreurs
END;

R. Grin PL/SQL page 59 R. Grin PL/SQL page 60

10
Saisir une exception Exceptions prédéfinies
‰ Une exception ne provoque pas ‰ NO_DATA_FOUND
nécessairement l’arrêt du programme si elle ‰ TOO_MANY_ROWS
est saisie par un bloc (dans la partie
‰ VALUE_ERROR (erreur arithmétique)
« EXCEPTION »)
‰ ZERO_DIVIDE
‰ Une exception non saisie remonte dans la
procédure appelante (où elle peut être saisie) ‰ …

R. Grin PL/SQL page 61 R. Grin PL/SQL page 62

Traitement des exceptions Exceptions utilisateur


BEGIN On peut utiliser les 2 variables
prédéfinies SQLCODE et SQLERRM ‰ Elles doivent être déclarées avec le type
… EXCEPTION
EXCEPTION
‰ On les lève avec l’instruction RAISE
WHEN NO_DATA_FOUND THEN
. . .
WHEN TOO_MANY_ROWS THEN
. . .
WHEN OTHERS THEN -- optionnel
. . .
END;
R. Grin PL/SQL page 63 R. Grin PL/SQL page 64

Exemple
DECLARE
salaire numeric(8,2);
salaire_trop_bas EXCEPTION;
BEGIN
select sal into salaire from emp
where matr = 50;
if salaire < 300 then Procédures et fonctions
raise salaire_trop_bas;
end if;
-- suite du bloc
EXCEPTION
WHEN salaire_trop_bas THEN . . .;
WHEN OTHERS THEN
dbms_output.put_line(SQLERRM);
END;
R. Grin PL/SQL page 65 R. Grin PL/SQL page 66

11
Bloc anonyme ou nommé Création d’une procédure
‰ create or replace
‰ Un bloc anonyme PL/SQL est un bloc PROCEDURE(<liste params>) IS
« DECLARE – BEGIN – END » comme dans -- déclaration des variables
les exemples précédents BEGIN
‰ Dans SQL*PLUS on peut exécuter -- code de la procédure
directement un bloc PL/SQL anonyme en END;
tapant sa définition ‰ Pas de DECLARE ; les variables sont
‰ Le plus souvent, on crée plutôt une déclarées entre IS et BEGIN
procédure ou une fonction nommée pour ‰ Si la procédure ne nécessite aucune
réutiliser le code déclaration, le code est précédé de « IS
BEGIN »
R. Grin PL/SQL page 67 R. Grin PL/SQL page 68

Création d’une fonction Passage des paramètres


‰ Dans la définition d’une procédure on indique
‰ create or replace le type de passage que l’on veut pour les
FUNCTION(<liste params>) paramètres :
RETURN <type retour> IS n IN pour le passage par valeur
-- déclaration des variables
n IN OUT pour le passage par référence
BEGIN
n OUT pour le passage par référence mais
-- code de la procédure
END; pour un paramètre dont la valeur n’est pas
utilisée en entrée
‰ Pour les fonctions, seul le passage par valeur
(IN) est autorisé

R. Grin PL/SQL page 69 R. Grin PL/SQL page 70

Compilation Utilisation des procédures et fonctions


‰ Sous SQL*PLUS, il faut taper une dernière ‰ Les procédures et fonctions peuvent être
ligne contenant « / » pour compiler une utilisées dans d’autres procédures ou
procédure ou une fonction fonctions ou dans des blocs PL/SQL
anonymes

R. Grin PL/SQL page 71 R. Grin PL/SQL page 72

12
Fonctions Exemple de fonction
‰ Les fonctions peuvent aussi être utilisées create or replace
dans les requêtes SQL function euro_to_fr(somme IN number)
RETURN number IS
taux constant number := 6.55957;
begin
return somme * taux;
end;

R. Grin PL/SQL page 73 R. Grin PL/SQL page 74

Utilisation dans un bloc anonyme Utilisation dans une requête SQL


declare
cursor c(p_dept integer) is select nome, sal, euro_to_fr(sal)
select dept, nome, sal from emp from emp;
where dept = p_dept;
begin
for employe in c(10) loop
dbms_output.put_line(employe.nome
|| ' gagne '
|| euro_to_fr(employe.sal)
|| ' francs');
end loop;
end;
R. Grin PL/SQL page 75 R. Grin PL/SQL page 76

Exécution d’une procédure Bibliographie


‰ Sous SQL*PLUS on exécute une procédure ‰ Pour cette introduction rapide je me suis
PL/SQL avec la commande EXECUTE : inspiré du livre suivant :
EXECUTE nomProcédure(param1, …); SQL pour Oracle de Soutou et Teste
(Eyrolles)

R. Grin PL/SQL page 77 R. Grin PL/SQL page 78

13

Vous aimerez peut-être aussi