Vous êtes sur la page 1sur 12

Programmation PL/SQL

Programmation PL/SQL
G
en
eralit
es
1 / 45

2 / 45

Presentation

Programmation PL/SQL

Programming Language with SQL

Langage de programmation procedural ADA like

Langage proprietaire mais qui a inspire la norme SQL3

Adapte `a la manipulation de bases de donnees relationnelles :


types, requetes, curseurs, traitement des erreurs . . .

Anne-Cecile Caron
Licence MIAGE - Bases de donn
ees

2012-2013

Programmation PL/SQL

Programmation PL/SQL

G
en
eralit
es

Un peu de syntaxe
3 / 45

Utilisation
I

Quelques elements de syntaxe

C
ote Serveur : Definir des objets programmes persistants
I

procedures stockees (packages, procedures et fonctions)


triggers

C
ote Client :
I
I

4 / 45

en SQLPlus, permet decrire des blocs anonymes


Outils de developpement dinterface graphique Developer

PL/SQL nest pas sensible `a la casse (comme SQL)

Les identificateurs comportent des lettres, chires, $, #,

Les commentaires

lettre (lettre | chiffre | $ | # | _ )*


-- ceci est un commentaire monoligne
/* et ceci
est un commentaire multilignes */
I

structure dun bloc anonyme :


declare
-- les declarations de types et variables
begin
-- corps du bloc PL/SQL
exception
-- traitement des exceptions
end ;

Programmation PL/SQL

Programmation PL/SQL

Un peu de syntaxe

Un peu de syntaxe
5 / 45

Declarations de variables et constantes

Declarations de variables et constantes (2)

Les variables peuvent etre dun type


I

scalaire, recevant une seule valeur de type SQL (CHAR, DATE,


NUMBER, VARCHAR2, . . .) ou de type PL/SQL (sous-type
predefini comme INTEGER, ou bien sous-type defini par lutilisateur)

dun type compose (RECORD, collection, types objets)

dun type reference (REF) ou dun type LOB (adresse vers une
donnee externe de tr`es grande taille)

6 / 45

Exemples de declarations :
num NUMBER(4) ;
num2 NUMBER NOT NULL := 3.5 ;
en_stock BOOLEAN := false ;
limite CONSTANT REAL := 5000.00 ;

La syntaxe est

La contrainte NOT NULL doit etre suivie dune clause dinitialisation

Les declarations multiples ne sont pas permises (helas !)


On ne peut donc pas ecrire :

identificateur [CONSTANT] typeDeDonn


ee
[NOT NULL] [(:= | DEFAULT) expression];

v1 , v2 NUMBER ;

Programmation PL/SQL

Programmation PL/SQL

Un peu de syntaxe

Un peu de syntaxe
7 / 45

Declarations de types composes


I

types record. Quand tous les attributs sont dun type SQL, une variable de
type record peut representer une ligne dune table relationnelle.

types collections : TABLE, VARRAY utilises en relationnel objet

types objets : mod`ele relationnel objet

par la suite, nous nutiliserons pas les types issus du relationnel-objet


Type PERSONNE_REC is record(
nom VARCHAR2(15),
prenom VARCHAR2(20)
);
p PERSONNE_REC ; -- champs p.nom, p.prenom

8 / 45

Utilisation de types implicites


attribut %type :
signifie du meme type que
v1
--v2
--

Employee.emp_name%type ;
v1 du m^
eme type que la colonne emp_name
de la table Employee
v1%type ;
v2 du m^
eme type que v1

num NUMBER(5) ;
numbis num%type ;
-- numbis du m^
eme type que num

Programmation PL/SQL

Programmation PL/SQL

Un peu de syntaxe

Un peu de syntaxe
9 / 45

Utilisation de types implicites (2)

10 / 45

Notion de sous-type
I

attribut %rowtype :
signifie du meme type ligne (record) que

emp_rec Employee%rowtype ;
-- emp_rec est de type record
-- ses attributs suivent le sch
ema de Employee

Chaque type de donnees PL/SQL predefini a ses caracteristiques


(domaine, operateurs, ...)
Un sous-type dun type permet den restreindre certaines de ses
caracteristiques.

Il existe des sous-types predefinis en PL/SQL, qui servent `a rendre


les applications compatibles avec la norme SQL (CHARACTER,
INTEGER, POSITIVE, . . .).

Lutilisateur peut definir ses propres sous-types.


SUBTYPE nomSousType IS TypeDeBase[(contrainte)] [NOT NULL];

subtype
subtype
subtype
-- type

Programmation PL/SQL

DAT_NAISS_TYPE is DATE NOT NULL ;


NOMBRE_TYPE is NUMBER(1,0) -- entre -9 et +9
DIPLOME_TYPE is Etudiant.Diplome%type
de la colonne Diplome de la table Etudiant

Programmation PL/SQL

Un peu de syntaxe

Un peu de syntaxe
11 / 45

Conversions de types
Comme en SQL, Oracle autorise des conversions implicites ou explicites.
une_date DATE := 27-11-2007;
une_chaine VARCHAR2(20) := sysdate ;
une_autre_date DATE
:= to_date(10/11/12,DD/MM/YY);

12 / 45

Expressions et operateurs
I

Les operateurs de SQL sont valides en PL/SQL.

Un operande est une variable, une constante, un litteral, ou un appel


de fonction.
Voici lordre des operateurs du plus prioritaire au moins prioritaire :

** (exponentiation)
+ - (op unaires)
* /
+ - ||
< > = <= >= <>
NOT
AND
OR

!=

IS NULL

LIKE

BETWEEN

IN

Programmation PL/SQL

Programmation PL/SQL

Un peu de syntaxe

Int
egrer les requ
etes SQL
13 / 45

Structures de controle

14 / 45

Exploitation des requetes SQL


I

if condition then instr


[elsif condition then instr]
[else instr]
end if ;

for i in [reverse] deb .. fin loop


instr
end loop;
while condition loop
instr
end loop;
loop
instr
exit when condition;
instr
end loop;

Programmation PL/SQL

Les instructions INSERT, DELETE, UPDATE secrivent telles


quelles dans un programme.
Elles peuvent utiliser les variables du programme : il faut donc
donner des noms dierents aux variables du programme et aux
colonnes des tables manipulees par le programme

Pour une requete dont le resultat est constitue dune unique ligne,
on peut utiliser la syntaxe SELECT ... INTO....
select * into emp_rec
from Employee
where emp_no = 12; emp no est la clef

Pour une requete qui ram`ene un nombre quelconque de lignes, il


faut utiliser un curseur.

Pas de possibilite decrire telle quelle une requete DDL (utiliser SQL
dynamique)

Programmation PL/SQL

Int
egrer les requ
etes SQL

Int
egrer les requ
etes SQL
15 / 45

Requetes SQL : exemple 1


declare
nouveauNum NUMBER ;
begin
select nvl(max(emp_no),0)+1 into nouveauNum
from employee ;
insert into employee(emp_no, emp_name,
emp_firstname)
values(nouveauNum, CARON, Anne-C
ecile);
end ;

16 / 45

Requetes SQL : exemple 2


create or replace
procedure ajouterEmp(leNom employee.emp_name%type,
lePrenom employee.emp_firstname%type) is
nouveauNum NUMBER ;
begin
select nvl(max(emp_no),0)+1 into nouveauNum
from employee ;
insert into employee(emp_no, emp_name,
emp_firstname)
values(nouveauNum, leNom, lePrenom);
end ajouterEmp;

Programmation PL/SQL

Programmation PL/SQL

Int
egrer les requ
etes SQL

Int
egrer les requ
etes SQL
17 / 45

Select ... into et exceptions

Les curseurs
I

Les requetes de la forme select ... into ... peuvent declencher des
exceptions
I TOO_MANY_ROWS si le r
esultat de la requete contient plusieurs lignes.
I

18 / 45

NO_DATA_FOUND si le resultat de la requete ne contient aucune ligne.

Si on nest pas s
ur que la requete ram`ene exactement 1 ligne, utiliser un
curseur.

Un curseur est une structure de donnee sequentielle avec une


position courante
Un curseur est utilise pour parcourir le resultat dune requete SQL
dans un programme PL/SQL.
Quelque fois, PL/SQL declare implicitement un curseur
I

Programmation PL/SQL

pour les instructions du DML qui modifient la base (INSERT,


DELETE, UPDATE)
pour les requetes de la forme SELECT INTO.

Programmation PL/SQL

Int
egrer les requ
etes SQL

Int
egrer les requ
etes SQL
19 / 45

Declaration dun curseur


I

CURSOR nom_curseur IS une_requ^


ete ;

On peut definir des param`etres en entree utilises dans la requete


CURSOR nom_curseur(p1, ..., pn) IS une_requ^
ete ;

20 / 45

Manipulation dun curseur


I

I
I

Si c est un curseur, le type dune ligne est c%rowtype.

cursor emp_cursor(dnum NUMBER) is


select salary, comm
from Employee
where deptno = dnum ;

Instructions :

I
I

OPEN : initialise le curseur


FETCH : extrait la ligne courante et passe `
a la suivante (pas
dexception si plus de ligne)
CLOSE : invalide le curseur
Si on veut parcourir toutes les lignes : boucle FOR

Attributs du curseur :
I
I
I
I

%found vrai si le dernier fetch a ramene une ligne


%notfound vrai si le dernier fetch na pas ramene de ligne
%isopen vrai ssi le curseur est ouvert
%rowcount le nombre de lignes dej`
a ramenees

Programmation PL/SQL

Programmation PL/SQL

Int
egrer les requ
etes SQL

Int
egrer les requ
etes SQL
21 / 45

Requetes SQL : exemple avec curseur

22 / 45

Requetes SQL : exemple avec curseur (2)


Lexemple precedent peut secrire :

declare
cursor c_proj is
select proj_name, proj_budget
from project
order by proj_budget ;

declare
cursor c_proj is
select proj_name, proj_budget
from project
order by proj_budget ;

proj_rec c_proj%rowtype ;
begin
open c_proj ;
loop -- parcours des lignes du curseur
fetch c_proj into proj_rec ;
exit when c_proj%notfound ;
... on utilise la ligne courante rang
ee dans proj_rec ...
end loop ;
close c_proj ;
end ;

begin
for proj_rec in c_proj loop -- parcours des lignes du curseur
... on utilise la ligne courante rang
ee dans proj_rec ...
end loop ;
end ;

Programmation PL/SQL

Programmation PL/SQL

Int
egrer les requ
etes SQL

Int
egrer les requ
etes SQL
23 / 45

Utilisation dun curseur avec param`etre(s)


Reprenons lexemple du curseurs emp_cursor declare precedemment.
Lors de son utilisation, il faut instancier le param`etre formel dnum.

24 / 45

Curseurs implicites
I

open emp_cursor(56) ;
fetch emp_cursor into emp_cursor_rec ;
...
close emp_cursor ;

Avec un curseur implicite, on peut obtenir des informations sur la


requete realisee, grace aux attributs : SQL%attribut applique
lattribut sur la derni`ere instruction SQL executee.
I

ou bien :

SQL%rowcount : nombre de lignes aectees par la derni`ere


instruction.
SQL%found : TRUE si la derni`ere instruction aecte au moins 1
ligne.
SQL%notfound : TRUE si la derni`ere instruction naecte aucune
ligne.

delete from Employee where ...


if SQL%rowcount > 10 then
-- on a supprim
e plus de 10 lignes
...
end if ;

for emp_cursor_rec in emp_cursor(56) loop


...
end loop ;
I

Si une requete declenche une exception, il ne faut pas se fier aux


valeurs retournees par les attributs.

Programmation PL/SQL

Programmation PL/SQL

Gestion des erreurs

Gestion des erreurs


25 / 45

Les Exceptions

Les Exceptions et les codes derreur

En PL/SQL, la gestion des erreurs se fait grace aux exceptions.

il existe de nombreuses exceptions predefinies (dans le package


STANDARD)

Le programmeur peut aussi definir de nouvelles exceptions

Le programmeur peut explicitement declencher une exception


(raise)
Le programmeur peut traiter des exceptions.

26 / 45

Programmation PL/SQL

PL/SQL a defini des exceptions pour certaines erreurs Oracle. Par


exemple
exception TOO_MANY_ROWS
= erreur Oracle ORA-01422 (code erreur -1422)

Pour lier une exception `a un code derreur SQL :


PRAGMA EXCEPTION_INIT(nom_exception, code_erreur);

Programmation PL/SQL

Gestion des erreurs

Gestion des erreurs


27 / 45

Declenchement dexception
I
I
I

Traitement dexception

Une erreur `a lexecution declenche une exception (par exemple une


division par 0 declenche lexception ZERO_DIVIDE)
Dans un programme, on declenche explicitement une exception
grace `a linstruction raise nom_exception
Pour declencher une erreur qui nest pas liee `a une exception, utiliser
linstruction :
raise_application_error(num_erreur, message);
I

num_erreur est un entier negatif compris entre


(codes reserves aux erreurs de lutilisateur)
message est une chaine de caract`eres.

28 / 45

20999 et

20000

Dans un bloc PL/SQL, il peut y avoir une partie traitement dexception :


EXCEPTION
WHEN exception_1 THEN
-- on traite lexception_1
WHEN exception_2 THEN
-- on traite lexception_2
...
WHEN OTHERS THEN -- optionnel
-- on traite toutes les exceptions
-- et erreurs non trait
ees auparavant
END;

Programmation PL/SQL

Programmation PL/SQL

Gestion des erreurs

Gestion des erreurs


29 / 45

Traitement dexception (2)


I
I
I

Exemple (doc Oracle)

Le WHEN OTHERS permet de traiter les erreurs (non liees `a des noms
dexception)
Lorsquune exception est declenchee, le deroulement du programme
est interrompu et le traitement dexception est execute.
Sil ny a pas de traitement pour une exception donnee,
I

30 / 45

DECLARE
pe_ratio NUMBER(3,1);
BEGIN
SELECT price / earnings INTO pe_ratio
FROM stocks
WHERE symbol = XYZ;
-- might cause division-by-zero error
INSERT INTO stats (symbol, ratio)
VALUES (XYZ, pe_ratio);
EXCEPTION -- exception handlers begin
WHEN ZERO_DIVIDE THEN
INSERT INTO stats (symbol, ratio)
VALUES (XYZ, NULL);
END;

lexception remonte au programme appelant, sil existe


sinon, la transaction est annulee (rollback)

On peut redeclencher lexception que lon a attrape avec


linstruction raise;

Programmation PL/SQL

Programmation PL/SQL

Gestion des erreurs

Gestion des erreurs


31 / 45

Exemple (2)
On suppose quil existe une table COMPAGNIE et une table PILOTE avec une
contrainte de clef etrang`ere entre les deux (un pilote appartient `
a une
compagnie)
Lorsquon veut supprimer une compagnie qui a encore des pilotes :
ORA-02292 enregistrement fils existant.
create procedure detruitCompagnie...
restePilote EXCEPTION ;
PRAGMA Exception_init(restePilote, -2292);
begin
delete from compagnie where comp = MaCompagnie ;
...
exception
when restePilote then
... traitement de lerreur ...
end ;

32 / 45

Exemple (3)
Version o`
u lon traite le cas o`
u il ny a pas de ligne eacee.
create procedure detruitCompagnie(ma_comp VARCHAR2) is
restePilote EXCEPTION ;
PRAGMA Exception_init(restePilote, -2292);
compagnieInexistante EXCEPTION ;
begin
delete from compagnie where comp = ma_comp ;
if SQL%NOTFOUND then
raise compagnieInexistante ;
end if ;
exception
when restePilote then
... traitement de lerreur ...
when compagnieInexistante then
...
when others then
... on traite les autres erreurs
end ;

Programmation PL/SQL

Programmation PL/SQL

Modules stock
es

Proc
edures et fonctions
33 / 45

Les modules stockes


I

Un module stocke est un programme range dans la base de donnees

Ces programmes peuvent etre appeles par les programmes clients, et


sont executes par le serveur.

Avec Oracle, lutilisateur peut definir des procedures, des fonctions


ou des paquetages stockes.

Langage de programmation : PL/SQL pour Oracle, langage proche


defini dans SQL3.

34 / 45

Procedures et fonctions Syntaxe


create or replace
procedure <p_name> [ <les_parametres> ] is
<declarations>
begin
<code PL/SQL>
end [<p_name>];
create or replace
function <f_name> [ <les_parametres> ]
return <datatype> is
<declarations>
begin
<code PL/SQL>
end [<f_name>];
Sous JDeveloper, on ne precise pas le create or replace

Programmation PL/SQL

Programmation PL/SQL

Proc
edures et fonctions

Proc
edures et fonctions
35 / 45

Les param`etres
I

Pour declarer un param`etre, la syntaxe est

<nom_param> [mode] <datatype>


[ := <valeur_defaut> ]
Pour une procedure, il y a trois modes de passage de param`etre
I
I
I

les param`etres IN : en entree (par defaut)


les param`etres OUT : en sortie
les param`etres IN OUT : en entree et sortie

Tous les param`etres dune fonction sont en mode IN (dans ce cas,


on nest pas oblige decrire le mode).

36 / 45

Exemple
create or replace function nom_dept(numero dept.dept_no%type)
return VARCHAR2 is
nom dept.dept_name%type ;
begin
select dept_name into nom from dept
where dept_no = numero ;
return nom ;
end ;
select nom_dept(1) from dual ; -- possible car pas de modif de la base
NOM_DEPT(1)
---------------------------info

Programmation PL/SQL

Programmation PL/SQL

Proc
edures et fonctions

Proc
edures et fonctions
37 / 45

Exemple (2)

38 / 45

Exemple (3)
Sous SQLPlus, on peut aussi utiliser des variables globales, et
linstruction execute :

create or replace procedure nom_dept2(numero IN dept.dept_no%type,


nom OUT dept.dept_name%type) is
begin
select dept_name into nom
from dept
where dept_no = numero ;
end ;

VARIABLE le_nom VARCHAR2(20);


execute nom_dept2(1,:le_nom);
print le_nom ;
VARIABLE le_dept NUMBER(3) ;

declare
leNom VARCHAR2(100) ;
begin
nom_dept2(1,leNom) ; -- appel de la procedure
dbms_output.put_line(leNom) ;
end ;

begin
:le_dept := 4 ;
nom_dept2(:le_dept,:le_nom);
end ;
/
print le_nom ;

sous SQLPlus, activer laffichage par SET SERVEROUTPUT ON

Sous SQLPlus, la d
efinition dun programme PLSQL est suivie de / `
a la ligne suivante
(directive dex
ecution de linstruction donc de compilation du programme PLSQL)

Programmation PL/SQL

Programmation PL/SQL

Proc
edures et fonctions

Les paquetages
39 / 45

Erreurs de compilation
I
I

Evidemment, jdeveloper permet de voir rapidement les erreurs de


compilation, et de les corriger.
Si le programme ne compile pas, show errors permet de voir les
erreurs sous SQLPlus (dans le cas peu probable o`
u vous feriez de la
programmation sans jdeveloper).
Certaines vues du dictionnaire donnent des informations sur ces
objets
I

I
I

la vue USER_OBJECTS donne tous les objets et en particulier les


programmes stockes.
la vue USER_SOURCE donne acc`es aux sources des programmes
la vue USER_ERRORS donne acc`es aux erreurs de compilation.

40 / 45

Les paquetages
I

Un paquetage est constitue dune specification (la partie visible) et dun


corps (limplementation)

La specification du paquetage contient des elements que lon rend


accessibles `
a tous les utilisateurs du paquetage.

Le corps du paquetage contient limplementation et ce que lon veut


cacher.

Au niveau des droits, on donne le droit dexecuter un paquetage : on a


alors acc`es `
a toute la specification, pas au corps.

Il faut mettre le minimum de choses dans la specification (penser `


a
lencapsulation)

La surcharge est autorisee, i.e. on peut avoir plusieurs procedures ou


fonctions de meme nom, avec des signatures dierentes.

Chaque session qui utilise le paquetage poss`ede 1 instance du paquetage


(il ny a donc pas partage des variables)

Programmation PL/SQL

Programmation PL/SQL

Les paquetages

Les paquetages
41 / 45

La specification

42 / 45

Le corps

Elle contient :

Il contient :

des signatures de procedures et fonctions,

Les corps des procedures et fonctions de la specification (obligatoire)

des constantes et des variables

Dautres procedures et fonctions (cachees)

des definitions dexceptions

Des declarations que lon veut rendre privees

des definitions de curseurs

Un bloc dinitialisation du paquetage si necessaire.

Programmation PL/SQL

Programmation PL/SQL

Les paquetages

Les paquetages
43 / 45

Exemple (1)
create or replace package Paq_Commerce as
procedure ajout_produit(le_nom produit.nom%type,
le_prix produit.prix_unitaire%type) ;
procedure suppression_produit(le_num produit.num_produit%type);
procedure ajout_produit_commande(le_num_cmde commande.num_commande%type,
le_num_produit produit.num_produit%type,
la_qte contient.quantite%type);
PRODUIT_INCONNU EXCEPTION ;
PRAGMA exception_init(PRODUIT_INCONNU,-20100);
PRODUIT_UTILISE EXCEPTION ;
PRAGMA exception_init(PRODUIT_UTILISE,-20101);
end Paq_Commerce;

44 / 45

Exemple (2)
create or replace package body Paq_Commerce as
...
procedure ajout_produit_commande(le_num_cmde commande.num_commande%type,
le_num_produit produit.num_produit%type,
la_qte contient.quantite%type) is
ancienne_qte contient.quantite%type ;
begin
select quantite into ancienne_qte from contient
where num_commande = le_num_cmde and num_produit = le_num_produit ;
-- il y a d
ej`
a une ligne pour cette commande et ce produit
update contient set quantite = quantite + la_qte
where num_commande = le_num_cmde and num_produit = le_num_produit ;
exception
when NO_DATA_FOUND then -- creer une nouvelle ligne
insert into contient(num_commande, num_produit, quantite)
values(le_num_cmde, le_num_produit, la_qte);
end ajout_produit_commande ;
end Paq_Commerce;

Programmation PL/SQL
Les paquetages
45 / 45

Exemple (3)
Sous SQLPlus :
execute paq_commerce.ajout_produit_commande(3,1,2);
-- ok
execute paq_commerce.suppression_produit(25);
ERREUR `
a la ligne 1 :
ORA-20100:
ORA-06512: `
a "CARON.PAQ_COMMERCE", ligne 16
ORA-06512: `
a ligne 1