Vous êtes sur la page 1sur 79

Introduction au PL/SQL Oracle

Alexandre Mesle
17 octobre 2011

Table des mati`


eres
1 Notes de cours
1.1 Introduction au PL/SQL . . . . . . . . . . . . . . . . .
1.1.1 PL/SQL . . . . . . . . . . . . . . . . . . . . . .
1.1.2 Blocs . . . . . . . . . . . . . . . . . . . . . . .
1.1.3 Affichage . . . . . . . . . . . . . . . . . . . . .
1.1.4 Variables . . . . . . . . . . . . . . . . . . . . .
1.1.5 Traitements conditionnels . . . . . . . . . . . .
1.1.6 Traitements repetitifs . . . . . . . . . . . . . .
1.2 Tableaux et structures . . . . . . . . . . . . . . . . . .
1.2.1 Tableaux . . . . . . . . . . . . . . . . . . . . .
1.2.2 Structures . . . . . . . . . . . . . . . . . . . . .
1.3 Utilisation du PL/SQL . . . . . . . . . . . . . . . . . .
1.3.1 Affectation . . . . . . . . . . . . . . . . . . . .
1.3.2 Tables et structures . . . . . . . . . . . . . . .
1.3.3 Transactions . . . . . . . . . . . . . . . . . . .
1.4 Exceptions . . . . . . . . . . . . . . . . . . . . . . . .
1.4.1 Rattraper une exception . . . . . . . . . . . . .
1.4.2 Exceptions predefinies . . . . . . . . . . . . . .
1.4.3 Codes derreur . . . . . . . . . . . . . . . . . .
1.4.4 Declarer et lancer ses propres exceptions . . . .
1.5 Sous-programmes . . . . . . . . . . . . . . . . . . . . .
1.5.1 Procedures . . . . . . . . . . . . . . . . . . . .
1.5.2 Fonctions . . . . . . . . . . . . . . . . . . . . .
1.6 Curseurs . . . . . . . . . . . . . . . . . . . . . . . . . .
1.6.1 Introduction . . . . . . . . . . . . . . . . . . .
1.6.2 Les curseurs . . . . . . . . . . . . . . . . . . . .
1.7 Curseurs parametres . . . . . . . . . . . . . . . . . . .
1.7.1 Introduction . . . . . . . . . . . . . . . . . . .
1.7.2 Definition . . . . . . . . . . . . . . . . . . . . .
1.7.3 Declaration . . . . . . . . . . . . . . . . . . . .
1.7.4 Ouverture . . . . . . . . . . . . . . . . . . . . .
1.7.5 Lecture dune ligne, fermeture . . . . . . . . . .
1.7.6 Boucle pour . . . . . . . . . . . . . . . . . . . .
1.7.7 Exemple recapitulatif . . . . . . . . . . . . . .
1.8 Triggers . . . . . . . . . . . . . . . . . . . . . . . . . .
1.8.1 Principe . . . . . . . . . . . . . . . . . . . . . .
1.8.2 Classification . . . . . . . . . . . . . . . . . . .
1.8.3 Creation . . . . . . . . . . . . . . . . . . . . . .
1.8.4 Acc`es aux lignes en cours de modification . . .
1.8.5 Contourner le probl`eme des tables en mutation
1.9 Packages . . . . . . . . . . . . . . . . . . . . . . . . . .
1.9.1 Principe . . . . . . . . . . . . . . . . . . . . . .
1.9.2 Specification . . . . . . . . . . . . . . . . . . .
1.9.3 Corps . . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

3
3
3
3
3
3
4
4
5
5
6
8
8
8
9
10
10
11
11
11
13
13
13
15
15
15
17
17
17
17
17
17
18
18
19
19
19
19
20
22
25
25
25
25

2 Exercices
2.1 Introduction au PL/SQL .
2.2 Tableaux et Structures . .
2.3 Utilisation PL/SQL . . .
2.4 Exceptions . . . . . . . .
2.5 Sous-programmes . . . . .
2.6 Curseurs . . . . . . . . . .
2.7 Curseurs parametres . . .
2.8 Triggers . . . . . . . . . .
2.9 Packages . . . . . . . . . .
2.10 Revisions . . . . . . . . .

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

27
27
28
30
31
32
33
34
35
36
37

3 Corrig
es
3.1 Introduction au PL/SQL . . . . . . . .
3.2 Tableaux et Structures . . . . . . . . .
3.3 Application du PL/SQL et Exceptions
3.4 Sous-programmes . . . . . . . . . . . .
3.5 Curseurs . . . . . . . . . . . . . . . . .
3.6 Curseurs parametres . . . . . . . . . .
3.7 Triggers . . . . . . . . . . . . . . . . .
3.8 Packages . . . . . . . . . . . . . . . . .
3.9 Revisions . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

38
38
39
42
46
49
52
53
62
63

A Scripts de cr
eation de bases
A.1 Livraisons Sans contraintes . . . .
A.2 Modules et prerequis . . . . . . . .
A.3 Geometrie . . . . . . . . . . . . . .
A.4 Livraisons . . . . . . . . . . . . . .
A.5 Arbre genealogique . . . . . . . . .
A.6 Comptes bancaires . . . . . . . . .
A.7 Comptes bancaires avec exceptions
A.8 Secretariat pedagogique . . . . . .
A.9 Mariages . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

67
67
68
69
70
71
72
74
76
78

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

Chapitre 1

Notes de cours
1.1
1.1.1

Introduction au PL/SQL
PL/SQL

Le PL de PL/SQL signifie Procedural Language. Il sagit dune extension procedurale du SQL permettant deffectuer
des traitements complexes sur une base de donnees. Les possibilites offertes sont les memes quavec des langages
imperatifs (instructions en sequence) classiques.
Ecrivez-le dans un editeur dont vous copierez le contenu dans SQL+. Un script ecrit en PL/SQL se termine obligatoirement par un /, sinon SQL+ ne linterpr`ete pas. Sil contient des erreurs de compilation, il est possible dafficher les
messages derreur avec la commande SQL+ : SHOW ERRORS.

1.1.2

Blocs

Tout code ecrit dans un langage procedural est forme de blocs. Chaque bloc comprend une section de declaration
de variables, et un ensemble dinstructions dans lequel les variables declarees sont visibles.
La syntaxe est
DECLARE
/ d e c l a r a t i o n de v a r i a b l e s /
BEGIN
/ i n s t r u c t i o n s a e x e c u t e r /
END;

1.1.3

Affichage

Pour afficher le contenu dune variable, les procedures DBMS OUTPUT.PUT() et DBMS OUTPUT.PUT LINE() prennent
en argument une valeur `
a afficher ou une variable dont la valeur est `a afficher. Par defaut, les fonctions daffichage
sont desactivees. Il convient, `
a moins que vous ne vouliez rien voir safficher, de les activer avec la commande SQL+
SET SERVEROUTPUT ON.

1.1.4

Variables

Une variable se declare de la sorte :


nom type [ : = initialisation ] ;
Linitisation est optionnelle. Nous utiliserons les memes types primitifs que dans les tables. Par exemple :
SET SERVEROUTPUT ON
DECLARE
c varchar2 ( 1 5 ) := H e l l o World ! ;
BEGIN
DBMS_OUTPUT . PUT_LINE ( c ) ;
END;
/
Les affectations se font avec la syntaxe variable := valeur ;
3

1.1.5

Traitements conditionnels

Le IF et le CASE fonctionnent de la meme facon que dans les autres langages imperatifs :
IF / c o n d i t i o n 1 / THEN
/ i n s t r u c t i o n s 1 /
ELSE
/ i n s t r u c t i o n s 2 /
END IF ;
voire
IF / c o n d i t i o n 1 / THEN
/ i n s t r u c t i o n s 1 /
ELSIF / c o n d i t i o n 2 /
/ i n s t r u c t i o n s 2 /
ELSE
/ i n s t r u c t i o n s 3 /
END IF ;
Les conditions sont les memes quen SQL. Le switch du langage C simplemente en PL/SQL de la facon suivante :
CASE / v a r i a b l e /
WHEN / v a l e u r 1 / THEN
/ i n s t r u c t i o n s 1 /
WHEN / v a l e u r 2 / THEN
/ i n s t r u c t i o n s 2 /
...
WHEN / v a l e u r n / THEN
/ i n s t r u c t i o n s n /
ELSE
/ i n s t r u c t i o n s par d e f a u t /
END CASE;

1.1.6

Traitements r
ep
etitifs

LOOP ... END LOOP ; permet dimplementer les boucles


LOOP
/ i n s t r u c t i o n s /
END LOOP ;
Linstruction EXIT WHEN permet de quitter une boucle.
LOOP
/ i n s t r u c t i o n s /
EXIT WHEN / c o n d i t i o n / ;
END LOOP ;
La boucle FOR existe aussi en PL/SQL :
FOR / v a r i a b l e / IN / i n f / . . / sup / LOOP
/ i n s t r u c t i o n s /
END LOOP ;
Ainsi que la boucle WHILE :
WHILE / c o n d i t i o n / LOOP
/ i n s t r u c t i o n s /
END LOOP ;
Est-il possible, en bidouillant, dimplementer une boucle DO ... WHILE ?

1.2
1.2.1

Tableaux et structures
Tableaux

Cr
eation dun type tableau
Les types tableau doivent etre definis explicitement par une declaration de la forme
TYPE / t y p e / IS VARRAY ( / t a i l l e / ) OF / t y p e E l e m e n t s / ;
type est le nom du type tableau cree par cette instruction
taille est le nombre maximal delements quil est possible de placer dans le tableau.
typeElements est le type des elements qui vont etre stockes dans le tableau, il peut sagir de nimporte quel
type.
Par exemple, creons un type tableau de nombres indice de 1 `a 10, que nous appelerons numberTab
TYPE numberTab IS VARRAY ( 1 0 ) OF NUMBER;

D
eclaration dun tableau
Dorenavant, le type dun tableau peut etre utilise au meme titre que NUMBER ou VARCHAR2. Par exemple, declarons
un tableau appele t de type numberTab,
DECLARE
TYPE numberTab IS VARRAY ( 1 0 ) OF NUMBER;
t numberTab ;
BEGIN
/ i n s t r u c t i o n s /
END;
/

Allocation dun tableau


La creation dun type tableau met `
a disposition un constructeur du meme nom que le type cree. Cette fonction
reserve de lespace memoire pour ce tableau et retourne ladresse memoire de la zone reservee, il sagit dune sorte de
malloc. Si, par exemple, un type tableau numtab a ete cree, la fonction numtab() retourne une tableau vide.
DECLARE
TYPE numberTab IS VARRAY ( 1 0 ) OF NUMBER;
t numberTab ;
BEGIN
t := numberTab ( ) ;
/ u t i l i s a t i o n du t a b l e a u /
END;
/
Une fois cette allocation faite, il devient presque possible dutiliser le tableau...
Dimensionnement dun tableau
Le tableau retourne par le constructeur est vide. Il convient ensuite de reserver de lespace pour stocker les elements
quil va contenir. On utilise pour cela la methode EXTEND(). EXTEND sinvoque en utilisant la notation pointee. Par
exemple,
DECLARE
TYPE numberTab IS VARRAY ( 1 0 ) OF NUMBER;
t numberTab ;
BEGIN
t := numberTab ( ) ;
t . EXTEND ( 4 ) ;
/ u t i l i s a t i o n du t a b l e a u /
END;
/

Dans cet exemple, t.EXTEND(4) ; permet par la suite dutiliser les elements du tableau t(1), t(2), t(3) et t(4).
Il nest pas possible detendre un tableau `
a une taille superieure `a celle specifiee lors de la creation du type tableau
associe.
Utilisation dun tableau
On acc`ede, en lecture et en ecriture, au i-`eme element dune variable tabulaire nomme T avec linstruction T(i).
Les elements sont indices `
a partir de 1.
Effectuons, par exemple, une permutation circulaire vers la droite des elements du tableau t.
DECLARE
TYPE numberTab IS VARRAY ( 1 0 ) OF NUMBER;
t numberTab ;
i number ;
k number ;
BEGIN
t := numberTab ( ) ;
t . EXTEND ( 1 0 ) ;
FOR i IN 1 . . 1 0 LOOP
t ( i ) := i ;
END LOOP ;
k := t ( 1 0 ) ;
FOR i in REVERSE 2 . . 1 0 LOOP
t ( i ) := t ( i 1 ) ;
END LOOP ;
t ( 1 ) := k ;
FOR i IN 1 . . 1 0 LOOP
DBMS_OUTPUT . PUT_LINE ( t ( i ) ) ;
END LOOP ;
END;
/

1.2.2

Structures

Un structure est un type regroupant plusieurs types. Une variable de type structure contient plusieurs variables,
ces variables sappellent aussi des champs.
Cr
eation dun type structur
e
On definit un type structure de la sorte :
TYPE / nomType / IS RECORD
(
/ l i s t e d e s champs /
);
nomType est le nom du type structure construit avec la syntaxe precedente. La liste suit la meme syntaxe que la
liste des colonnes dune table dans un CREATE TABLE. Par exemple, construisons le type point (dans IR2 ),
TYPE point IS RECORD
(
abscisse NUMBER,
ordonnee NUMBER
);
Notez bien que les types servant `
a definir un type structure peuvent etre quelconques : variables scalaires, tableaux,
structures, etc.
D
eclaration dune variable de type structur
e
point est maintenant un type, il devient donc possible de creer des variables de type point, la r`egle est toujours la
meme pour declarer des variables en PL/SQL, par exemple
6

p point ;
permet de declarer une variable p de type point.
Utilisation dune variable de type structur
e
Pour acceder `
a un champ dune variable de type structure, en lecture ou en ecriture, on utilise la notation pointee :
v.c est le champ appele c de la variable structure appelee v. Par exemple,
DECLARE
TYPE point IS RECORD
(
abscisse NUMBER,
ordonnee NUMBER
);
p point ;
BEGIN
p . abscisse := 1 ;
p . ordonnee := 3 ;
DBMS_OUTPUT . PUT_LINE ( p . a b s c i s s e = | | p . abscisse | |
and p . ordonnee = | | p . ordonnee ) ;
END;
/
Le script ci-dessous cree le type point, puis cree une variable t de type point, et enfin affecte aux champs abscisse
et ordonnee du point p les valeurs 1 et 3.

1.3

Utilisation du PL/SQL

Ce cours est une introduction aux interactions possibles entre la base de donnees et les scripts PL/SQL.

1.3.1

Affectation

On place dans une variable le resultat dune requete en utilisant le mot-cle INTO. Les instructions
SELECT champ_1 , . . . , champ_n INTO v_1 , . . . , v_n
FROM . . .
affecte aux variables v 1, ..., v n les valeurs retournees par la requete. Par exemple
DECLARE
num NUMBER;
nom VARCHAR2( 3 0 ) := Poupe e Batman ;
BEGIN
SELECT numprod INTO num
FROM PRODUIT
WHERE nomprod = nom ;
DBMS_OUTPUT . PUT_LINE ( L a r t i c l e | |
nom | | a pour numero | | num ) ;
END;
/
Pretez attention au fait que la requete doit retourner une et une une seule ligne, sinon, une erreur se produit `
a
lexecution.

1.3.2

Tables et structures

Si vous ne tenez pas `


a vous prendre la tete pour choisir le type de chaque variable, demandez-vous ce que vous
allez mettre dedans ! Si vous tenez `
a y mettre une valeur qui se trouve dans une colonne dune table, il est possible de
vous referer directement au type de cette colonne avec le type nomTable.nomColonne%type. Par exemple,
DECLARE
num PRODUIT . numprod%type ;
nom PRODUIT . nomprod%type := Poupe e Batman ;
BEGIN
SELECT numprod INTO num
FROM PRODUIT
WHERE nomprod = nom ;
DBMS_OUTPUT . PUT_LINE ( L a r t i c l e | |
nom | | a pour numero | | num ) ;
END;
/
Pour aller plus loin, il est meme possible de declarer une structure pour representer une ligne dune table, le type
porte alors le nom suivant : nomTable%rowtype.
DECLARE
nom PRODUIT . nomprod%type := Poupe e Batman ;
ligne PRODUIT%rowtype ;
BEGIN
SELECT INTO ligne
FROM PRODUIT
WHERE nomprod = nom ;
DBMS_OUTPUT . PUT_LINE ( L a r t i c l e | |
ligne . nomprod | | a pour numero | | ligne . numprod ) ;
END;
/

1.3.3

Transactions

Un des mecanismes les plus puissants des SGBD recents reside dans le syst`eme des transactions. Une transaction
est un ensemble doperations atomiques, cest-`
a-dire indivisible. Nous considererons quun ensemble doperations est
indivisible si une execution partielle de ces instructions poserait des probl`emes dintegrite dans la base de donnees.
Par exemple, dans le cas dune base de donnees de gestion de comptes en banque, un virement dun compte `a un autre
se fait en deux temps : crediter un compte dune somme s, et debiter un autre de la meme somme s. Si une erreur
survient pendant la deuxi`eme operation, et que la transaction est interrompue, le virement est incomplet et le patron
va vous assassiner.
Il convient donc de disposer dun mecanisme permettant de se proteger de ce genre de desagrement. Plut
ot que
se casser la tete `
a tester les erreurs `
a chaque etape et `a balancer des instructions permettant de revenir en arri`ere,
nous allons utiliser les instructions COMMIT et ROLLBACK.
Voici le squelette dun exemple :
/ i n s t r u c t i o n s /
IF / e r r e u r / THEN
ROLLBACK;
ELSE
COMMIT;
END;
Le ROLLBACK annule toutes les modifications faites depuis le debut de la transaction (donc depuis le precedent
COMMIT), COMMIT les enregistre definitivement dans la base de donnees.
La variable denvironnement AUTOCOMMIT, qui peut etre positionnee `a ON ou `a OFF permet dactiver la gestion des
transactions. Si elle est positionnee `
a ON, chaque instruction a des repercussions immediates dans la base, sinon, les
modifications ne sont effectives quune fois quun COMMIT a ete execute.

1.4

Exceptions

Le mecanisme des exceptions est implemente dans la plupart des langages recent, notament orientes objet. Cette
facon de programmer a quelques avantages immediats :
obliger les programmeurs `
a traiter les erreurs : combien de fois votre prof de C a hurle en vous suppliant
de verifier les valeurs retournees par un malloc, ou un fopen ? La plupart des compilateurs des langages `
a
exceptions (notamment java) ne compilent que si pour chaque erreur potentielle, vous avez prepare un bloc de
code (eventuellement vide...) pour la traiter. Le but est de vous assurer que vous navez pas oublie derreur.
Rattraper les erreurs en cours dex
ecution : Si vous programmez un syst`eme de securite de centrale
nucleaire ou un pilote automatique pour laviation civile, une erreur de memoire qui vous afficherait lecran
bleu de windows, ou le message Envoyer le rapport derreur ?, ou plus simplement le fameux Segmentation
fault produirait un effet des plus mauvais. Certaines erreurs dexecution sont rattrapables, autrement dit, il est
possible de resoudre le probl`eme sans interrompre le programme.
Ecrire le traitement des erreurs `
a part : Pour des raisons fiabilite, de lisibilite, il a ete considere que
melanger le code normal et le traitement des erreurs etait un style de programmation perfectible... Dans les
langages `
a exception, les erreurs sont traitees `a part.

1.4.1

Rattraper une exception

Je vous ai menti dans le premier cours, un bloc en PL/SQL a la forme suivante :


DECLARE
/ d e c l a r a t i o n s /
BEGIN
/ i n s t r u c t i o n s /
EXCEPTION
/ t r a i t e m e n t d e s e r r e u r s /
END;
Une exception est une erreur type, elle porte un nom, au meme titre quune variable a une identificateur, par
exemple GLUBARF. Lorsque dans les instructions, lerreur GLUBARF se produit, le code du BEGIN sinterrompt et le
code de la section EXCEPTION est lance. On dit aussi que quand une exception est lev
ee (raised) (on dit aussi jet
ee
(thrown)), on la rattrape (catch) dans le bloc EXCEPTION. La section EXCEPTION a la forme suivante :
EXCEPTION
WHEN E1 THEN
/ t r a i t e m e n t
WHEN E2 THEN
/ t r a i t e m e n t
WHEN E3 THEN
/ t r a i t e m e n t
WHEN OTHERS THEN
/ t r a i t e m e n t
END;

/
/
/
/

On enum`ere les erreurs les plus pertinentes en utilisant leur nom et en consacrant `a chacune delle un traitement
particulier pour rattraper (ou propager) lerreur. Quand un bloc est traite, les WHEN suivants ne sont pas evalues.
OTHERS est lexception par defaut, OTHERS est toujours verifie, sauf si un cas precedent a ete verifie. Dans lexemple
suivant :
DECLARE
/ d e c l a r a t i o n s /
BEGIN
/ i n s t r u c t i o n s /
COMMIT;
EXCEPTION
WHEN GLUBARF THEN
ROLLBACK;
DBMS_OUTPUT . PUT_LINE ( GLUBARF e x c e p t i o n r a i s e d ! ) ;
WHEN OTHERS THEN
DBMS_OUTPUT . PUT_LINE ( SQLCODE = | | SQLCODE ) ;
DBMS_OUTPUT . PUT_LINE ( SQLERRM = | | SQLERRM ) ;
10

END;
Les deux variables globales SQLCODE et SQLERRM contiennent respectivement le code derreur Oracle et un message
derreur correspondant `
a la derni`ere exception levee. Chaque exception a donc, en plus dun nom, un code et un
message.

1.4.2

Exceptions pr
ed
efinies

Bon nombre dexceptions sont predefinies par Oracle, par exemple


NO DATA FOUND est levee quand la requete dune instruction de la forme SELECT ... INTO ... ne retourne
aucune ligne
TOO MANY ROWS est levee quand la requete dune instruction de la forme SELECT ... INTO ... retourne plusieurs
lignes
DUP VAL ON INDEX est levee si une insertion (ou une modification) est refusee `a cause dune contrainte dunicite.
On peut enrichir notre exemple de la sorte :
DECLARE
num NUMBER;
nom VARCHAR2( 3 0 ) := Poupe e Batman ;
BEGIN
SELECT numprod INTO num
FROM PRODUIT
WHERE nomprod = nom ;
DBMS_OUTPUT . PUT_LINE ( L a r t i c l e | |
nom | | a pour numero | | num ) ;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT . PUT_LINE ( Aucun a r t i c l e ne p o r t e l e nom
| | nom ) ;
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT . PUT_LINE ( P l u s i e u r s a r t i c l e s p o r t e n t l e nom
| | nom ) ;
WHEN OTHERS THEN
DBMS_OUTPUT . PUT_LINE ( I l y a un g r o s p r o b l`e m e . . . ) ;
END;
/
SELECT numprod INTO num... l`eve une exception si la requete renvoie un nombre de lignes different de 1.

1.4.3

Codes derreur

Je vous encore menti, certaines exceptions nont pas de nom. Elle ont seulement un code derreur, il est conseille
de se reporter `
a la documentation pour les obtenir. On les traite de la facon suivante
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = CODE1 THEN
/ t r a i t e m e n t /
ELSIF SQLCODE = CODE2 THEN
/ t r a i t e m e n t /
ELSE
DBMS_OUTPUT . PUT_LINE ( J v o i s pas c que ca
peut et re . . . ) ;
END;
Cest souvent le cas lors de violation de contraintes.

1.4.4

D
eclarer et lancer ses propres exceptions

Exception est un type, on declare donc les exceptions dans une section DECLARE. Une exception se lance avec
linstruction RAISE. Par exemple,

11

DECLARE
GLUBARF EXCEPTION;
BEGIN
RAISE GLUBARF ;
EXCEPTION
WHEN GLUBARF THEN
DBMS_OUTPUT . PUT_LINE ( g l u b a r f r a i s e d . ) ;
END;
/

12

1.5

Sous-programmes

1.5.1

Proc
edures

Syntaxe
On definit une procedure de la sorte
CREATE OR REPLACE PROCEDURE / nom / ( / p a r a m e t r e s / ) IS
/ d e c l a r a t i o n d e s v a r i a b l e s l o c a l e s /
BEGIN
/ i n s t r u c t i o n s /
END;
les param`etres sont une simple liste de couples nom type. Par exemple, la procedure suivante affiche un compte `
a
rebours.
CREATE OR REPLACE PROCEDURE compteARebours ( n NUMBER) IS
BEGIN
IF n >= 0 THEN
DBMS_OUTPUT . PUT_LINE ( n ) ;
compteARebours ( n 1 ) ;
END IF ;
END;

Invocation
En PL/SQL, une procedure sinvoque tout simplement avec son nom. Mais sous SQL+, on doit utiliser le mot-cle
CALL. Par exemple, on invoque le compte `
a rebours sous SQL+ avec la commande CALL compteARebours(20).
Passage de param`
etres
Oracle permet le passage de param`etres par reference. Il existe trois types de passage de param`etres :
IN : passage par valeur
OUT : aucune valeur passee, sert de valeur de retour
IN OUT : passage de param`etre par reference
Par defaut, le passage de param`etre se fait de type IN.
CREATE OR REPLACE PROCEDURE incr ( val IN OUT NUMBER) IS
BEGIN
val := val + 1 ;
END;

1.5.2

Fonctions

Syntaxe
On cree une nouvelle fonction de la facon suivante :
CREATE OR REPLACE FUNCTION / nom / ( / p a r a m e t r e s / ) RETURN / t y p e
/ IS
/ d e c l a r a t i o n d e s v a r i a b l e s l o c a l e s /
BEGIN
/ i n s t r u c t i o n s /
END;
Linstruction RETURN sert `
a retourner une valeur. Par exemple,
CREATE OR REPLACE FUNCTION module ( a NUMBER, b NUMBER) RETURN NUMBER IS
BEGIN
IF a < b THEN
RETURN a ;
ELSE
13

RETURN module ( a b , b ) ;
END IF ;
END;

Invocation
Tout comme les procedures, linvocation des fonctions ne pose aucun probl`eme en PL/SQL, par contre, sous SQL+,
cest quelque peu particulier. On passe par une pseudo-table nommee DUAL de la facon suivante :
SELECT module ( 2 1 , 1 2 ) FROM DUAL ;

Passage de param`
etres
Les param`etres sont toujours passes avec le type IN.

14

1.6
1.6.1

Curseurs
Introduction

Les instructions de type SELECT ... INTO ... manquent de souplesse, elles ne fontionnent que sur des requetes
retourant une et une seule valeur. Ne serait-il pas interessant de pouvoir placer dans des variables le resultat dune
requete retournant plusieurs lignes ? A mediter...

1.6.2

Les curseurs

Un curseur est un objet contenant le resultat dune requete (0, 1 ou plusieurs lignes).
d
eclaration
Un curseur se declare dans une section DECLARE :
CURSOR / nomcurseur / IS / r e q u e t e / ;
Par exemple, si on tient `
a recuperer tous les employes de la table EMP, on declare le curseur suivant.
CURSOR emp_cur IS
SELECT FROM EMP ;
Ouverture
Lors de louverture dun curseur, la requete du curseur est evaluee, et le curseur contient toutes les donnees
retournees par la requete. On ouvre un curseur dans une section BEGIN :
OPEN / nomcurseur / ;
Par exemmple,
DECLARE
CURSOR emp_cur IS
SELECT FROM EMP ;
BEGIN
OPEN emp_cur ;
/ U t i l i s a t i o n du c u r s e u r /
END;

Lecture dune ligne


Une fois ouvert, le curseur contient toutes les lignes du resultat de la requete On les recup`ere une par une en
utilisant le mot-cle FETCH :
FETCH / nom curseur

/ INTO / l i s t e v a r i a b l e s / ;

La liste de variables peut etre remplacee par une structure de type nom curseur%ROWTYPE. Si la lecture de la ligne
echoue, parce quil ny a plus de ligne `
a lire, lattribut %NOTFOUND prend la valeur vrai.
DECLARE
CURSOR emp_cur IS
SELECT FROM EMP ;
ligne emp_cur%rowtype
BEGIN
OPEN emp_cur ;
LOOP
FETCH emp_cur INTO ligne ;
EXIT WHEN emp_cur%NOTFOUND ;
DBMS_OUTPUT . PUT_LINE ( ligne . ename ) ;
END LOOP ;
/ . . . /
END;

15

Fermeture
Apr`es utilisation, il convient de fermer le curseur.
CLOSE / nomcurseur / ;
Completons notre exemple,
DECLARE
CURSOR emp_cur IS
SELECT FROM EMP ;
ligne emp_cur%rowtype ;
BEGIN
OPEN emp_cur ;
LOOP
FETCH emp_cur INTO ligne ;
EXIT WHEN emp_cur%NOTFOUND ;
DBMS_OUTPUT . PUT_LINE ( ligne . ename ) ;
END LOOP ;
CLOSE emp_cur ;
END;
/
Le programme ci-dessus peut aussi secrire
DECLARE
CURSOR emp_cur IS
SELECT FROM EMP ;
ligne emp_cur%rowtype ;
BEGIN
OPEN emp_cur ;
FETCH emp_cur INTO ligne ;
WHILE emp_cur%FOUND LOOP
DBMS_OUTPUT . PUT_LINE ( ligne . ename ) ;
FETCH emp_cur INTO ligne ;
END LOOP ;
CLOSE emp_cur ;
END;

Boucle FOR
Il existe une boucle FOR se chargeant de louverture, de la lecture des lignes du curseur et de sa fermeture,
FOR ligne IN emp_cur LOOP
/ Traitement /
END LOOP ;
Par exemple,
DECLARE
CURSOR emp_cur IS
SELECT FROM EMP ;
ligne emp_cur%rowtype ;
BEGIN
FOR ligne IN emp_cur LOOP
DBMS_OUTPUT . PUT_LINE ( ligne . ename ) ;
END LOOP ;
END;
/

16

1.7
1.7.1

Curseurs parametr
es
Introduction

A votre avis, le code suivant est-il valide ?


DECLARE
NUMBER n := 1 4 ;
BEGIN
DECLARE
CURSOR C IS
SELECT
FROM PERSONNE
WHERE numpers >= n ;
ROW C%rowType ;
BEGIN
FOR ROW IN C LOOP
DBMS_OUTPUT . PUT_LINE ( ROW . numpers ) ;
END LOOP ;
END;
END;
/
Reponse : non. La requete dun curseur ne peut pas contenir de variables dont les valeurs ne sont pas fixees.
Pourquoi ? Parce que les valeurs des ces sont susceptibles de changer entre la declaration du curseur et son ouverture.
Le rem`ede est un curseur parametre.

1.7.2

D
efinition

Un curseur parametre est un curseur dont la requete contient des variables dont les valeurs ne seront fixees qu`
a
louverture.

1.7.3

D
eclaration

On precise la liste des noms et des type des param`etres entre parenth`eses apr`es le nom du curseur :
CURSOR / nom / ( / l i s t e d e s p a r a m`e t r e s / ) IS
/ r e q u e t e /
Par exemple, creeons une requete qui, pour une personne donnee, nous donne la liste des noms et prenoms de ses
enfants :
CURSOR enfants ( numparent NUMBER) IS
SELECT
FROM PERSONNE
WHERE pere = numparent
OR mere = numparent ;

1.7.4

Ouverture

On ouvre un curseur parametre en passant en param`etre les valeurs des variables :


OPEN / nom / ( / l i s t e d e s p a r a m`e t r e s / )
Par exemple,
OPEN enfants ( 1 ) ;

1.7.5

Lecture dune ligne, fermeture

la lecture dune ligne suit les memes r`egles quavec un curseur non parametre.
17

1.7.6

Boucle pour

La boucle pour se charge de louverture, il convient donc de placer les param`etre dans lentete de la boucle,
FOR / v a r i a b l e / IN / nom / ( / l i s t e p a r a m`e t r e s / ) LOOP
/ i n s t r u c t i o n s /
END LOOP ;
Par exemple,
FOR e IN enfants ( 1 ) LOOP
DBMS_OUTPUT . PUT_LINE ( e . nompers | |
END LOOP ;

1.7.7

| | e . prenompers ) ;

Exemple r
ecapitulatif

DECLARE
CURSOR parent IS
SELECT
FROM PERSONNE ;
p parent%rowtype ;
CURSOR enfants ( numparent NUMBER) IS
SELECT
FROM PERSONNE
WHERE pere = numparent
OR mere = numparent ;
e enfants%rowtype ;
BEGIN
FOR p IN parent LOOP
DBMS_OUTPUT . PUT_LINE ( Les e n f a n t s de | | p . prenom | |
| | p . nom | | s o n t : ) ;
FOR e IN enfants ( p . numpers ) LOOP
DBMS_OUTPUT . PUT_LINE ( | | e . prenom
| | | | e . nom
);
END LOOP ;
END LOOP ;
END;
/

18

1.8

Triggers

1.8.1

Principe

Un trigger est une procedure stockee qui se lance automatiquement lorsquun evenement se produit. Par evenement,
on entend dans ce cours toute modification des donnees se trouvant dans les tables. On sen sert pour contr
oler ou
appliquer des contraintes quil est impossible de formuler de facon declarative.

1.8.2

Classification

Type d
ev
enement
Lors de la creation dun trigger, il convient de preciser quel est le type devenement qui le declenche. Nous realiserons
dans ce cours des triggers pour les evenements suivants :
INSERT
DELETE
UPDATE
Moment de l
execution
On precise aussi si le trigger doit etre execute avant (BEFORE) ou apr`es (AFTER) levenement.
Ev
enements non atomiques
Lors que lon fait un DELETE ..., il y a une seule instruction, mais plusieurs lignes sont affectees. Le trigger doit-il
etre execute pour chaque ligne affectee (FOR EACH ROW), ou seulement une fois pour toute linstruction (STATEMENT) ?
un FOR EACH ROW TRIGGER est execute `
a chaque fois quune ligne est affectee.
un STATEMENT TRIGGER est executee `
a chaque fois quune instruction est lancee.

1.8.3

Cr
eation

Syntaxe
On declare un trigger avec linstruction suivante :
CREATE OR REPLACE TRIGGER nomtrigger
[ BEFORE | AFTER ] [INSERT | DELETE | UPDATE] ON nomtable
[ FOR EACH ROW | ]
DECLARE
/ d e c l a r a t i o n s /
BEGIN
/ i n s t r u c t i o n s /
END;
Par exemple,
SQL>
2
3
4
5
6

CREATE OR REPLACE TRIGGER pasDeDeleteDansClient


BEFORE DELETE ON CLIENT
BEGIN
RAISE_APPLICATION_ERROR ( 20555 , Va t e f a i r e . . . ) ;
END;
/

D
e clencheur cr
e
e.
SQL> SELECT COUNT( )
2 FROM CLIENT ;
COUNT( )

21
SQL> DELETE FROM CLIENT ;
19

DELETE FROM CLIENT

ERREUR `
a la ligne 1 :
ORA 20555: Va te faire . . .
ORA 06512: `
a SCOTT.PASDEDELETEDANSCLIENT , ligne 2
ORA 04088: erreur lors d ex
e cution du d
e clencheur SCOTT.PASDEDELETEDANSCLIENT

SQL> SELECT COUNT( )


2 FROM CLIENT ;
COUNT( )

21
Linstruction RAISE APPLICATION ERROR(code, message) l`eve une exception sans nom portant un code code et
un message derreur message. Vous remarquez que comme lerreur a ete levee avant la suppression, les donnees sont
toujours presentes dans la table CLIENT. Le trigger a controle une r`egle, et comme elle netait pas respectee, il a lance
une erreur.
Combinaisons d
ev
enements
Il est possible, en separant les types devenement par le mot-cle OR, de definir un trigger declenche par plusieurs
evenements. Les variables booleennes INSERTING, UPDATING et DELETING permettent didentifier levenement qui a
declenche le trigger.
CREATE OR REPLACE TRIGGER afficheEvenement
BEFORE INSERT OR UPDATE OR DELETE ON CLIENT
FOR EACH ROW
BEGIN
IF INSERTING THEN
DBMS_OUTPUT . PUT_LINE ( I n s e r t i o n dans CLIENT ) ;
ELSIF UPDATING THEN
DBMS_OUTPUT . PUT_LINE ( Mise a j o u r dans CLIENT ) ;
ELSE
DBMS_OUTPUT . PUT_LINE ( S u p p r e s s i o n dans CLIENT ) ;
END IF ;
END;

1.8.4

Acc`
es aux lignes en cours de modification

Dans les FOR EACH ROW triggers, il est possible avant la modification de chaque ligne, de lire lancienne ligne et la
nouvelle ligne par lintermediaire des deux variables structurees :old et :new. Par exemple le trigger suivant empeche
de diminuer un salaire :
CREATE OR REPLACE TRIGGER pasDeBaisseDeSalaire
BEFORE UPDATE ON EMP
FOR EACH ROW
BEGIN
IF ( : old . sal > : new . sal ) THEN
RAISE_APPLICATION_ERROR ( 20567 ,
Pas de b a i s s e de s a l a i r e ! ) ;
END IF ;
END;

Tables en mutation
Il est impossible, dans un trigger de type FOR EACH ROW de faire un SELECT sur la table en cours de modification.

20

SQL>
2
3
4
5
6
7
8
9

CREATE OR REPLACE TRIGGER beforeStatement


BEFORE UPDATE ON CLIENT
DECLARE
NB NUMBER;
BEGIN
SELECT COUNT( ) INTO NB
FROM CLIENT ;
END;
/

D
e clencheur cr
e
e.
SQL>
SQL>
2
3
4
5
6
7
8
9

CREATE OR REPLACE TRIGGER afterStatement


AFTER UPDATE ON CLIENT
DECLARE
NB NUMBER;
BEGIN
SELECT COUNT( ) INTO NB
FROM CLIENT ;
END;
/

D
e clencheur cr
e
e.
SQL>
SQL> UPDATE CLIENT SET nomcli = nomcli ;
21 ligne ( s ) mise ( s ) `
a jour .
SQL>
SQL>
2
3
4
5
6
7
8
9
10

CREATE OR REPLACE TRIGGER beforeForEachRow


BEFORE UPDATE ON CLIENT
FOR EACH ROW
DECLARE
NB NUMBER;
BEGIN
SELECT COUNT( ) INTO NB
FROM CLIENT ;
END;
/

D
e clencheur cr
e
e.
SQL>
SQL> UPDATE CLIENT SET nomcli = nomcli ;
UPDATE CLIENT SET nomcli = nomcli

ERREUR `
a la ligne 1 :
ORA 04091: la table SCOTT . CLIENT est en mutation ; le d
e clencheur ou la
fonction ne peut la voir
ORA 06512: `
a SCOTT.BEFOREFOREACHROW , ligne 4
ORA 04088: erreur lors d ex
e cution du d
e clencheur SCOTT.BEFOREFOREACHROW

SQL> DROP TRIGGER beforeForEachRow ;


D
e clencheur supprim
e.

21

SQL>
SQL>
SQL>
2
3
4
5
6
7
8
9
10

CREATE OR REPLACE TRIGGER afterForEachRow


AFTER UPDATE ON CLIENT
FOR EACH ROW
DECLARE
NB NUMBER;
BEGIN
SELECT COUNT( ) INTO NB
FROM CLIENT ;
END;
/

D
e clencheur cr
e
e.
SQL>
SQL> UPDATE CLIENT SET nomcli = nomcli ;
UPDATE CLIENT SET nomcli = nomcli

ERREUR `
a la ligne 1 :
ORA 04091: la table SCOTT . CLIENT est en mutation ; le d
e clencheur ou la
fonction ne peut la voir
ORA 06512: `
a SCOTT.AFTERFOREACHROW , ligne 4
ORA 04088: erreur lors d ex
e cution du d
e clencheur SCOTT.AFTERFOREACHROW

1.8.5

Contourner le probl`
eme des tables en mutation

Il existe plusieurs facons de contourner ce probl`eme :


Utiliser un STATEMENT trigger. Comme on ne sait pas quelles lignes ont ete modifiees, on est oblige de toutes
les traiter. Cette approche presente donc un inconvenient majeur : elle nous am`ene `a effectuer de nombreux
traitements inutiles.
En ayant des donnees redondantes. Il suffit que les donnees servant `a la verification se trouvent dans une autre
table que celle en mutation. Cette methode a pour inconvenient la memoire occupee et la quantite de code `
a ecrire
pour maintenir la coherence des donnees. Dans la plupart des cas, cette solution est malgre tout la meilleure.
Colonnes suppl
ementaires
Par exemple, si lon souhaite empecher un client davoir plus de 10 comptes en banque, une solution est de placer
dans la table client une colonne contenant le nombre de comptes.
ALTER TABLE CLIENT ADD nbComptes number ;
UPDATE CLIENT SET nbComptes = 0 ;
Une fois cette table cree, il convient de sassurer que les donnees de la colonne nbComptes contient toujours les
bonnes valeurs. On le fait avec plusieurs sous-programmes :
CREATE OR REPLACE TRIGGER metAJourNbComptes
AFTER INSERT OR UPDATE OR DELETE ON COMPTECLIENT
BEGIN
UPDATE CLIENT SET nbComptes =
(
SELECT COUNT( )
FROM COMPTECLIENT CC
WHERE CC . numCli = numCli
);
END;
/
CREATE OR REPLACE TRIGGER verifieNbComptes

22

BEFORE INSERT ON COMPTECLIENT


FOR EACH ROW
DECLARE
nbComptes NUMBER;
BEGIN
SELECT nbComptes INTO nbComptes
FROM CLIENT
WHERE numCli = : new . numcli ;
IF ( nbComptes >= 1 0 ) THEN
RAISE_APPLICATION_ERROR ( 20556 ,
Ce c l i e n t a d e j a t r o p de comptes ) ;
END IF ;
END;
/
On peut affiner en remplacant metAJourNbComptes par plusieurs sous-programmes :
CREATE OR REPLACE TRIGGER initialiseNbComptes
BEFORE INSERT ON CLIENT
FOR EACH ROW
BEGIN
: new . nbComptes := 0 ;
END;
/
CREATE OR REPLACE TRIGGER metAJourNbComptes
AFTER INSERT OR UPDATE OR DELETE ON COMPTECLIENT
FOR EACH ROW
BEGIN
IF DELETING OR UPDATING THEN
UPDATE CLIENT SET nbComptes = nbComptes 1
WHERE numcli = : old . numcli ;
END IF ;
IF INSERTING OR UPDATING THEN
UPDATE CLIENT SET nbComptes = nbComptes + 1
WHERE numcli = : new . numcli ;
END IF ;
END;
/

Tables suppl
ementaires
Si lon souhaite par exemple empecher les circuits dans la table PERSONNE, il est necessaire de faire un parcours
de graphe. Ce qui necessite des SELECT dans la table en cours de mutation. La seule solution est dans ce cas davoir
une table miroir qui contient les colonnes cles primaire et etrang`eres de cette table, et de sen servir pour detecter les
circuits.
CREATE TABLE MIRRORPERSONNE
(
numpers NUMBER PRIMARY KEY,
pere NUMBER,
mere NUMBER
);
Nous allons ensuite proceder de meme, en repercutant chaque operation de PERSONNE sur MIRRORPERSONNE.
CREATE OR REPLACE TRIGGER miseAJourMirrorPersonne
BEFORE UPDATE OR INSERT OR DELETE ON PERSONNE
FOR EACH ROW
BEGIN
IF DELETING OR UPDATING THEN
23

DELETE FROM MIRRORPERSONNE


WHERE numpers = : old . numpers ;
END IF ;
IF INSERTING OR UPDATING THEN
INSERT INTO MIRRORPERSONNE VALUES
( : new . numpers , : new . pere , : new . mere ) ;
END IF ;
END;
/
Une fois cela fait, il suffit de rechercher si une personne inseree est une descendante delle meme dans MIRRORPERSONNE.
CREATE OR REPLACE FUNCTION trouveCircuit ( current NUMBER, toFind NUMBER)
RETURN BOOLEAN IS
numPere NUMBER;
numMere NUMBER;
BEGIN
IF ( current IS NULL) THEN
RETURN FALSE;
END IF ;
SELECT pere , mere INTO numPere , numMere
FROM MIRRORPERSONNE
WHERE numPers = current ;
RETURN ( numPere = toFind OR numMere = toFind OR
trouveCircuit ( numPere , toFind ) OR
trouveCircuit ( numMere , toFind ) ) ;
END;
/
CREATE OR REPLACE TRIGGER verifieCircuit
AFTER UPDATE OR INSERT ON PERSONNE
FOR EACH ROW
BEGIN
IF ( trouveCircuit ( : new . numPers , : new . numPers ) ) THEN
RAISE_APPLICATION_ERROR ( 20557 ,
C i r c u i t dans l a r b r e g e n e a l o g i q u e . ) ;
END IF ;
END;
/

24

1.9

Packages

1.9.1

Principe

Un package est un ensemble de sous-programmes et de variables forme par


Une specification : declaration de variables et de sous-programmes
Un corps : implementation des sous-programmes
Tout ce qui se trouve dans la specification doit se trouver dans le corps, mais la reciproque est fausse. Un package
satisfait les points suivants :
encapsulation : certains traitements sont masques, seule la specification du package est visible. Cela a pour
avantage de simplifier la t
ache de celui qui va utiliser le package.
modularit
e : il est possible de developper separement les diverses parties de lapplication. le developpement
devient ainsi un assemblage de package.
Ces deux aspects fournissent une souplesse certaine au niveau du developpement : il est possible de modifier le
corps dun package sans changer sa specification, donc sans modifier le fonctionnement de lapplication.

1.9.2

Sp
ecification

La syntaxe permettant de creer lentete est la suivante :


CREATE OR REPLACE PACKAGE nompackage IS
/
declarations
/
END nomPackage ;
/
Par exemple,
CREATE OR REPLACE PACKAGE compteur IS
procedure reset ;
function nextValue return number ;
END compteur ;
/

1.9.3

Corps

La syntaxe permettant de creer le corps est la suivante :


CREATE OR REPLACE PACKAGE BODY nompackage IS
/
implementation
/
END nomPackage ;
/
Par exemple,
CREATE OR REPLACE PACKAGE BODY compteur IS
cpt NUMBER := 0 ;
PROCEDURE reset IS
BEGIN
cpt := 0 ;
END;
FUNCTION nextValue RETURN NUMBER IS
BEGIN
cpt := cpt + 1 ;
RETURN cpt 1 ;
END;
END compteur ;
25

/
On peut utiliser un package depuis nimporte quel script PL/SQL :
DECLARE
nb NUMBER;
BEGIN
FOR nb IN 4 . . 2 0 LOOP
DBMS_OUTPUT . PUT_LINE ( COMPTEUR . nextValue ( ) ) ;
END LOOP ;
COMPTEUR . RESET ( ) ;
FOR nb IN REVERSE 0 . . 1 0 LOOP
DBMS_OUTPUT . PUT_LINE ( COMPTEUR . nextValue ( ) ) ;
END LOOP ;
END;
/

26

Chapitre 2

Exercices
2.1

Introduction au PL/SQL

Exercice 1
Ecrivez un programme affectant les valeurs 1 et 2 `a deux variables a et b, puis permutant les valeurs de ces deux
variables.

Exercice 2
Ecrivez un programme placant la valeur 10 dans une variable a, puis affichant la factorielle de a.

Exercice 3
Ecrivez un programme placant les valeurs 48 et 84 dans deux variables a et b puis affichant le pgcd de a et b.

27

2.2

Tableaux et Structures

Exercice 1
1. Creez un type tableau pouvant contenir jusqu`a 50 entiers.
2. Creez une variable de ce type , faites une allocation dynamique et dimensionnez ce tableau `a 20 emplacements.
3. Placez dans ce tableau la liste des 20 premiers carres parfaits : 1, 4, 9, 16, 25, . . .
4. Inversez lordre des elements du tableau
5. Affichez le tableau.

Exercice 2
Triez le tableau precedent avec la methode du tri `a bulle.

Exercice 3
Recherchez, par dichotomie, si lelement 225 se trouve dans le tableau.

Exercice 4
On implemente des listes chanees avec des tableaux de la sorte,
SET SERVEROUTPUT ON
DECLARE
-- Maillon dune liste cha^
n
ee
TYPE CELL IS RECORD
(
-- Donn
ee de chaque maillon
data INTEGER,
-- Indice du maillon pr
ec
edent de la liste,
-- -1 sil ny en a pas
previous INTEGER,
-- Indice du maillon suivant de la liste,
-- -1 sil ny en a pas
next INTEGER
);
-- Type tableau contenant les maillons de la liste
TYPE TREE IS VARRAY (19) OF CELL;
-- Tableau contenant les maillons de la liste
t TREE;
-- indice du premier
el
ement de la liste
first integer;
-- indice du dernier
el
ement de la liste
last integer;
BEGIN
t := TREE();
t.extend(19);
-- Initialisation
FOR i IN 1..19 LOOP
t(i).data := power(i, 5) mod 19 ;
t(i).previous := i-1;
t(i).next := i+1;
END LOOP;
first := 1;
last := 19;
t(first).previous := -1;
t(last).next := -1;

28

-- Affichage
DECLARE
p integer := first;
BEGIN
WHILE p <> -1 LOOP
DBMS_OUTPUT.PUT_LINE(( || p || , ||
t(p).data || , ||
t(p).previous || , || t(p).next || ));
p := t(p).next;
END LOOP;
END;
/* Ecrivez la suite vous-m^
eme... */
END;
/
Inversez lordre des elements de la liste, sans changer les indices des maillons (seulement en modifiant le chanage).

Exercice 5
Utilisez le tri `
a bulle pour remettre les elements dans lordre. Les indications sont les memes : ne deplacez pas les
maillons, vous navez le droit de toucher quau chanage. Bon courage, laspirine nest pas fournie.

29

2.3

Utilisation PL/SQL

Nous travaillerons sur les donnees A.6 et A.5.


Vous noublierez pas de placer des commit en des lieux bien choisis.

Exercice 1
Vous remarquerez que les valeurs des numpers de la table PERSONNE forment une sequence de nombres de 1 `
a 21.
Utilisez une boucle dans laquelle vous placerez une requete pour recopier les couples nom/prenom de la table personne
dans la table CLIENT.

Exercice 2
Ecrivez un script recuperant le client de cle primaire la plus elevee, et injectant ce client dans la table PERSONNEL.

Exercice 3
Ouvrez un compte courant pour chaque personne, effectuez un depot en esp`ece egal `a numpers 100 euros.

Exercice 4
Ouvrez un livret pour chaque personne ayant un numpers pair, faites un virement de leur compte courant vers ce
livret de sorte quil ne reste plus que 500 sur leur compte.

30

2.4

Exceptions

Nous utiliserons les donnees de A.7 et A.5


Vous etes invites `
a modifier le code de la seance precedente. Chaque fois quun SELECT ... INTO ... sera effectue,
vous rattraperez les exceptions NO DATA FOUND et TOO MANY ROWS. A chaque insertion, vous ratrapperez lexception
DUP VAL ON INDEX.

Exercice 1
Faites de sorte que les scripts important les donnees des tables CLIENT ne puissent etre executes quune seule fois.

Exercice 2
Les scripts remplissant la table Operation ne fonctionneront pas aujourdhui... Meme sil fonctionnaient la derni`ere
fois. Trouvez les codes derreurs des exceptions levees par ces scripts, rattrapez-les de la facon la plus appropriee qui
soit.

31

2.5

Sous-programmes

Exercice 1
Ecrire une fonction recursive retournant bn , avec n entier positif ou nul.

Exercice 2
Ameliorer la fonction precedente en utilisant le fait que
n

bn = (b2 ) 2
si n est pair.
Pour les questions suivantes, utilisez les donnees de A.5.

Exercice 3
Ecrire une fonction demi-freres prenant deux numeros de personnes en param`etre et retournant vrai si et seulement
si ces deux personnes ont un parent en commun.

Exercice 4
Ecrire une fonction cousins germains prenant deux numeros de personnes en param`etre et retournant vrai si et
seulement si ces deux deux individus sont cousins germains.

Exercice 5
Ecrire une procedure recursive affichant le nom de la personne dont le numero est passe en param`etre et se rappellant
recursivement sur le p`ere de cette personne. Faites de sorte `a ne pas utiliser dexceptions.

Exercice 6
Ecrire une procedure recursive affichant les noms des ascendants de sexe masculin de la personne dont le numero
est passe en param`etre.

Exercice 7
Ecrire une fonction recursive prenant deux numeros de personne A et B et retournant vrai si A est un ascendant
de B.

Exercice 8
Ecrire une fonction prenant en param`etre deux numeros de personne A et B et retournant, si lun est un ascendant
de lautre, le nombre de generations les separant, 1 si lun nest pas un ascendant de lautre.

Exercice 9
Preparez un verre daspirine et ecrivez une requete retournant le(s) couples(s) personnes separees par le plus de
generations.

Exercice 10
Reprendre le code du tp precedent, le decouper en sous-programmes de la facon la moins inintelligente possible.
Bon courage.

32

2.6

Curseurs

Exercice 1
Refaites les exercices de 2.3 en utilisant les curseurs.

Exercice 2
En utlisant les donnees A.5, ecrivez une fonction affichant toute la descendance dune personne.

33

2.7

Curseurs parametr
es

Linteret de ces exercices etant de vous familiariser avec les curseurs parametres, vous ferez en sorte de ne pas
contourner leur usage. Nous utiliserons les donnees de A.6

Exercice 1
Ecrire une procedure qui affiche tous les clients, et pour chaque client, la liste des comptes.

Exercice 2
Ecrire une procedure qui affiche tous les clients, et pour chaque client, la liste des comptes, et pour chacun de ces
comptes, lhistorique des operations.

34

2.8

Triggers

Implementez les contraintes suivantes dans les donnees de les donnees de A.8. Vous ferez des sous-programmes
tenant sur une page, et ne contenant pas plus de trois niveaux dimbrication. Vous repertorierez les numeros derreurs
que vous affecterez a` chaque levee dexception.
1. Il ne doit pas etre possible de modifier la note min dans la table prerequis.
2. Dans un module, il ne doit pas y avoir plus de effecMax el`eves inscrits.
3. On ne peut creer un examen pour un module que sil y a des el`eves inscrits dans ce module.
4. Un el`eve ne peut passer un examen que si sa date dinscription est anterieure `a la date de lexamen.
5. Il ne doit pas y avoir de circuit dans la table prerequis (il existe une facon de la verifier en PL/SQL, mais
comme vous ne la connaissez pas, faites un parcours en profondeur du graphe des pre-requis)
6. Un el`eve sinscrivant `
a un module doit avoir eu au moins la note min `a tous les modules pre-requis.
7. Ajouter dans etudiant un champ moyenne, celui-ci contiendra la moyenne de chaque etudiant sil a passe les
examens de tous les modules dans lesquels il est inscrit.
8. Revenez sur la premi`ere contrainte : il ne doit etre possible de modifier une note min dans la table prerequis que
sil nexiste pas del`eve dont une inscription serait invalidee.
9. Il ne doit etre possible de modifier effecMax que si des etudiants ne se retrouvent pas avec une inscription
invalidee.
Libre `
a vous par la suite de trouver dautres contraintes et de les implementer.

35

2.9

Packages

Exercice 1
Lancez deux sessions simultanement sur le meme serveur et invoquez les sous-programmes du package compteur
depuis chacune des sessions. Que remarquez-vous ?

Exercice 2
Implementer le corps du package suivant (utilisez les donnees de A.5).
CREATE OR R E P L A C E P A C K A G E g e s t i o n _ a r b r e I S
c i r c u i t exception ;
c u r s o r f e u i l l e s r e t u r n p e r s o n n e%r o w t y p e ;
p r o c e d u r e a j o u t e P e r s o n n e ( n o m p e r s o n n e . n o m%t y p e ,
p r e n o m p e r s o n n e . p r e n o m%t y p e , p e r e p e r s o n n e . p e r e%t y p e ,
m e r e p e r s o n n e . m e r e%t y p e ) ;
p r o c e d u r e m o d i f i e P a r e n t s ( p e r s p e r s o n n e . n u m p e r s%t y p e ,
n u m P e r e p e r s o n n e . p e r e%t y p e , n u m M e r e p e r s o n n e . m e r e%t y p e ) ;

END g e s t i o n _ a r b r e ;
/

36

2.10

R
evisions

Implementez les contraintes suivantes dans les donnees de A.9.


1. Les parents dune meme personne sont des personnes differentes.
2. Larbre genealogique ne contient pas de circuit.
3. Les dates de divorce sont ulterieures aux dates de mariage.
4. Une meme personne ne peut pas etre mariee `a plusieurs personnes simultanement.
5. Personne ne peut etre p`ere dune personne et m`ere dune autre.
6. Un mari ne peut pas etre m`ere et une femme ne peut pas etre p`ere.
7. Deux personnes ayant du sang en commun ne peuvent se marier.

37

Chapitre 3

Corrig
es
3.1

Introduction au PL/SQL

E x e r c i c e 1
DECLARE
a NUMBER;
b NUMBER;
t NUMBER;
BEGIN
a := 1 ;
b := 2 ;
DBMS_OUTPUT
DBMS_OUTPUT
DBMS_OUTPUT
t := a ;
a := b ;
b := t ;
DBMS_OUTPUT
DBMS_OUTPUT

. PUT_LINE ( a = | | a ) ;
. PUT_LINE ( b = | | b ) ;
. P U T _ L I N E ( Let s swap a and b . . . The r e s u l t

. PUT_LINE ( a = | | a ) ;
. PUT_LINE ( b = | | b ) ;

END;
/
E x e r c i c e 2
DECLARE
a NUMBER;
r e s NUMBER;
c o u n t e r NUMBER;
BEGIN
a := 1 0 ;
r e s := 1 ;
c o u n t e r := a ;
WHILE counter > 0 LOOP
r e s := r e s c o u n t e r ;
c o u n t e r := c o u n t e r 1 ;
END L O O P ;
D B M S _ O U T P U T . P U T _ L I N E ( a | | != | | r e s ) ;
END;
/
E x e r c i c e 3
DECLARE
a NUMBER := 4 8 ;
b NUMBER := 8 4 ;
a m o d b NUMBER;
BEGIN
D B M S _ O U T P U T . P U T ( PGCD( | | a | | , | | b | | ) = ) ;
WHILE b > 0 LOOP
a m o d b := a ;
W H I L E a m o d b >= b L O O P
a m o d b := a m o d b b ;
END L O O P ;
a := b ;
b := a m o d b ;
END L O O P ;
DBMS_OUTPUT . PUT_LINE ( a ) ;
END;
/

38

is : );

3.2

Tableaux et Structures

SET S E R V E R O U T P U T ON
Tableaux
DECLARE
T Y P E m o n t a b I S V A R R A Y ( 5 0 ) O F INTEGER ;
t montab ;
BEGIN
t := m o n t a b ( ) ;
t . extend ( 2 0 ) ;
I n i t i a l i s a t i o n
F O R i IN 1 . . 2 0 L O O P
t ( i ) := i i ;
END L O O P ;
I n v e r s i o n de l o r d r e d e s
e l
ements
DECLARE
temp i n t e g e r ;
BEGIN
F O R i IN 1 . . 1 0 L O O P
t e m p := t ( i ) ;
t ( i ) := t (20 i + 1 ) ;
t (20 i +1) := t e m p ;
END L O O P ;
END;
A f f i c h a g e
F O R i IN 1 . . 2 0 L O O P
DBMS_OUTPUT . PUT_LINE ( t ( | |
i || ) = || t(i ));
END L O O P ;
Tri `
a bulle
DECLARE
temp i n t e g e r ;
BEGIN
F O R i IN R E V E R S E 2 . . 2 0 L O O P
F O R j IN 2 . . i L O O P
I F t ( j 1 ) > t ( j ) THEN
t e m p := t ( j ) ;
t ( j ) := t ( j 1 ) ;
t ( j 1) := t e m p ;
END I F ;
END L O O P ;
END L O O P ;
END;
A f f i c h a g e
F O R i IN 1 . . 2 0 L O O P
DBMS_OUTPUT . PUT_LINE ( t ( | |
i || ) = || t(i ));
END L O O P ;
Recherche par d i c h o t o m i e de l
e l
e m e n t 225
DECLARE
i n f INTEGER := 1 ;
s u p INTEGER := 2 0 ;
m INTEGER ;
X INTEGER := 4 0 0 ;
BEGIN
LOOP
DBMS_OUTPUT . PUT_LINE ( i n f = | | inf
; sup = | | s u p ) ;
m := ( i n f + s u p ) / 2 ;
E X I T WHEN
t ( m ) = X OR i n f = s u p ;
I F t ( m ) > X THEN
s u p := m 1;
ELSE
i n f := m +1;
END I F ;
END L O O P ;
I F t ( m ) = X THEN
DBMS_OUTPUT . PUT_LINE ( X | |
e s t dans l e t a b l e a u ) ;
ELSE
DBMS_OUTPUT . PUT_LINE ( X | |
n e s t pas dans l e t a b l e a u ) ;
END I F ;
END;
END;
/

39

||

S t r u c t u r e s
DECLARE
M a i l l o n d une l i s t e c h an
ee
TYPE CELL IS RECORD
(
Donn
ee de chaque m a i l l o n
d a t a INTEGER,
I n d i c e du m a i l l o n p r
e c
e d e n t de l a l i s t e ,
1 s i l n y en a pas
p r e v i o u s INTEGER,
I n d i c e du m a i l l o n s u i v a n t de l a l i s t e ,
1 s i l n y en a pas
next INTEGER
);
Type t a b l e a u c o n t e n a n t l e s m a i l l o n s de l a l i s t e
TYPE TREE IS VARRAY ( 1 9 ) OF CELL ;
Tableau c o n t e n a n t l e s m a i l l o n s de l a l i s t e
t TREE ;
i n d i c e du premier
e l
e m e n t de l a l i s t e
first integer ;
i n d i c e du d e r n i e r
e l
e m e n t de l a l i s t e
last integer ;
BEGIN
t := T R E E ( ) ;
t . extend ( 1 9 ) ;
I n i t i a l i s a t i o n
F O R i IN 1 . . 1 9 L O O P
t ( i ) . d a t a := p o w e r ( i , 5 ) m o d 19 ;
t ( i ) . p r e v i o u s := i 1;
t ( i ) . next := i +1;
END L O O P ;
f i r s t := 1 ;
l a s t := 1 9 ;
t ( f i r s t ) . p r e v i o u s := 1;
t ( l a s t ) . next := 1;
A f f i c h a g e
DECLARE
p i n t e g e r := f i r s t ;
BEGIN
W H I L E p <> 1 L O O P
DBMS_OUTPUT . PUT_LINE ( ( | | p | |
t ( p ) . data | | , | |
t ( p ) . previous | | , | |
t ( p ) . next | | ) ) ;
p := t ( p ) . next ;
END L O O P ;
END;

||

I n v e r s i o n de l o r d r e d e s
e l
ements
DECLARE
t e m p INTEGER ;
BEGIN
F O R i IN 1 . . 1 9 L O O P
t e m p := t ( i ) . p r e v i o u s ;
t ( i ) . p r e v i o u s := t ( i ) . next ;
t ( i ) . next := t e m p ;
END L O O P ;
f i r s t := 1 9 ;
l a s t := 1 ;
END;
A f f i c h a g e
DECLARE
p i n t e g e r := f i r s t ;
BEGIN
W H I L E p <> 1 L O O P
DBMS_OUTPUT . PUT_LINE ( ( | |
p || , ||
t ( p ) . data | | , | |
t ( p ) . previous | | ,
t ( p ) . next | | ) ) ;
p := t ( p ) . next ;
END L O O P ;
END;

||

Tri `
a bulle
DECLARE
i i n t e g e r := l a s t ;
j integer ;
BEGIN
W H I L E t ( t ( i ) . p r e v i o u s ) . p r e v i o u s <> 1 L O O P
j := f i r s t ;
W H I L E i<>j L O O P
I F ( t ( j ) . d a t a > t ( t ( j ) . next ) . d a t a ) THEN

40

Echange de j e t t ( j ) . n e x t
par m o d i f i c a t i o n du c h an a g e
DECLARE
a f t e r J INTEGER := t ( j ) . next ;
b e f o r e J INTEGER := t ( j ) . p r e v i o u s ;
BEGIN
t ( j ) . next := t ( a f t e r J ) . next ;
t ( a f t e r J ) . next := j ;
t ( a f t e r J ) . p r e v i o u s := b e f o r e J ;
t ( j ) . p r e v i o u s := a f t e r J ;
I F t ( j ) . next <> 1 THEN
t ( t ( j ) . next ) . p r e v i o u s := j ;
ELSE
l a s t := j ;
END I F ;
I F t ( a f t e r J ) . p r e v i o u s <> 1 THEN
t ( t ( a f t e r J ) . p r e v i o u s ) . next := a f t e r J ;
ELSE
f i r s t := a f t e r J ;
END I F ;
I F a f t e r J = i THEN
i := j ;
END I F ;
END;
ELSE
j := t ( j ) . next ;
END I F ;
END L O O P ;
i := t ( i ) . p r e v i o u s ;
END L O O P ;
END;
A f f i c h a g e
DECLARE
p i n t e g e r := f i r s t ;
BEGIN
W H I L E p <> 1 L O O P
DBMS_OUTPUT . PUT_LINE ( ( | | p | |
t ( p ) . data | | , | |
t ( p ) . previous | | , | |
t ( p ) . next | | ) ) ;
p := t ( p ) . next ;
END L O O P ;
END;
END;
/

41

||

3.3

Application du PL/SQL et Exceptions

SET S E R V E R O U T P U T ON
SET A U T O C O M M I T O F F
E x e r c i c e 1
DECLARE
u n C l i e n t P E R S O N N E%R O W T Y P E ;
n u m C l i e n t P E R S O N N E . n u m p e r s%t y p e ;
Y _ A _ E U _ U N E _ M E R D E EXCEPTION;
BEGIN
F O R n u m C l i e n t IN 1 . . 2 1 L O O P
BEGIN
SELECT INTO u n C l i e n t
FROM P E R S O N N E
WHERE n u m p e r s = n u m C l i e n t ;
INSERT INTO C L I E N T ( n u m c l i , n o m c l i , p r e n o m c l i )
VALUES
( unClient . numpers ,
u n C l i e n t . nom ,
unClient . prenom ) ;
EXCEPTION
WHEN N O _ D A T A _ F O U N D THEN
DBMS_OUTPUT . PUT_LINE (
Personne na l i d e n t i f i a n t | |
numClient ) ;
WHEN T O O _ M A N Y _ R O W S THEN
DBMS_OUTPUT . PUT_LINE (
C e t t e message ne d e v r a i t j a m a i s a p p a r at r e ! ) ;
WHEN D U P _ V A L _ O N _ I N D E X THEN
DBMS_OUTPUT . PUT_LINE (
C o n t r a i n t e de c l
e viol
e e ! Message SQL : | |
SQLERRM ) ;
WHEN O T H E R S THEN
RAISE Y_A_EU_UNE_MERDE ;
END;
END L O O P ;
COMMIT;
EXCEPTION
WHEN Y _ A _ E U _ U N E _ M E R D E THEN
D B M S _ O U T P U T . P U T _ L I N E ( SQLCODE = | | S Q L C O D E ) ;
D B M S _ O U T P U T . P U T _ L I N E ( I l y a eu une Merde ! ) ;
ROLLBACK;
END;
/
E x e r c i c e 2
DECLARE
u n C l i e n t C L I E N T%r o w t y p e ;
BEGIN
SELECT INTO u n C l i e n t
FROM C L I E N T WHERE n u m C l i =
(
SELECT MAX( n u m c l i )
FROM C L I E N T
);
INSERT INTO P E R S O N N E L VALUES
(
1,
unClient . nomcli ,
unClient . prenomcli ,
NULL,
1254.28
);
COMMIT;
EXCEPTION
WHEN N O _ D A T A _ F O U N D THEN
D B M S _ O U T P U T . P U T _ L I N E ( Aucun c l i e n t ) ;
WHEN D U P _ V A L _ O N _ I N D E X THEN
DBMS_OUTPUT . PUT_LINE (
I l y a un g r o s probl`
e me . . . J comprends pas c q u i s p a s s e ) ;
END;
/
E x e r c i c e 3

DECLARE
n u m C l i e n t C L I E N T . n u m c l i%T Y P E ;
t C C L T Y P E C C L . n u m t y p e c c l%T Y P E ;
n t o T Y P E O P E R A T I O N . n u m t y p e o p e r%T Y P E ;
Y _ A _ U N _ G R O _ B L E M E EXCEPTION;
BEGIN
SELECT n u m t y p e o p e r INTO n t o

42

FROM T Y P E O P E R A T I O N
WHERE n o m t y p e o p e r = d
ep
o t e s p`
eces ;
SELECT n u m t y p e c c l INTO t C C L
FROM T Y P E C C L
WHERE n o m t y p e C C L = Compte c o u r a n t ;
F O R n u m C l i e n t IN 1 . . 2 1 L O O P
BEGIN
INSERT INTO C O M P T E C L I E N T VALUES
(
numClient ,
1,
tCCL ,
SYSDATE ,
1
);
INSERT INTO O P E R A T I O N VALUES
(
numClient ,
1,
1,
nto ,
SYSDATE ,
numClient 100 ,
i n a u g u r a t i o n du compte
);
COMMIT;
EXCEPTION
WHEN O T H E R S THEN
Adaptez l e num
ero du code ,
c h e z moi
c a donne 2290
I F S Q L C O D E = 2290 THEN
DECLARE
t o t a l O P E R A T I O N . m o n t a n t o p e r%T Y P E := n u m C l i e n t 1 0 0 ;
t o I n s e r t O P E R A T I O N . m o n t a n t o p e r%T Y P E ;
c p t NUMBER := 1 ;
BEGIN
WHILE total > 0 LOOP
I F t o t a l > 1000 THEN
t o I n s e r t := 1 0 0 0 ;
ELSE
t o I n s e r t := t o t a l ;
END I F ;
INSERT INTO O P E R A T I O N VALUES
(
numClient ,
1,
(SELECT n v l (MAX( n u m o p e r ) , 0 ) + 1
FROM O P E R A T I O N
WHERE n u m c l i = n u m C l i e n t
AND n u m c c l = 1
),
nto ,
SYSDATE ,
toInsert ,
I n a u g u r a t i o n du compte | | c p t
);
t o t a l := t o t a l t o I n s e r t ;
c p t := c p t + 1 ;
END L O O P ;
EXCEPTION
WHEN O T H E R S THEN
D B M S _ O U T P U T . P U T _ L I N E ( MOD( t o t a l , 1000) = | | M O D ( t o t a l ,
D B M S _ O U T P U T . P U T _ L I N E ( SQLCODE = | | S Q L C O D E ) ;
D B M S _ O U T P U T . P U T _ L I N E ( SQLERRM = | | S Q L E R R M ) ;
RAISE Y_A_UN_GRO_BLEME ;
END;
ELSE
D B M S _ O U T P U T . P U T _ L I N E ( SQLCODE = | | S Q L C O D E ) ;
D B M S _ O U T P U T . P U T _ L I N E ( SQLERRM = | | S Q L E R R M ) ;
ROLLBACK;
END I F ;
END;
END L O O P ;
EXCEPTION
WHEN N O _ D A T A _ F O U N D THEN
D B M S _ O U T P U T . P U T _ L I N E ( Pas de donn
e es ! ) ;
WHEN T O O _ M A N Y _ R O W S THEN
D B M S _ O U T P U T . P U T _ L I N E ( Trop de donn
e es ! ) ;
WHEN Y _ A _ U N _ G R O _ B L E M E THEN
D B M S _ O U T P U T . P U T _ L I N E ( I l y a un g r o s probl`
e me ! ) ;
D B M S _ O U T P U T . P U T _ L I N E ( SQLCODE = | | S Q L C O D E ) ;
D B M S _ O U T P U T . P U T _ L I N E ( SQLERRM = | | S Q L E R R M ) ;
WHEN O T H E R S THEN
D B M S _ O U T P U T . P U T _ L I N E ( SQLCODE = | | S Q L C O D E ) ;
D B M S _ O U T P U T . P U T _ L I N E ( SQLERRM = | | S Q L E R R M ) ;
END;
/
E x e r c i c e 4

43

1000));

DECLARE
n u m C l i e n t C L I E N T . n u m c l i%T Y P E := 2 ;
n u m C o m p t e L i v r e t T Y P E C C L . n u m t y p e C C L%T Y P E ;
n t o T Y P E O P E R A T I O N . n u m t y p e o p e r%T Y P E ;
m o n t a n t O P E R A T I O N . m o n t a n t o p e r%T Y P E ;
Y _ A _ U N _ G R O _ B L E M E EXCEPTION;
BEGIN
SELECT n u m t y p e o p e r INTO n t o
FROM T Y P E O P E R A T I O N
WHERE n o m t y p e o p e r = v i r e m e n t ;
SELECT n u m t y p e c c l INTO n u m C o m p t e L i v r e t
FROM T Y P E C C L
WHERE n o m t y p e C c l = l i v r e t ;
W H I L E n u m C l i e n t <= 21 L O O P
BEGIN
m o n t a n t := 100 n u m C l i e n t 5 0 0 ;
INSERT INTO C O M P T E C L I E N T VALUES
(
numClient ,
2,
numCompteLivret ,
SYSDATE ,
1
);
INSERT INTO O P E R A T I O N VALUES
(
numClient ,
1,
(SELECT n v l (MAX( n u m o p e r ) , 0 ) + 1
FROM O P E R A T I O N
WHERE n u m c l i = n u m C l i e n t
AND n u m c c l = 1 ) ,
nto ,
SYSDATE ,
m o n t a n t ,
versement l i v r e t
);
INSERT INTO O P E R A T I O N VALUES
(
numClient ,
2,
(SELECT n v l (MAX( n u m o p e r ) , 0 ) + 1
FROM O P E R A T I O N
WHERE n u m c l i = n u m C l i e n t
AND n u m c c l = 2 ) ,
nto ,
SYSDATE ,
montant ,
versement l i v r e t
);
COMMIT;
EXCEPTION
WHEN O T H E R S THEN
idem
I F S Q L C O D E = 2290 THEN
DECLARE
t o t a l O P E R A T I O N . m o n t a n t o p e r%T Y P E := m o n t a n t ;
t o M o v e O P E R A T I O N . m o n t a n t o p e r%T Y P E ;
c p t NUMBER := 1 ;
BEGIN
W H I L E t o t a l > 1000 L O O P
I F t o t a l > 1000 THEN
t o M o v e := 1 0 0 0 ;
ELSE
t o m o v e := t o t a l ;
END I F ;
INSERT INTO O P E R A T I O N VALUES
(
numClient ,
1,
(SELECT n v l (MAX( n u m o p e r ) , 0 ) + 1
FROM O P E R A T I O N
WHERE n u m c l i = n u m C l i e n t
AND n u m c c l = 1 ) ,
nto ,
SYSDATE ,
t o M o v e ,
versement l i v r e t | | c p t
);
INSERT INTO O P E R A T I O N VALUES
(
numClient ,
2,
(SELECT n v l (MAX( n u m o p e r ) , 0 ) + 1
FROM O P E R A T I O N
WHERE n u m c l i = n u m C l i e n t
AND n u m c c l = 2 ) ,
nto ,

44

SYSDATE ,
toMove ,
versement l i v r e t
);
t o t a l := t o t a l t o M o v e ;
c p t := c p t + 1 ;
END L O O P ;
COMMIT;
EXCEPTION
WHEN O T H E R S THEN
RAISE Y_A_UN_GRO_BLEME ;
END;

||

ELSE
D B M S _ O U T P U T . P U T _ L I N E ( SQLCODE =
D B M S _ O U T P U T . P U T _ L I N E ( SQLERRM =
ROLLBACK;
END I F ;
END;
COMMIT;
n u m C l i e n t := n u m C l i e n t + 2 ;
END L O O P ;
EXCEPTION
WHEN N O _ D A T A _ F O U N D THEN
D B M S _ O U T P U T . P U T _ L I N E ( Pas de donn
e es ! ) ;
WHEN T O O _ M A N Y _ R O W S THEN
D B M S _ O U T P U T . P U T _ L I N E ( Trop de donn
e es ! ) ;
WHEN Y _ A _ U N _ G R O _ B L E M E THEN
D B M S _ O U T P U T . P U T _ L I N E ( I l y a un g r o s probl`
e me ! ) ;
D B M S _ O U T P U T . P U T _ L I N E ( SQLCODE = | | S Q L C O D E ) ;
D B M S _ O U T P U T . P U T _ L I N E ( SQLERRM = | | S Q L E R R M ) ;
WHEN O T H E R S THEN
D B M S _ O U T P U T . P U T _ L I N E ( SQLCODE = | | S Q L C O D E ) ;
D B M S _ O U T P U T . P U T _ L I N E ( SQLERRM = | | S Q L E R R M ) ;
END;
/

45

||
||

SQLCODE ) ;
SQLERRM ) ;

cpt

3.4

Sous-programmes

E x e r c i c e 1
CREATE OR R E P L A C E F U N C T I O N
b a d _ p u i s s a n c e ( b NUMBER, n NUMBER)
R E T U R N NUMBER I S
BEGIN
I F ( n = 0 ) THEN
RETURN 1;
ELSE
RETURN b bad_puissance ( b , n 1 ) ;
END I F ;
END;
/
E x e r c i c e 2
CREATE OR R E P L A C E F U N C T I O N
g o o d _ p u i s s a n c e ( b NUMBER, n NUMBER)
R E T U R N NUMBER I S
BEGIN
I F ( n = 0 ) THEN
RETURN 1;
END I F ;
I F ( M O D ( n , 2 ) = 0 ) THEN
RETURN good_puissance ( b b , n / 2 ) ;
END I F ;
RETURN b good_puissance ( b , n 1 ) ;
END;
/
E x e r c i c e 3
CREATE OR R E P L A C E F U N C T I O N
d e m i F r e r e s ( A P E R S O N N E . n u m p e r s%t y p e , B P E R S O N N E . n u m p e r s%t y p e )
RETURN B O O L E A N IS
r o w A P E R S O N N E%r o w t y p e ;
r o w B P E R S O N N E%r o w t y p e ;
BEGIN
SELECT INTO r o w A FROM P E R S O N N E WHERE n u m p e r s = A ;
SELECT INTO r o w B FROM P E R S O N N E WHERE n u m p e r s = B ;
R E T U R N r o w A . p e r e = r o w B . p e r e OR r o w A . m e r e = r o w B . m e r e ;
END;
/
E x e r c i c e 4
CREATE OR R E P L A C E F U N C T I O N
f r e r e s ( A P E R S O N N E . n u m p e r s%t y p e , B P E R S O N N E . n u m p e r s%t y p e )
RETURN B O O L E A N IS
r o w A P E R S O N N E%r o w t y p e ;
r o w B P E R S O N N E%r o w t y p e ;
BEGIN
SELECT INTO r o w A FROM P E R S O N N E WHERE n u m p e r s = A ;
SELECT INTO r o w B FROM P E R S O N N E WHERE n u m p e r s = B ;
R E T U R N r o w A . p e r e = r o w B . p e r e AND r o w A . m e r e = r o w B . m e r e ;
END;
/
CREATE OR R E P L A C E F U N C T I O N
c o u s i n s G e r m a i n s ( A P E R S O N N E . n u m p e r s%t y p e , B P E R S O N N E . n u m p e r s%t y p e )
RETURN B O O L E A N IS
r o w A P E R S O N N E%r o w t y p e ;
r o w B P E R S O N N E%r o w t y p e ;
BEGIN
SELECT INTO r o w A FROM P E R S O N N E WHERE n u m p e r s = A ;
SELECT INTO r o w B FROM P E R S O N N E WHERE n u m p e r s = B ;
RETURN
freres ( rowA . pere , rowB . pere )
OR
freres ( rowA . pere , rowB . mere )
OR
freres ( rowA . mere , rowB . pere )
OR
freres ( rowA . mere , rowB . mere ) ;
END;
/
E x e r c i c e 5
CREATE OR R E P L A C E P R O C E D U R E
a i e u l ( P P E R S O N N E . n u m p e r s%t y p e ) I S
r o w P E R S O N N E%r o w t y p e ;
n b NUMBER;
BEGIN
SELECT count ( ) INTO N B
FROM P E R S O N N E

46

WHERE n u m p e r s = P ;
I F ( N B = 1 ) THEN
SELECT INTO r o w
FROM P E R S O N N E
WHERE n u m p e r s = P ;
DBMS_OUTPUT . PUT_LINE ( row . nom ) ;
aieul ( row . pere ) ;
END I F ;
END;
/
E x e r c i c e 6
CREATE OR R E P L A C E P R O C E D U R E
m e c s ( P P E R S O N N E . n u m p e r s%t y p e ) I S
r o w P E R S O N N E%r o w t y p e ;
n b NUMBER;
BEGIN
SELECT count ( ) INTO N B
FROM P E R S O N N E
WHERE n u m p e r s = P ;
I F ( N B = 1 ) THEN
SELECT INTO r o w
FROM P E R S O N N E
WHERE n u m p e r s = P ;
SELECT count ( ) INTO N B
FROM P E R S O N N E
WHERE p e r e = P ;
I F ( N B > 0 ) THEN
DBMS_OUTPUT . PUT_LINE ( row . nom ) ;
END I F ;
mecs ( row . pere ) ;
mecs ( row . mere ) ;
END I F ;
END;
/
E x e r c i c e 7
CREATE OR R E P L A C E F U N C T I O N
a s c e n d a n t ( A P E R S O N N E . n u m p e r s%t y p e , B P E R S O N N E . n u m p e r s%t y p e )
RETURN B O O L E A N IS
r o w P E R S O N N E%r o w t y p e ;
BEGIN
SELECT INTO r o w FROM P E R S O N N E WHERE n u m p e r s = B ;
I F ( r o w . p e r e = A OR r o w . m e r e = A ) THEN
R E T U R N TRUE;
END I F ;
R E T U R N ( r o w . p e r e I S NOT NULL AND a s c e n d a n t ( A , r o w . p e r e ) )
OR
( r o w . m e r e I S NOT NULL AND a s c e n d a n t ( A , r o w . m e r e ) ) ;
END;
/
BEGIN
I F ( a s c e n d a n t ( 1 , 8 ) ) THEN
D B M S _ O U T P U T . P U T _ L I N E ( OK ) ;
ELSE
D B M S _ O U T P U T . P U T _ L I N E ( pas OK ) ;
END I F ;
END;
/
E x e r c i c e 8
CREATE OR R E P L A C E F U N C T I O N
f m a x ( A NUMBER, B NUMBER)
R E T U R N NUMBER I S
BEGIN
I F ( A > B ) THEN
RETURN A ;
ELSE
RETURN B ;
END I F ;
END;
/
CREATE OR R E P L A C E F U N C T I O N
e c a r t A s c e n d a n t ( A P E R S O N N E . n u m p e r s%t y p e , B P E R S O N N E . n u m p e r s%t y p e )
R E T U R N NUMBER I S
r o w P E R S O N N E%r o w t y p e ;
N B NUMBER;
BEGIN
SELECT INTO r o w FROM P E R S O N N E WHERE n u m p e r s = B ;
I F ( r o w . p e r e = A OR r o w . m e r e = A ) THEN
RETURN 1;
END I F ;
I F ( r o w . p e r e I S NULL) THEN

47

N B := 1;
ELSE
N B := e c a r t A s c e n d a n t ( A , r o w . p e r e ) ;
END I F ;
I F ( r o w . m e r e I S NULL) THEN
N B := f m a x ( 1 , N B ) ;
ELSE
N B := f m a x ( e c a r t A s c e n d a n t ( A , r o w . p e r e ) , N B ) ;
END I F ;
I F ( N B <> 1) THEN
N B := N B + 1 ;
END I F ;
RETURN NB ;
END;
/
CREATE OR R E P L A C E F U N C T I O N
e c a r t ( A P E R S O N N E . n u m p e r s%t y p e , B P E R S O N N E . n u m p e r s%t y p e )
R E T U R N NUMBER I S
r o w P E R S O N N E%r o w t y p e ;
N B NUMBER;
BEGIN
RETURN fmax ( ecartAscendant ( A , B ) , ecartAscendant ( B , A ) ) ;
END;
/
E x e r c i c e 9
SELECT A . nom , A . p r e n o m , B . nom , B . p r e n o m
FROM P E R S O N N E A , P E R S O N N E B
WHERE e c a r t A s c e n d a n t ( A . n u m p e r s , B . n u m p e r s ) =
(
SELECT MAX( e c )
FROM
(
SELECT e c a r t ( A . n u m p e r s , B . n u m p e r s ) AS e c
FROM P E R S O N N E A , P E R S O N N E B
)
);
E x e r c i c e 10

48

3.5

Curseurs

CREATE OR R E P L A C E P R O C E D U R E c o p y F r o m P e r s o n n e T o C l i e n t I S
CURSOR C IS
SELECT
FROM P E R S O N N E ;
R O W C%r o w t y p e ;
BEGIN
F O R R O W IN C L O O P
INSERT INTO C L I E N T
( numcli , nomcli , prenomcli )
VALUES
( R O W . n u m p e r s , R O W . nom , R O W . p r e n o m ) ;
END L O O P ;
COMMIT;
EXCEPTION
WHEN D U P _ V A L _ O N _ I N D E X THEN
D B M S _ O U T P U T . P U T _ L I N E ( Copy can be done o n l y once . ) ;
END;
/
CALL copyFromPersonneToClient ( ) ;
CREATE OR R E P L A C E P R O C E D U R E t a k e C l i e n t T o P e r s o n n e l I S
R o w c l i e n t%r o w t y p e ;
BEGIN
SELECT INTO R o w
FROM C L I E N T
WHERE n u m c l i =
(
SELECT MAX( n u m c l i )
FROM C L I E N T ) ;
INSERT INTO P E R S O N N E L
( numpers , nompers , prenompers )
VALUES
( Row . numcli , Row . nomcli , Row . prenomcli ) ;
COMMIT;
EXCEPTION
WHEN D U P _ V A L _ O N _ I N D E X THEN
D B M S _ O U T P U T . P U T _ L I N E ( This row has a l r e a d y been imported . ) ;
ROLLBACK;
WHEN N O _ D A T A _ F O U N D THEN
D B M S _ O U T P U T . P U T _ L I N E ( Table CLIENT i s empty . ) ;
ROLLBACK;
END;
/
CALL takeClientToPersonnel ( ) ;
CREATE OR R E P L A C E P R O C E D U R E
c r e d i t A c c o u n t ( n u m c l i e n t C L I E N T . n u m c l i%t y p e , value NUMBER) I S
BEGIN
I F ( value > 1 0 0 ) THEN
creditAccount ( numclient , 100);
c r e d i t A c c o u n t ( n u m c l i e n t , value 1 0 0 ) ;
ELSE
INSERT INTO O P E R A T I O N VALUES
( numclient ,
1,
(SELECT n v l (MAX( n u m o p e r ) , 0 ) + 1
FROM O P E R A T I O N
WHERE n u m c l i = n u m c l i e n t
AND n u m c c l = 1
),
(SELECT n u m t y p e o p e r
FROM T Y P E O P E R A T I O N
WHERE n o m t y p e o p e r = v i r e m e n t
),
sysdate ,
value ,
cadeau !
);
END I F ;
EXCEPTION
WHEN O T H E R S THEN
I F ( S Q L C O D E = 22900) THEN
D B M S _ O U T P U T . P U T _ L I N E ( Too much money a t once . ) ;
END I F ;
END;
/
CREATE OR R E P L A C E P R O C E D U R E
c r e a t e V i r e m e n t ( n u m c l i e n t C L I E N T . n u m c l i%t y p e , value NUMBER) I S
BEGIN
INSERT INTO O P E R A T I O N VALUES
( numclient ,
1,
(SELECT n v l (MAX( n u m o p e r ) , 0 ) + 1

49

FROM O P E R A T I O N
WHERE n u m c l i = n u m c l i e n t
AND n u m c c l = 1
),
(SELECT n u m t y p e o p e r
FROM T Y P E O P E R A T I O N
WHERE n o m t y p e o p e r = v i r e m e n t
),
sysdate ,
value ,
cadeau !
);
INSERT INTO O P E R A T I O N VALUES
( numclient ,
2,
(SELECT n v l (MAX( n u m o p e r ) , 0 ) + 1
FROM O P E R A T I O N
WHERE n u m c l i = n u m c l i e n t
AND n u m c c l = 1
),
(SELECT n u m t y p e o p e r
FROM T Y P E O P E R A T I O N
WHERE n o m t y p e o p e r = v i r e m e n t
),
sysdate ,
value ,
cadeau !
);
EXCEPTION
WHEN O T H E R S THEN
I F ( S Q L C O D E = 22900) THEN
D B M S _ O U T P U T . P U T _ L I N E ( Too much money a t once . ) ;
END I F ;
END;
/
CREATE OR R E P L A C E P R O C E D U R E
m o v e T o L i v r e t ( n u m c l i e n t C L I E N T . n u m c l i%t y p e , value NUMBER) I S
BEGIN
I F ( value >= 0 ) THEN
I F ( value > 1 0 0 ) THEN
moveToLivret ( numclient , 100);
m o v e T o L i v r e t ( n u m c l i e n t , value 1 0 0 ) ;
ELSE
c r e a t e V i r e m e n t ( n u m c l i e n t , value ) ;
END I F ;
END I F ;
EXCEPTION
WHEN O T H E R S THEN
I F ( S Q L C O D E = 22900) THEN
D B M S _ O U T P U T . P U T _ L I N E ( Too much money a t once . ) ;
END I F ;
END;
/
CREATE OR R E P L A C E P R O C E D U R E
o p e n A c c o u n t ( n u m c l i e n t C L I E N T . n u m c l i%t y p e ) I S
BEGIN
INSERT INTO C O M P T E C L I E N T VALUES
( numclient ,
1,
(SELECT n u m t y p e c c l
FROM T Y P E C C L
WHERE n o m t y p e c c l = Compte c o u r a n t
),
sysdate ,
(SELECT n u m p e r s
FROM P E R S O N N E L
WHERE n u m p e r s =
(
SELECT MAX( n u m c l i )
FROM C L I E N T
)
)
);
INSERT INTO C O M P T E C L I E N T VALUES
( numclient ,
2,
(SELECT n u m t y p e c c l
FROM T Y P E C C L
WHERE n o m t y p e c c l = v i r e m e n t
),
sysdate ,
(SELECT n u m p e r s
FROM P E R S O N N E L
WHERE n u m p e r s =
(
SELECT MAX( n u m c l i )
FROM C L I E N T

50

)
)
);
creditAccount ( numclient , numclient 100);
m o v e T o L i v r e t ( n u m c l i e n t , n u m c l i e n t 100 5 0 0 ) ;
EXCEPTION
WHEN D U P _ V A L _ O N _ I N D E X THEN
D B M S _ O U T P U T . P U T _ L I N E ( This ac co un t has a l r e a d y been opened . ) ;
END;
/
CREATE OR R E P L A C E P R O C E D U R E o p e n A c c o u n t s I S
CURSOR C IS
SELECT n u m c l i FROM C L I E N T ;
R O W C%r o w t y p e ;
BEGIN
F O R R O W IN C L O O P
openAccount ( ROW . numcli ) ;
END L O O P ;
COMMIT;
EXCEPTION
WHEN O T H E R S THEN
D B M S _ O U T P U T . P U T _ L I N E ( An e r r o r has o c c u r r e d . ) ;
ROLLBACK;
END;
/
CALL openAccounts ( ) ;
CREATE OR R E P L A C E P R O C E D U R E
a f f i c h e D e s c e n d a n c e ( n u m p e r s o n n e NUMBER) I S
CURSOR C IS
SELECT
FROM P E R S O N N E
WHERE p e r e = n u m p e r s o n n e
OR m e r e = n u m p e r s o n n e ;
R O W C%r o w T y p e ;
BEGIN
F O R R O W IN C L O O P
DBMS_OUTPUT . PUT_LINE ( row . nom | | | | row . prenom ) ;
afficheDescendance ( ROW . numpers ) ;
END L O O P ;
END;
/

51

3.6

Curseurs param
etr
es

E x e r c i c e 1
CREATE OR R E P L A C E P R O C E D U R E a f f i c h e C l i e n t ( u n C l i e n t C L I E N T%r o w t y p e ) I S
BEGIN
DBMS_OUTPUT . PUT_LINE ( Client | | unClient . prenomcli | | | |
END;
/

unClient . nomCli ) ;

CREATE OR R E P L A C E P R O C E D U R E a f f i c h e C o m p t e ( u n C o m p t e C O M P T E C L I E N T%r o w t y p e ) I S
BEGIN
D B M S _ O U T P U T . P U T _ L I N E ( Compte | | u n C o m p t e . n u m C l i | | | | u n C o m p t e . n u m c c l ) ;
END;
/
CREATE OR R E P L A C E P R O C E D U R E a f f i c h e C o m p t e s C l i e n t s I S
CURSOR c l i e n t s IS
SELECT
FROM C L I E N T ;
u n C l i e n t c l i e n t s%r o w t y p e ;
C U R S O R c o m p t e s ( n u m c l i e n t C L I E N T . n u m c l i%t y p e ) I S
SELECT
FROM C O M P T E C L I E N T
WHERE n u m c l i = n u m c l i e n t ;
u n C o m p t e c l i e n t s%r o w t y p e ;
BEGIN
F O R u n C l i e n t IN c l i e n t s L O O P
afficheClient ( unClient ) ;
F O R u n C o m p t e IN c o m p t e s ( u n C l i e n t . n u m c l i ) L O O P
afficheCompte ( unCompte ) ;
END L O O P ;
END L O O P ;
END;
/
SET S E R V E R O U T P U T ON SIZE 1 00 00 0 0
call afficheComptesClients ( ) ;
E x e r c i c e 2
CREATE OR R E P L A C E P R O C E D U R E a f f i c h e O p e r a t i o n ( u n e O p e r a t i o n O P E R A T I O N%r o w t y p e ) I S
BEGIN
D B M S _ O U T P U T . P U T _ L I N E ( Operation | | u n e O p e r a t i o n . n u m O p e r | | , montant :
END;
/

||

uneOperation . montantOper )

CREATE OR R E P L A C E P R O C E D U R E a f f i c h e O p e r C o m p t e s C l i e n t s I S
CURSOR c l i e n t s IS
SELECT
FROM C L I E N T ;
u n C l i e n t c l i e n t s%r o w t y p e ;
C U R S O R c o m p t e s ( n u m c l i e n t C L I E N T . n u m c l i%t y p e ) I S
SELECT
FROM C O M P T E C L I E N T
WHERE n u m c l i = n u m c l i e n t ;
u n C o m p t e c l i e n t s%r o w t y p e ;
CURSOR operations
( n u m c l i e n t C L I E N T . n u m c l i%t y p e ,
n u m c o m p t e C O M P T E C L I E N T . n u m c c l%t y p e ) I S
SELECT
FROM O P E R A T I O N
WHERE n u m c l i = n u m c l i e n t
AND n u m c c l = n u m c o m p t e ;
u n e O p e r a t i o n o p e r a t i o n s%r o w t y p e ;
BEGIN
F O R u n C l i e n t IN c l i e n t s L O O P
afficheClient ( unClient ) ;
F O R u n C o m p t e IN c o m p t e s ( u n C l i e n t . n u m c l i ) L O O P
afficheCompte ( unCompte ) ;
F O R u n e O p e r a t i o n IN o p e r a t i o n s ( u n C l i e n t . n u m c l i , u n C o m p t e . n u m c c l ) L O O P
afficheOperation ( uneOperation ) ;
END L O O P ;
END L O O P ;
END L O O P ;
END;
/
call afficheOperComptesClients ( ) ;

52

3.7

Triggers

I l c o n v i e n t d abord de m o d i f i e r q u e l q u e peu l o r g a n i s a t i o n d e s
donnees , on a j o u t e par exemple dans l a t a b l e MODULE l e nombre
d e t u d i a n t s i n s c r i t s
DROP
DROP
DROP
DROP
DROP
DROP

TABLE
TABLE
TABLE
TABLE
TABLE
TABLE

RESULTAT ;
EXAMEN ;
PREREQUIS ;
INSCRIPTION ;
MODULE ;
ETUDIANT ;

CREATE TABLE E T U D I A N T
( n u m E t u d number ,
n o m varchar2 ( 4 0 ) ,
p r e n o m varchar2 ( 4 0 ) ,
d a t e n a i s s date ,
c i v i l i t e varchar2 ( 4 ) ,
p a t r o n y m e varchar2 ( 4 0 ) ,
n u m s e c u varchar2 ( 1 5 ) NOT NULL,
m o y e n n e NUMBER DEFAULT NULL) ;
CREATE TABLE M O D U L E
( c o d M o d number ,
n o m M o d varchar2 ( 1 5 ) ,
e f f e c M a x number DEFAULT 3 0 ,
e f f e c number d e f a u l t 0 ) ;
CREATE TABLE E X A M E N
( c o d M o d number ,
c o d E x a m number ,
dateExam date ) ;
CREATE TABLE I N S C R I P T I O N
( n u m E t u d number ,
c o d M o d number ,
dateInsc date default sysdate ) ;
CREATE TABLE P R E R E Q U I S
( c o d M o d number ,
c o d M o d P r e r e q number ,
n o t e M i n number ( 4 , 2 ) NOT NULL) ;
CREATE TABLE R E S U L T A T
( c o d M o d number ,
c o d E x a m number ,
n u m E t u d number ,
n o t e number ( 4 , 2 ) ) ;
ALTER TABLE E T U D I A N T ADD
CONSTRAINT p k _ e t u d i a n t
PRIMARY KEY ( n u m E t u d ) ;
ALTER TABLE M O D U L E ADD
CONSTRAINT p k _ m o d u l e
PRIMARY KEY ( c o d M o d ) ;
ALTER TABLE E X A M E N ADD
CONSTRAINT p k _ e x a m e n
PRIMARY KEY ( c o d M o d , c o d E x a m ) ;
ALTER TABLE P R E R E Q U I S ADD
CONSTRAINT p k _ p r e r e q u i s
PRIMARY KEY ( c o d M o d , c o d M o d P r e r e q ) ;
ALTER TABLE I N S C R I P T I O N ADD
CONSTRAINT p k _ i n s c r i p t i o n
PRIMARY KEY ( c o d M o d , n u m E t u d ) ;
ALTER TABLE R E S U L T A T ADD
CONSTRAINT p k _ r e s u l t a t
PRIMARY KEY ( c o d M o d , n u m E t u d , c o d E x a m ) ;
ALTER TABLE I N S C R I P T I O N ADD
(CONSTRAINT f k _ i n s c r i p t i o n _ e t u d i a n t
FOREIGN KEY ( n u m E t u d )
REFERENCES ETUDIANT ( numEtud ) ,
CONSTRAINT f k _ i n s c r i p t i o n _ m o d u l e
FOREIGN KEY ( c o d M o d )
REFERENCES MODULE ( codMod ) ) ;
ALTER TABLE P R E R E Q U I S ADD
(CONSTRAINT f k _ p r e r e q u i s _ c o d m o d
FOREIGN KEY ( c o d M o d )
REFERENCES MODULE ( codMod ) ,
CONSTRAINT f k _ p r e r e q u i s _ c o d m o d p r e r e q
FOREIGN KEY ( c o d M o d P r e r e q )
REFERENCES MODULE ( codMod ) ) ;
ALTER TABLE E X A M E N ADD
CONSTRAINT f k _ e x a m e n
FOREIGN KEY ( c o d M o d )
REFERENCES MODULE ( codMod ) ;
ALTER TABLE R E S U L T A T ADD

53

(CONSTRAINT f k _ r e s u l t a t _ e x a m e n
FOREIGN KEY ( c o d M o d , c o d E x a m )
REFERENCES EXAMEN ( codMod , codExam ) ,
CONSTRAINT f k _ r e s u l t a t _ i n s c r i p t i o n
FOREIGN KEY ( c o d M o d , n u m E t u d )
REFERENCES INSCRIPTION ( codMod , numEtud ) ) ;
ALTER TABLE E T U D I A N T ADD
(CONSTRAINT c k _ c i v i l i t e
CHECK
(
c i v i l i t e IN ( Mr , Mme , M l l e )
),
CONSTRAINT c k _ c i v i l i t e _ n u m s e c u
CHECK
(
SUBSTR( n u m s e c u , 1 , 1 ) = 2 OR p a t r o n y m e I S NULL
),
CONSTRAINT c k _ l e n g t h _ n u m s e c u
CHECK
(
l e n g t h ( n u m s e c u ) = 15
),
CONSTRAINT c k _ a n n e e _ n u m s e c u CHECK
(
t o _ c h a r ( d a t e n a i s s , yy ) = substr ( n u m s e c u , 2 , 2 )
)
);

C o n t r a i n t e 1

CREATE OR R E P L A C E TRIGGER b e f o r e U p d a t e F E R P r e r e q u i s
B E F O R E UPDATE ON P R E R E Q U I S
FOR EACH ROW
BEGIN
I F ( : n e w . n o t e M i n < : o l d . n o t e M i n ) THEN
: n e w . n o t e M i n := : o l d . n o t e M i n ;
END I F ;
END;
/

C o n t r a i n t e 2

CREATE OR R E P L A C E P R O C E D U R E i n c r E f f e c ( m o d u l e NUMBER) I S
BEGIN
UPDATE M O D U L E SET e f f e c = e f f e c + 1 WHERE c o d m o d = m o d u l e ;
END;
/

CREATE OR R E P L A C E P R O C E D U R E d e c r E f f e c ( m o d u l e NUMBER) I S
BEGIN
UPDATE M O D U L E SET e f f e c = e f f e c 1 WHERE c o d m o d = m o d u l e ;
END;
/

CREATE OR R E P L A C E TRIGGER B e f o r e I n s e r t F E R M o d u l e
B E F O R E INSERT ON M O D U L E
FOR EACH ROW
BEGIN
: n e w . e f f e c := 0 ;
END;
/

CREATE OR R E P L A C E TRIGGER a f t e r I n s e r t F E R I n s c
A F T E R INSERT ON I N S C R I P T I O N
FOR EACH ROW
BEGIN
incrEffec ( : new . codmod ) ;
END;
/

54

CREATE OR R E P L A C E TRIGGER a f t e r D e l e t e F E R I n s c
A F T E R DELETE ON I N S C R I P T I O N
FOR EACH ROW
BEGIN
decrEffec ( : old . codmod ) ;
END;
/

CREATE OR R E P L A C E TRIGGER a f t e r U p d a t e F E R I n s c
A F T E R UPDATE ON I N S C R I P T I O N
FOR EACH ROW
BEGIN
decrEffec ( : old . codmod ) ;
incrEffec ( : new . codmod ) ;
END;
/

DROP VIEW m o d u l e s D i s p o n i b l e s ;
CREATE VIEW m o d u l e s D i s p o n i b l e s AS
SELECT c o d m o d
FROM M O D U L E
WHERE e f f e c < e f f e c M a x ;

CREATE OR R E P L A C E TRIGGER b e f o r e I n s e r t U p d a t e F E R I n s c
B E F O R E INSERT OR UPDATE ON I N S C R I P T I O N
FOR EACH ROW
DECLARE
n b L i g n e s NUMBER;
BEGIN
SELECT count ( ) INTO n b L i g n e s
FROM m o d u l e s D i s p o n i b l e s
WHERE c o d m o d = : n e w . c o d m o d ;
I F ( n b L i g n e s = 0 ) THEN
R A I S E _ A P P L I C A T I O N _ E R R O R ( 20001 , P l u s de p l a c e s d i p o n i b l e s . ) ;
END I F ;
END;
/

C o n t r a i n t e 3

DROP VIEW e x a m e n s P o s s i b l e s ;
CREATE VIEW e x a m e n s P o s s i b l e s AS
SELECT c o d M o d
FROM M O D U L E M
WHERE
(
SELECT COUNT( )
FROM I N S C R I P T I O N I
WHERE I . c o d m o d = M . c o d m o d
) > 0 ;

CREATE OR R E P L A C E TRIGGER b e f o r e I n s e r t U p d a t e F E R E x a m
B E F O R E INSERT OR UPDATE ON E X A M E N
FOR EACH ROW
DECLARE
n b L i g n e s NUMBER;
BEGIN
SELECT count ( ) INTO n b L i g n e s
FROM e x a m e n s P o s s i b l e s
WHERE c o d M o d = : n e w . c o d m o d ;
I F ( n b L i g n e s = 0 ) THEN
R A I S E _ A P P L I C A T I O N _ E R R O R ( 20002 , Pas d
el`
e v e dans ce module . ) ;
END I F ;
END;
/

55


C o n t r a i n t e 4

DROP VIEW e t u d i a n t s E x a m e n s ;
CREATE VIEW e t u d i a n t s E x a m e n s AS
SELECT I . n u m e t u d , E . c o d m o d , E . c o d e x a m
FROM I N S C R I P T I O N I , E X A M E N E
WHERE I . c o d m o d = E . c o d m o d
AND I . d a t e I n s c < E . d a t e E x a m ;

CREATE OR R E P L A C E TRIGGER b e f o r e I n s e r t U p d a t e F E R R e s u l t
B E F O R E INSERT OR UPDATE ON R E S U L T A T
FOR EACH ROW
DECLARE
n b L i g n e s NUMBER;
BEGIN
SELECT count ( ) INTO n b L i g n e s
FROM e t u d i a n t s E x a m e n s
WHERE n u m e t u d = : n e w . n u m e t u d
AND c o d m o d = : n e w . c o d m o d
AND c o d e x a m = : n e w . c o d e x a m ;
I F ( n b L i g n e s = 0 ) THEN
R A I S E _ A P P L I C A T I O N _ E R R O R ( 20002 , Examen a n t
erieur `
a l i n s c r i p t i o n dans l e module . ) ;
END I F ;
END;
/

C o n t r a i n t e 5

On c r
e e une t a b l e t e m p o r a i r e c o n t e n a n t l e s m
emes v a l e u r s que p r e r e q u i s ,
On l a met `
a j o u r AVANT l a t a b l e p r e r e q u i s pour v
e r i f i e r que l i n s e r t i o n
ne c o n s t r u i t pas de c i r c u i t .
DROP TABLE M I R R O R P R E R E Q ;
CREATE TABLE M I R R O R P R E R E Q
( c o d m o d NUMBER,
c o d m o d p r e r e q NUMBER,
n o t e M i n NUMBER) ;

CREATE OR R E P L A C E F U N C T I O N
f i n d M o d u l e ( r o o t number , m o d u l e T o F i n d number)
RETURN BOOLEAN
IS
CURSOR C IS
SELECT c o d m o d
FROM M I R R O R P R E R E Q
WHERE c o d m o d p r e r e q = r o o t ;
S O N C%r o w t y p e ;
BEGIN
F O R S O N IN C L O O P
IF
( s o n . c o d m o d = m o d u l e T o F i n d OR
findModule ( son . codmod , moduleToFind ) )
THEN
R E T U R N TRUE;
END I F ;
END L O O P ;
R E T U R N FALSE;
END;
/

CREATE OR R E P L A C E P R O C E D U R E
i n s e r t M i r r o r P r e r e q ( c o d m o d V a l u e NUMBER, c o d m o d p r e r e q V a l u e NUMBER, n o t e NUMBER) I S
BEGIN
INSERT INTO M I R R O R P R E R E Q
( codmod , codmodprereq , noteMin )
VALUES
( codmodValue , codmodprereqValue , note ) ;
END;
/

56

CREATE OR R E P L A C E P R O C E D U R E
d e l e t e M i r r o r P r e r e q ( c o d m o d V a l u e NUMBER, c o d m o d p r e r e q V a l u e NUMBER) I S
BEGIN
DELETE FROM M I R R O R P R E R E Q
WHERE c o d m o d = c o d m o d V a l u e
AND c o d m o d p r e r e q = c o d m o d p r e r e q V a l u e ;
END;
/

CREATE OR R E P L A C E P R O C E D U R E
updateMirrorPrereq
( c o d m o d V a l u e NUMBER,
c o d m o d N e w V a l u e NUMBER,
c o d m o d p r e r e q V a l u e NUMBER,
c o d m o d p r e r e q N e w V a l u e NUMBER,
n e w N o t e NUMBER) I S
BEGIN
UPDATE M I R R O R P R E R E Q SET
codmod = codmodNewValue ,
codmodprereq = codmodprereqNewValue ,
noteMin = newNote
WHERE c o d m o d = c o d m o d V a l u e
AND c o d m o d p r e r e q = c o d m o d p r e r e q V a l u e ;
END;
/

CREATE OR R E P L A C E TRIGGER a f t e r D e l e t e F E R P r e r e q
A F T E R DELETE ON P R E R E Q U I S
FOR EACH ROW
BEGIN
deleteMirrorPrereq ( : old . codmod , : old . codmodprereq ) ;
END;
/

CREATE OR R E P L A C E TRIGGER b e f o r e I n s e r t U p d a t e F E R P r e r e q
B E F O R E INSERT OR UPDATE ON P R E R E Q U I S
FOR EACH ROW
BEGIN
I F I N S E R T I N G THEN
insertMirrorPrereq ( : new . codmod , : new . codmodprereq , : new . noteMin ) ;
END I F ;
I F U P D A T I N G THEN
updateMirrorPrereq ( : old . codmod , : new . codmod ,
: old . codmodprereq , : new . codmodprereq , : new . noteMin ) ;
END I F ;
I F ( f i n d M o d u l e ( : n e w . c o d m o d , : n e w . c o d m o d ) ) THEN
I F I N S E R T I N G THEN
deleteMirrorPrereq ( : new . codmod , : new . codmodprereq ) ;
END I F ;
I F U P D A T I N G THEN
updateMirrorPrereq ( : new . codmod , : old . codmod ,
: new . codmodprereq , : old . codmodprereq , : old . noteMin ) ;
END I F ;
R A I S E _ A P P L I C A T I O N _ E R R O R ( 20003 , C i r c u i t dans p r e r e q u i s . ) ;
END I F ;
END;
/

C o n t r a i n t e 6

CREATE OR R E P L A C E F U N C T I O N
c h e c k I n s c r i p t i o n ( e t u d NUMBER, m o d NUMBER)
RETURN BOOLEAN
IS
CURSOR prereq IS
SELECT n o t e M i n , c o d m o d p r e r e q
FROM M I R R O R P R E R E Q
WHERE c o d m o d = m o d ;
p p r e r e q%r o w t y p e ;
n b L i g n e s NUMBER;
BEGIN

57

F O R p IN p r e r e q L O O P
SELECT count ( ) INTO n b L i g n e s
FROM R E S U L T A T
WHERE c o d m o d = p . c o d m o d p r e r e q
AND n u m e t u d = e t u d
AND n o t e < p . n o t e M i n ;
I F ( n b L i g n e s = 0 ) THEN
R E T U R N FALSE;
END I F ;
END L O O P ;
R E T U R N TRUE;
END;
/

CREATE OR R E P L A C E TRIGGER b e f o r e I n s e r t U p d a t e F E R I n s c
B E F O R E INSERT OR UPDATE ON I N S C R I P T I O N
FOR EACH ROW
DECLARE
n b L i g n e s NUMBER;
BEGIN
SELECT count ( ) INTO n b L i g n e s
FROM m o d u l e s D i s p o n i b l e s
WHERE c o d m o d = : n e w . c o d m o d ;
I F ( n b L i g n e s = 0 ) THEN
R A I S E _ A P P L I C A T I O N _ E R R O R ( 20001 , P l u s de p l a c e s d i p o n i b l e s . ) ;
END I F ;
I F (NOT( c h e c k I n s c r i p t i o n ( : n e w . n u m e t u d , : n e w . c o d m o d ) ) ) THEN
R A I S E _ A P P L I C A T I O N _ E R R O R ( 20004 , P r
e r e q u i s non s a t i s f a i t . ) ;
END I F ;
END;
/

C o n t r a i n t e 7

La
la
le
les

a u s s i un probleme s e pose , on ne p e u t pas f a i r e de r e q u e t e s u r


t a b l e r e s u l t a t , comme de p l u s , on t i e n t `
a p r e n d r e pour chaque e t u d i a n t
m e i l l e u r e n o t e dans chaque module , on c r e e une t a b l e t e m p o r a i r e c o n t e n a n t
n o t e s o b e t n u e s par l e s e l e v e s .

DROP TABLE M I R R O R R E S U L T ;
CREATE TABLE M I R R O R R E S U L T
( n u m e t u d NUMBER,
c o d m o d NUMBER,
c o d e x a m NUMBER,
n o t e NUMBER,
PRIMARY KEY( n u m e t u d , c o d m o d , c o d e x a m )
);

DROP VIEW M E I L L E U R E N O T E ;
CREATE VIEW M E I L L E U R E N O T E AS
SELECT n u m e t u d , c o d m o d , MAX( n o t e ) AS n o t e M a x
FROM M I R R O R R E S U L T
GROUP BY n u m e t u d , c o d m o d ;

DROP VIEW N O M B R E I N S C R I P T I O N s ;
CREATE VIEW N O M B R E I N S C R I P T I O N S AS
SELECT n u m e t u d ,
(
SELECT COUNT( )
FROM I N S C R I P T I O N I
WHERE I . n u m e t u d = E . n u m e t u d
) AS n b I n s c r i p t i o n s
FROM E T U D I A N T E ;

DROP VIEW N O M B R E N O T E S ;
CREATE VIEW N O M B R E N O T E S AS
SELECT n u m e t u d ,

58

(SELECT COUNT( ) AS n b N o t e s
FROM M E I L L E U R E N O T E M
WHERE M . n u m e t u d = E . n u m e t u d
) AS n b N o t e s
FROM E T U D I A N T E ;

CREATE OR R E P L A C E P R O C E D U R E
u p d a t e M o y e n n e ( e t u d NUMBER)
IS
n b N o t e s NUMBER;
n b I n s c r i p t i o n s NUMBER;
BEGIN
SELECT n b N o t e s INTO n b N o t e s
FROM N O M B R E N O T E S
WHERE n u m e t u d = e t u d ;
SELECT n b I n s c r i p t i o n s INTO n b I N s c r i p t i o n s
FROM N O M B R E I N S C R I P T I O N S
WHERE n u m e t u d = e t u d ;
I F ( n b N o t e s = n b I n s c r i p t i o n s ) THEN
UPDATE E T U D I A N T SET m o y e n n e =
(SELECT AVG( n o t e M a x )
FROM M E I L L E U R E N O T E
WHERE n u m e t u d = e t u d
)
WHERE n u m e t u d = e t u d ;
ELSE
UPDATE E T U D I A N T SET
m o y e n n e = NULL
WHERE n u m e t u d = e t u d ;
END I F ;
END;
/

CREATE OR R E P L A C E TRIGGER a f t e r I n s e r t F E R R e s u l t
A F T E R INSERT ON R E S U L T A T
FOR EACH ROW
BEGIN
INSERT INTO M I R R O R R E S U L T VALUES
( : new . numetud , : new . codmod , : new . codexam ,
updateMoyenne ( : new . numetud ) ;
END;
/

: new . note ) ;

CREATE OR R E P L A C E TRIGGER a f t e r U p d a t e F E R R e s u l t
A F T E R UPDATE ON R E S U L T A T
FOR EACH ROW
BEGIN
UPDATE M I R R O R R E S U L T SET
numetud = : new . numetud ,
codmod = : new . codmod ,
codexam = : new . codexam ,
note = : new . note
WHERE n u m e t u d = : o l d . n u m e t u d
AND c o d m o d = : o l d . c o d m o d
AND c o d e x a m = : o l d . c o d e x a m ;
updateMoyenne ( : new . numetud ) ;
END;
/

CREATE OR R E P L A C E TRIGGER a f t e r D e l e t e F E R R e s u l t
A F T E R DELETE ON R E S U L T A T
FOR EACH ROW
BEGIN
DELETE FROM M I R R O R R E S U L T
WHERE n u m e t u d = : n e w . n u m e t u d
AND c o d m o d = : n e w . c o d m o d
AND c o d e x a m = : n e w . c o d e x a m ;
updateMoyenne ( : new . numetud ) ;
END;
/

C o n t r a i n t e 9

59


CREATE OR R E P L A C E F U N C T I O N
checkAllStudents
RETURN BOOLEAN
IS
CURSOR C IS
SELECT n u m e t u d , c o d m o d
FROM I N S C R I P T I O N ;
e C%r o w t y p e ;
BEGIN
F O R e IN C L O O P
I F (NOT( c h e c k I n s c r i p t i o n ( e . n u m e t u d , e . c o d m o d ) ) ) THEN
R E T U R N FALSE;
END I F ;
END L O O P ;
R E T U R N TRUE;
END;
/

CREATE OR R E P L A C E TRIGGER B e f o r e U p d a t e F E R M o d u l e
B E F O R E UPDATE ON M O D U L E
FOR EACH ROW
BEGIN
I F ( : n e w . e f f e c m a x < : n e w . e f f e c ) THEN
R A I S E _ A P P L I C A T I O N _ E R R O R ( 20005 ,
L e f f e c t i f ne p e u t
e t r e en d e s s o u s de
END I F ;
END;
/

||

: new . effec ) ;

C o n t r a i n t e 8

CREATE OR R E P L A C E TRIGGER b e f o r e I n s e r t U p d a t e F E R P r e r e q
B E F O R E INSERT OR UPDATE ON P R E R E Q U I S
FOR EACH ROW
BEGIN
I F I N S E R T I N G THEN
insertMirrorPrereq ( : new . codmod , : new . codmodprereq , : new . noteMin ) ;
END I F ;
I F U P D A T I N G THEN
updateMirrorPrereq ( : old . codmod , : new . codmod ,
: old . codmodprereq , : new . codmodprereq , : new . noteMin ) ;
END I F ;
I F ( f i n d M o d u l e ( : n e w . c o d m o d , : n e w . c o d m o d ) ) THEN
I F I N S E R T I N G THEN
deleteMirrorPrereq ( : new . codmod , : new . codmodprereq ) ;
END I F ;
I F U P D A T I N G THEN
updateMirrorPrereq ( : new . codmod , : old . codmod ,
: new . codmodprereq , : old . codmodprereq , : old . noteMin ) ;
END I F ;
R A I S E _ A P P L I C A T I O N _ E R R O R ( 20003 , C i r c u i t dans p r e r e q u i s . ) ;
END I F ;
I F (NOT( c h e c k A l l S t u d e n t s ( ) ) ) THEN
I F I N S E R T I N G THEN
deleteMirrorPrereq ( : new . codmod , : new . codmodprereq ) ;
END I F ;
I F U P D A T I N G THEN
updateMirrorPrereq ( : new . codmod , : old . codmod ,
: new . codmodprereq , : old . codmodprereq , : old . noteMin ) ;
END I F ;
R A I S E _ A P P L I C A T I O N _ E R R O R ( 20006 , I m p o s s i b l e de diminuer c e t t e n o t e . ) ;
END I F ;
END;
/

Quelques i n s e r t i o n s pour t e s t e r

INSERT INTO E T U D I A N T VALUES


(
(SELECT n v l (MAX( n u m E t u d ) , 0 ) + 1 FROM E T U D I A N T ) ,
Fourier ,
Joseph ,
t o _ d a t e ( 21031768 , ddmmyyyy ) ,
Mr ,
NULL,
168031234567890 ,
NULL
);

60

INSERT INTO M O D U L E
( codMod , nomMod )
VALUES
(
(SELECT n v l (MAX( c o d M o d ) , 0 ) + 1 FROM M O D U L E ) ,
Maths
);
INSERT INTO I N S C R I P T I O N
( codMod , numEtud )
VALUES
(
(SELECT n u m E t u d FROM E T U D I A N T WHERE n o m = F o u r i e r ) ,
(SELECT c o d M o d FROM M O D U L E WHERE n o m M o d = Maths )
);
INSERT INTO E X A M E N VALUES
(
(SELECT c o d M o d FROM M O D U L E WHERE n o m M o d = Maths ) ,
1,
t o _ d a t e ( 02012008 , ddmmyyyy )
);
INSERT INTO R E S U L T A T VALUES
(
(SELECT c o d M o d FROM M O D U L E WHERE n o m M o d = Maths ) ,
1,
(SELECT n u m E t u d FROM E T U D I A N T WHERE n o m = F o u r i e r ) ,
19
);
UPDATE R E S U L T A T SET
n o t e = 20
wHERE
n u m E t u d = (SELECT n u m E t u d FROM E T U D I A N T WHERE n o m = F o u r i e r )
AND c o d M o d = (SELECT c o d M o d FROM M O D U L E WHERE n o m M o d = Maths )
AND c o d E x a m = 1 ;
INSERT INTO M O D U L E VALUES
( 2 , Algo , 3 0 , 2 2 ) ;
INSERT INTO P R E R E Q U I S VALUES
(1 , 2 , 10);
INSERT INTO P R E R E Q U I S VALUES
(2 , 1 , 10);
UPDATE P R E R E Q U I S SET n o t e M i n = 2 ;
INSERT INTO E X A M E N VALUES ( 2 , 1 , s y s d a t e ) ;

61

3.8

Packages

CREATE OR R E P L A C E P A C K A G E B O D Y g e s t i o n _ a r b r e I S
c u r s o r f e u i l l e s r e t u r n p e r s o n n e%r o w t y p e I S
SELECT FROM P E R S O N N E ;
P R O C E D U R E a j o u t e P e r s o n n e ( n o m p e r s o n n e . n o m%t y p e ,
p r e n o m p e r s o n n e . p r e n o m%t y p e , p e r e p e r s o n n e . p e r e%t y p e ,
m e r e p e r s o n n e . m e r e%t y p e ) I S
BEGIN
INSERT INTO P E R S O N N E VALUES (
(SELECT n v l (MAX( n u m p e r s ) , 0 ) + 1 FROM P E R S O N N E ) ,
nom , p r e n o m , p e r e , m e r e ) ;
END;
F U N C T I O N d e s c e n d D e ( n u m p e r s p e r s o n n e . n u m p e r s%t y p e ,
d e s c e n d a n t p e r s o n n e . n u m p e r s%t y p e ) R E T U R N B O O L E A N I S
BEGIN
I F ( d e s c e n d a n t I S NULL) THEN
R E T U R N FALSE;
E L S I F ( d e s c e n d a n t = n u m p e r s ) THEN
R E T U R N TRUE;
ELSE
DECLARE
p e r s P E R S O N N E%r o w t y p e ;
BEGIN
SELECT INTO p e r s
FROM P E R S O N N E
WHERE n u m p e r s = d e s c e n d a n t ;
RETURN descendDe ( numpers , pers . pere )
OR d e s c e n d D e ( n u m p e r s , p e r s . m e r e ) ;
END;
END I F ;
END;
p r o c e d u r e m o d i f i e P a r e n t s ( p e r s p e r s o n n e . n u m p e r s%t y p e ,
n u m P e r e p e r s o n n e . p e r e%t y p e , n u m M e r e p e r s o n n e . m e r e%t y p e ) I S
BEGIN
I F ( d e s c e n d D e ( p e r s , n u m P e r e ) OR d e s c e n d D e ( p e r s , n u m M e r e ) ) THEN
RAISE CIRCUIT ;
END I F ;
UPDATE P E R S O N N E SET p e r e = n u m P e r e , m e r e = n u m M e r e
WHERE n u m P e r s = p e r s ;
END;
END;
/
CALL gestion_Arbre . modifieParents (20 , 14 , 1 5 ) ;

62

3.9

R
evisions

P r e p a r a t i f s . . .
DROP TABLE M I R R O R P E R S O N N E ;
CREATE TABLE M I R R O R P E R S O N N E
(
n u m p e r s NUMBER PRIMARY KEY,
p e r e NUMBER,
m e r e NUMBER
);
CREATE OR R E P L A C E TRIGGER m i s e A J o u r M i r r o r P e r s o n n e
B E F O R E UPDATE OR INSERT OR DELETE ON P E R S O N N E
FOR EACH ROW
BEGIN
I F D E L E T I N G OR U P D A T I N G THEN
DELETE FROM M I R R O R P E R S O N N E
WHERE n u m p e r s = : o l d . n u m p e r s ;
END I F ;
I F I N S E R T I N G OR U P D A T I N G THEN
INSERT INTO M I R R O R P E R S O N N E VALUES
( : new . numpers , : new . pere , : new . mere ) ;
END I F ;
END;
/
DROP TABLE M I R R O R M A R I A G E ;
CREATE TABLE M I R R O R M A R I A G E
(
n u m m a r i NUMBER,
n u m f e m m e NUMBER,
d a t e m a r i a g e DATE,
d a t e d i v o r c e DATE
);
CREATE OR R E P L A C E TRIGGER m i s e A J o u r M i r r o r M a r i a g e
B E F O R E UPDATE OR INSERT OR DELETE ON M A R I A G E
FOR EACH ROW
BEGIN
I F D E L E T I N G OR U P D A T I N G THEN
DELETE FROM M I R R O R M A R I A G E
WHERE n u m m a r i = : o l d . n u m m a r i
AND n u m f e m m e = : o l d . n u m f e m m e
AND d a t e m a r i a g e = : o l d . d a t e m a r i a g e ;
END I F ;
I F I N S E R T I N G OR U P D A T I N G THEN
INSERT INTO M I R R O R M A R I A G E VALUES
( : new . nummari , : new . numfemme , : new . datemariage ,
END I F ;
END;
/

: new . datedivorce ) ;

C o n t r a i n t e 1
ALTER TABLE P E R S O N N E ADD CONSTRAINT c k _ p a r e n t s _ d i f f e r e n t s CHECK( p e r e <> m e r e ) ;
C o n t r a i n t e 2
CREATE OR R E P L A C E P A C K A G E c o n t r a i n t e C i r c u i t I S
C I R C U I T EXCEPTION;
P R O C E D U R E v e r i f i e C i r c u i t ( p e r s p e r s o n n e . n u m p e r s%t y p e ) ;
F U N C T I O N d e s c e n d D e ( n u m p e r s p e r s o n n e . n u m p e r s%t y p e ,
d e s c e n d a n t p e r s o n n e . n u m p e r s%t y p e ) R E T U R N B O O L E A N ;
END;
/
CREATE OR R E P L A C E TRIGGER v e r i f i e C o n t r a i n t e C i r c u i t
A F T E R UPDATE OR INSERT ON P E R S O N N E
FOR EACH ROW
BEGIN
contrainteCircuit . verifieCircuit ( : new . numPers ) ;
END;
/
CREATE OR R E P L A C E P A C K A G E B O D Y c o n t r a i n t e C i r c u i t I S
F U N C T I O N d e s c e n d D e ( n u m p e r s p e r s o n n e . n u m p e r s%t y p e ,
d e s c e n d a n t p e r s o n n e . n u m p e r s%t y p e ) R E T U R N B O O L E A N I S
BEGIN
I F ( d e s c e n d a n t I S NULL) THEN
R E T U R N FALSE;
E L S I F ( d e s c e n d a n t = n u m p e r s ) THEN
R E T U R N TRUE;
ELSE
DECLARE

63

p e r s M I R R O R P E R S O N N E%r o w t y p e ;
BEGIN
SELECT INTO p e r s
FROM M I R R O R P E R S O N N E
WHERE n u m p e r s = d e s c e n d a n t ;
RETURN descendDe ( numpers , pers . pere )
OR d e s c e n d D e ( n u m p e r s , p e r s . m e r e ) ;
END;
END I F ;
END;
P R O C E D U R E v e r i f i e C i r c u i t ( p e r s p e r s o n n e . n u m p e r s%t y p e ) I S
l i g n e m i r r o r p e r s o n n e%r o w t y p e ;
BEGIN
SELECT INTO L I G N E
FROM m i r r o r p e r s o n n e
WHERE n u m p e r s = p e r s ;
I F ( d e s c e n d D e ( p e r s , l i g n e . p e r e ) OR d e s c e n d D e ( p e r s , l i g n e . m e r e ) ) THEN
RAISE CIRCUIT ;
END I F ;
END;
END;
/
C o n t r a i n t e 3
ALTER TABLE M A R I A G E ADD CONSTRAINT c k _ d a t e s _ m a r i a g e CHECK( d a t e D i v o r c e I S NULL OR d a t e M a r i a g e <=

dateDivorce ) ;

C o n t r a i n t e 4
CREATE OR R E P L A C E P A C K A G E c o n t r a i n t e s M a r i a g e s I S
m a r i a g e s S u p e r p o s e s EXCEPTION;
P R O C E D U R E v e r i f i e M a r i a g e s S u p e r p o s e s ( n o u v e a u M a r i a g e m a r i a g e%r o w t y p e ) ;
END c o n t r a i n t e s M a r i a g e s ;
/
CREATE OR R E P L A C E TRIGGER v e r i f i e C o n t r a i n t e s M a r i a g e s
B E F O R E UPDATE OR INSERT ON M A R I A G E
FOR EACH ROW
DECLARE
n o u v e a u M a r i a g e M A R I A G E%r o w t y p e ;
BEGIN
n o u v e a u M a r i a g e . n u m M a r i := : n e w . n u m M a r i ;
n o u v e a u M a r i a g e . n u m F e m m e := : n e w . n u m F e m m e ;
n o u v e a u M a r i a g e . d a t e M a r i a g e := : n e w . d a t e M a r i a g e ;
n o u v e a u M a r i a g e . d a t e D i v o r c e := : n e w . d a t e D i v o r c e ;
contraintesMariages . verifieMariagesSuperposes ( nouveauMariage ) ;
END;
/
CREATE OR R E P L A C E P A C K A G E B O D Y c o n t r a i n t e s M a r i a g e s I S
F U N C T I O N s e S u p e r p o s e n t ( m 1 m i r r o r M a r i a g e%r o w t y p e , m 2 m i r r o r M a r i a g e%r o w t y p e ) R E T U R N B O O L E A N I S
BEGIN
I F ( m 1 . n u m m a r i <> m 2 . n u m m a r i OR m 1 . n u m f e m m e <> m 2 . n u m f e m m e ) THEN
R E T U R N FALSE;
END I F ;
R E T U R N NOT(
( m 2 . d a t e d i v o r c e I S NOT NULL AND m 1 . d a t e M a r i a g e <= m 2 . d a t e D i v o r c e )
OR ( m 1 . d a t e d i v o r c e I S NOT NULL AND m 2 . d a t e M a r i a g e <= m 1 . d a t e D i v o r c e )
);
END;
P R O C E D U R E v e r i f i e M a r i a g e s S u p e r p o s e s ( n o u v e a u M a r i a g e m a r i a g e%r o w t y p e ) I S
CURSOR a u t r e s M a r i a g e s IS
SELECT FROM M I R R O R M A R I A G E
WHERE n u m M a r i = n o u v e a u M a r i a g e . n u m M a r i
OR n u m F e m m e = n o u v e a u M a r i a g e . n u m F e m m e ;
a u t r e M a r i a g e a u t r e s M a r i a g e s%R O W T Y P E ;
BEGIN
F O R a u t r e M a r i a g e IN a u t r e s M a r i a g e s L O O P
I F ( s e S u p e r p o s e n t ( n o u v e a u M a r i a g e , a u t r e M a r i a g e ) ) THEN
RAISE mariagesSuperposes ;
END I F ;
END L O O P ;
END;
END c o n t r a i n t e s M a r i a g e s ;
/
C o n t r a i n t e s 5 e t 6
CREATE OR R E P L A C E p a c k a g e c o n t r a i n t e s T r a n s I S
t r a n s EXCEPTION;
P R O C E D U R E v e r i f i e P e r e M e r e ( n o u v e l l e P e r s o n n e M I R R O R P E R S O N N E%r o w t y p e ) ;
P R O C E D U R E v e r i f i e M a r i F e m m e ( n o u v e a u M a r i a g e M A R I A G E%r o w t y p e ) ;

64

end c o n t r a i n t e s T r a n s ;
/
CREATE OR R E P L A C E TRIGGER p e r e M e r e
A F T E R UPDATE OR INSERT ON P E R S O N N E
FOR EACH ROW
DECLARE
n o u v e l l e P e r s o n n e M I R R O R P E R S O N N E%r o w t y p e ;
BEGIN
n o u v e l l e P e r s o n n e . n u m p e r s := : n e w . n u m p e r s ;
n o u v e l l e P e r s o n n e . p e r e := : n e w . p e r e ;
n o u v e l l e P e r s o n n e . m e r e := : n e w . m e r e ;
contraintesTrans . verifiePereMere ( nouvellePersonne ) ;
END;
/
CREATE OR R E P L A C E TRIGGER m a r i F e m m e
A F T E R UPDATE OR INSERT ON M A R I A G E
FOR EACH ROW
DECLARE
n o u v e a u M a r i a g e M A R I A G E%r o w t y p e ;
BEGIN
n o u v e a u M a r i a g e . n u m M a r i := : n e w . n u m M a r i ;
n o u v e a u M a r i a g e . n u m F e m m e := : n e w . n u m F e m m e ;
n o u v e a u M a r i a g e . d a t e M a r i a g e := : n e w . d a t e M a r i a g e ;
n o u v e a u M a r i a g e . d a t e D i v o r c e := : n e w . d a t e D i v o r c e ;
contraintesTrans . verifieMariFemme ( nouveauMariage ) ;
END;
/
CREATE OR R E P L A C E p a c k a g e B O D Y c o n t r a i n t e s T r a n s I S
P R O C E D U R E v e r i f i e P e r e M e r e ( n o u v e l l e P e r s o n n e M I R R O R P E R S O N N E%r o w t y p e ) I S
n b INT ;
BEGIN
SELECT COUNT( ) INTO n b
FROM M I R R O R P E R S O N N E
WHERE p e r e = n o u v e l l e P e r s o n n e . m e r e
OR m e r e = n o u v e l l e P e r s o n n e . p e r e ;
I F ( n b <> 0 ) THEN
RAISE TRANS ;
END I F ;
SELECT COUNT( ) INTO n b
FROM M I R R O R M A R I A G E
WHERE n u m M a r i = n o u v e l l e P e r s o n n e . m e r e
OR n u m F e m m e = n o u v e l l e P e r s o n n e . p e r e ;
I F ( n b <> 0 ) THEN
RAISE TRANS ;
END I F ;
END;
P R O C E D U R E v e r i f i e M a r i F e m m e ( n o u v e a u M a r i a g e M A R I A G E%r o w t y p e ) I S
n b INT ;
BEGIN
SELECT COUNT( ) INTO n b
FROM M I R R O R M A R I A G E
WHERE n u m M a r i = n o u v e a u M a r i a g e . n u m F e m m e
OR n u m F e m m e = n o u v e a u M a r i a g e . n u m M a r i ;
I F ( n b <> 0 ) THEN
RAISE TRANS ;
END I F ;
SELECT COUNT( ) INTO n b
FROM M I R R O R P E R S O N N E
WHERE p e r e = n o u v e a u M a r i a g e . n u m F e m m e
OR m e r e = n o u v e a u M a r i a g e . n u m M a r i ;
I F ( n b <> 0 ) THEN
RAISE TRANS ;
END I F ;
END;

END c o n t r a i n t e s T r a n s ;
/
C o n t r a i n t e 7
CREATE OR R E P L A C E P A C K A G E c o n t r a i n t e M a r i a g e C o n s a n g u i n I S
M a r i a g e C o n s a n g u i n EXCEPTION;
P R O C E D U R E v e r i f i e M a r i a g e C o n s a n g u i n ( n o u v e a u M a r i a g e M A R I A G E%r o w t y p e ) ;
END c o n t r a i n t e M a r i a g e C o n s a n g u i n ;
/
CREATE OR R E P L A C E TRIGGER m a r i a g e C o n s a n g u i n
A F T E R UPDATE OR INSERT ON M A R I A G E
FOR EACH ROW
DECLARE
n o u v e a u M a r i a g e M A R I A G E%r o w t y p e ;
BEGIN

65

n o u v e a u M a r i a g e . n u m M a r i := : n e w . n u m M a r i ;
n o u v e a u M a r i a g e . n u m F e m m e := : n e w . n u m F e m m e ;
n o u v e a u M a r i a g e . d a t e M a r i a g e := : n e w . d a t e M a r i a g e ;
n o u v e a u M a r i a g e . d a t e D i v o r c e := : n e w . d a t e D i v o r c e ;
contrainteMariageConsanguin . verifieMariageConsanguin ( nouveauMariage ) ;
END;
/
CREATE OR R E P L A C E P A C K A G E B O D Y c o n t r a i n t e M a r i a g e C o n s a n g u i n I S
F U N C T I O N p e r e ( p P E R S O N N E . n u m p e r s%t y p e ) R E T U R N P E R S O N N E . n u m p e r s%t y p e I S
n u m P e r e P E R S O N N E . n u m p e r s%t y p e ;
BEGIN
SELECT p e r e INTO n u m P e r e
FROM M I R R O R P E R S O N N E
WHERE n u m p e r s = p ;
RETURN numPere ;
EXCEPTION
WHEN N O _ D A T A _ F O U N D THEN
R E T U R N NULL;
END;
F U N C T I O N m e r e ( p P E R S O N N E . n u m p e r s%t y p e ) R E T U R N P E R S O N N E . n u m p e r s%t y p e I S
n u m M e r e P E R S O N N E . n u m p e r s%t y p e ;
BEGIN
SELECT m e r e INTO n u m M e r e
FROM M I R R O R P E R S O N N E
WHERE n u m p e r s = p ;
RETURN numMere ;
EXCEPTION
WHEN N O _ D A T A _ F O U N D THEN
R E T U R N NULL;
END;

F U N C T I O N r e c h e r c h e A n c e t r e C o m m u n ( a P E R S O N N E . n u m p e r s%t y p e ,
b P E R S O N N E . n u m p e r s%t y p e ) R E T U R N B O O L E A N I S
BEGIN
I F ( a I S NULL) THEN
R E T U R N FALSE;
ELSE
R E T U R N ( c o n t r a i n t e C i r c u i t . d e s c e n d D e ( a , b ) ) OR r e c h e r c h e A n c e t r e C o m m u n ( p e r e ( a ) , b ) OR r e c h e r c h e A n c e t
END I F ;
END;
P R O C E D U R E v e r i f i e M a r i a g e C o n s a n g u i n ( n o u v e a u M a r i a g e M A R I A G E%r o w t y p e ) I S
BEGIN
I F ( r e c h e r c h e A n c e t r e C o m m u n ( n o u v e a u M a r i a g e . n u m M a r i , n o u v e a u M a r i a g e . n u m F e m m e ) ) THEN
RAISE MariageConsanguin ;
END I F ;
END;
END c o n t r a i n t e M a r i a g e C o n s a n g u i n ;
/

66

Annexe A

Scripts de cr
eation de bases
A.1

Livraisons Sans contraintes

Attention : Le numero de livraison est une cle secondaire, cest-`a-dire un numero unique etant donne un fournisseur.
CREATE TABLE P R O D U I T
( n u m p r o d number ,
n o m p r o d varchar2 ( 3 0 ) ) ;
CREATE TABLE F O U R N I S S E U R
( n u m f o u number ,
n o m f o u varchar2 ( 3 0 ) ) ;
CREATE TABLE P R O P O S E R
( n u m f o u number ,
n u m p r o d number ,
p r i x number ) ;
CREATE TABLE L I V R A I S O N
( n u m f o u number ,
n u m l i number ,
dateli date default sysdate
);
CREATE TABLE D E T A I L L I V R A I S O N
( n u m f o u number ,
n u m l i number ,
n u m p r o d number ,
q t e number ) ;

67

A.2

Modules et prerequis

les modules sont repertories dans une table, et les modules pre-requis pour sy inscrire (avec la note minimale) se
trouvent dans la table prerequis. Une ligne de la table PREREQUIS nous indique que pour sinscrire dans le module
numero numMod, il faut avoir eu au moins noteMin au module numModPrereq.
CREATE TABLE M O D U L E
( n u m M o d number primary key ,
n o m M o d varchar2 ( 3 0 )
);
CREATE TABLE P R E R E Q U I S
(
n u m M o d number r e f e r e n c e s M O D U L E ( n u m M o d ) ,
n u m M o d P r e r e q number r e f e r e n c e s M O D U L E ( n u m M o d ) ,
n o t e M i n number ( 2 ) DEFAULT 10 NOT NULL ,
PRIMARY KEY( n u m M o d , n u m M o d P r e r e q )
);
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT

INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO

MODULE
MODULE
MODULE
MODULE
MODULE
MODULE
MODULE
MODULE

VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES

INSERT
INSERT
INSERT
INSERT
INSERT
INSERT

INTO
INTO
INTO
INTO
INTO
INTO

PREREQUIS
PREREQUIS
PREREQUIS
PREREQUIS
PREREQUIS
PREREQUIS

(1 ,
(2 ,
(3 ,
(4 ,
(5 ,
(6 ,
(7 ,
(8 ,

( numMod
( numMod
VALUES
( numMod
( numMod
( numMod

Oracle ) ;
C++ ) ;
C ) ;
Algo ) ;
Merise ) ;
PL/SQL O r a c l e ) ;
mySQL ) ;
e
c );
Algo avancA
, numModPrereq )
, numModPrereq )
(6 , 1 , 12);
, numModPrereq )
, numModPrereq )
, numModPrereq )

VALUES ( 1 ,
VALUES ( 2 ,

5);
3);

VALUES ( 6 ,
VALUES ( 8 ,
VALUES ( 7 ,

5);
5);
5);

68

A.3

G
eom
etrie

La table INTERVALLE contient des intervalles specifies par leurs bornes inferieure et superieure. Supprimer de la
table intervalle tous les intervalles qui nen sont pas avec une seule instruction.
CREATE TABLE I N T E R V A L L E
( b o r n e I n f NUMBER,
b o r n e S u p NUMBER,
PRIMARY KEY ( b o r n e I n f , b o r n e S u p ) ) ;
CREATE TABLE R E C T A N G L E
( x H a u t G a u c h e NUMBER,
y H a u t G a u c h e NUMBER,
x B a s D r o i t NUMBER,
y B a s D r o i t NUMBER,
PRIMARY KEY ( x H a u t G a u c h e , y H a u t G a u c h e , x B a s D r o i t ,
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT

INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO

INTERVALLE
INTERVALLE
INTERVALLE
INTERVALLE
INTERVALLE
INTERVALLE
INTERVALLE
INTERVALLE
INTERVALLE
INTERVALLE

INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT

INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO

RECTANGLE
RECTANGLE
RECTANGLE
RECTANGLE
RECTANGLE
RECTANGLE
RECTANGLE
RECTANGLE
RECTANGLE
RECTANGLE
RECTANGLE
RECTANGLE

VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES

VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES

(2 ,
(12 ,
(2 ,
(12 ,
(8 ,
(34 ,
(5 ,
(7 ,
(0 ,
(21 ,

yBasDroit ) ) ;

56);
30);
3);
3);
27);
26);
10);
32);
30);
8);

(2 , 12 , 5 , 7 ) ;
(2 , 12 , 1 , 1 3 ) ;
(10 , 13 , 1 , 1 1 ) ;
(10 , 13 , 10 , 1 1 ) ;
(2 , 7 , 5 , 13);
(21 , 73 , 15 , 2 2 ) ;
(1 , 2 , 3 , 4);
(1 , 5 , 3 , 2);
(1 , 6 , 3 , 6);
(4 , 2 , 1 , 4);
(2 , 3 , 4 , 0);
(5 , 4 , 2 , 1);

69

A.4

Livraisons

CREATE TABLE P R O D U I T
( n u m p r o d number ,
n o m p r o d varchar2 ( 3 0 ) ) ;
CREATE TABLE F O U R N I S S E U R
( n u m f o u number ,
n o m f o u varchar2 ( 3 0 ) ) ;
CREATE TABLE P R O P O S E R
( n u m f o u number ,
n u m p r o d number ,
p r i x number NOT NULL) ;
CREATE TABLE L I V R A I S O N
( n u m f o u number ,
n u m l i number ,
dateli date default sysdate
);
CREATE TABLE D E T A I L L I V R A I S O N
( n u m f o u number ,
n u m l i number ,
n u m p r o d number ,
q t e number NOT NULL) ;
a l t e r table
PRIMARY KEY
a l t e r table
PRIMARY KEY
a l t e r table
PRIMARY KEY
a l t e r table
PRIMARY KEY
a l t e r table
PRIMARY KEY
a l t e r table
FOREIGN KEY
a l t e r table
FOREIGN KEY
a l t e r table
FOREIGN KEY
a l t e r table
FOREIGN KEY
a l t e r table
FOREIGN KEY

p r o d u i t add c o n s t r a i n t p k _ p r o d u i t
( numprod ) ;
f o u r n i s s e u r add c o n s t r a i n t p k _ f o u r n i s s e u r
( numfou ) ;
p r o p o s e r add c o n s t r a i n t p k _ p r o p o s e r
( numfou , numprod ) ;
l i v r a i s o n add c o n s t r a i n t p k _ l i v r a i s o n
( numfou , numli ) ;
d e t a i l l i v r a i s o n add c o n s t r a i n t p k _ d e t a i l _ l i v r a i s o n
( numfou , numli , numprod ) ;
p r o p o s e r add c o n s t r a i n t f k _ p r o p o s e r _ f o u r n i s s e u r
( numfou ) REFERENCES fournisseur ( numfou ) ;
p r o p o s e r add c o n s t r a i n t f k _ p r o p o s e r _ p r o d u i t
( numprod ) REFERENCES produit ( numprod ) ;
l i v r a i s o n add c o n s t r a i n t f k _ l i v r a i s o n
( numfou ) REFERENCES fournisseur ( numfou ) ;
d e t a i l l i v r a i s o n add c o n s t r a i n t f k _ d e t a i l _ l i v r a i s o n
( numfou , numli ) REFERENCES livraison ( numfou , numli ) ;
d e t a i l l i v r a i s o n add c o n s t r a i n t f k _ d e t a i l _ l i v r a i s o n _ p r o p o s e r
( numfou , numprod ) REFERENCES proposer ( numfou , numprod ) ;

INSERT
INSERT
INSERT
INSERT

INTO
INTO
INTO
INTO

PRODUIT
PRODUIT
PRODUIT
PRODUIT

INSERT
INSERT
INSERT
INSERT

INTO
INTO
INTO
INTO

FOURNISSEUR
FOURNISSEUR
FOURNISSEUR
FOURNISSEUR

INSERT
INSERT
INSERT
INSERT

INTO
INTO
INTO
INTO

PROPOSER
PROPOSER
PROPOSER
PROPOSER

values
values
values
values

(1 ,
(2 ,
(3 ,
(4 ,

values
values
values
values

values
values
values
values

(1 ,
(1 ,
(2 ,
(3 ,

Roue de s e c o u r s ) ;
e
c Batman ) ;
PoupA
Cotons t i g e s ) ;
Cornichons ) ;
(1 ,
(2 ,
(3 ,
(4 ,
1,
2,
2,
3,

f1
f2
f3
f4

);
);
);
);

200);
15);
1);
2);

INSERT INTO L I V R A I S O N ( n u m f o u , n u m l i ) values ( 1 ,


INSERT INTO L I V R A I S O N ( n u m f o u , n u m l i ) values ( 1 ,
INSERT INTO L I V R A I S O N ( n u m f o u , n u m l i ) values ( 3 ,
INSERT
INSERT
INSERT
INSERT
INSERT

INTO
INTO
INTO
INTO
INTO

DETAILLIVRAISON
DETAILLIVRAISON
DETAILLIVRAISON
DETAILLIVRAISON
DETAILLIVRAISON

values
values
values
values
values

(3 ,
(1 ,
(1 ,
(1 ,
(1 ,

1,
1,
1,
2,
2,

3,
1,
2,
1,
2,

1);
2);
1);

10);
25);
20);
15);
17);

70

A.5

Arbre g
en
ealogique

La table PERSONNE, le champ pere contient le numero du p`ere de la personne, le champ mere contient le numero
de la m`ere de la personne.
CREATE TABLE P E R S O N N E
( n u m p e r s number PRIMARY KEY,
n o m varchar2 ( 3 0 ) NOT NULL,
p r e n o m varchar2 ( 3 0 ) ,
pere REFERENCES PERSONNE ( numpers ) ,
mere REFERENCES PERSONNE ( numpers )
);
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT

INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO

PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE
PERSONNE

VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES

(1 ,
(16 ,
(2 ,
(3 ,
(4 ,
(13 ,
(5 ,
(12 ,
(6 ,
(7 ,
(8 ,
(9 ,
(10 ,
(17 ,
(11 ,
(15 ,
(19 ,
(20 ,
(21 ,
(14 ,
(18 ,

de Montmirail , d i t l e Hardi , Godefroy , NULL, NULL) ;


ET , NULL, NULL, NULL) ;
Le Croquant , Jacqou , 1 , 1 6 ) ;
La F r i p o u i l l e , J a c q o u i l l e , 1 , 1 6 ) ;
Bush , Kate , NULL, NULL) ;
Granger , Hermione , NULL, NULL) ;
mur
dor
c
c
Du FA
, MA
, 3 ,4 ) ;

Kobalevska Aa
, S o f i a , NULL, NULL) ;

c , NULL, NULL) ;
Rieu , AndrA
Bontoutou , Rex , 6 , 4 ) ;
D i j k s t r a , Edvard , 2 , 1 3 ) ;
L e i b n i z , G o t t f r i e 1 d Wilhem , 8 , 1 2 ) ;
Bach , Johann S e b a s t i e n , 5 , 1 2 ) ;
Mathieu , M i r e i l l e , NULL, NULL) ;
Lemarchal , Gregory , 1 0 , 1 7 ) ;
S o c r a t e , NULL, 3 , 1 3 ) ;
Leroy , Nolwen , NULL, NULL) ;
Bartoli , Jennifer , 9 , 19);
Fabian , Lara , 1 0 , 1 7 ) ;
Stone , Sharon , 1 5 , 2 0 ) ;
Frege , E l o d i e , 7 , 1 3 ) ;

71

A.6
DROP
DROP
DROP
DROP
DROP
DROP

Comptes bancaires

TABLE
TABLE
TABLE
TABLE
TABLE
TABLE

OPERATION ;
TYPEOPERATION ;
COMPTECLIENT ;
TYPECCL ;
PERSONNEL ;
CLIENT ;

CREATE TABLE C L I E N T
( n u m c l i number ,
n o m c l i varchar2 ( 3 0 ) ,
p r e n o m c l i varchar2 ( 3 0 ) ,
a d r e s s e varchar2 ( 6 0 ) ,
tel varchar (10)
);
CREATE TABLE P E R S O N N E L
( n u m p e r s number ,
n o m p e r s varchar2 ( 3 0 ) ,
p r e n o m p e r s varchar2 ( 3 0 ) ,
m a n a g e r number ,
s a l a i r e number
);
CREATE TABLE T Y P E C C L
( n u m t y p e c c l number ,
n o m t y p e c c l varchar2 ( 3 0 )
);
CREATE TABLE C O M P T E C L I E N T
( n u m c l i number ,
n u m c c l number ,
n u m t y p e c c l number ,
d a t e c c l d a t e d e f a u l t s y s d a t e not null ,
n u m p e r s number
);
CREATE TABLE T Y P E O P E R A T I O N
( n u m t y p e o p e r number ,
n o m t y p e o p e r varchar2 ( 3 0 )
);
CREATE TABLE O P E R A T I O N
( n u m c l i number ,
n u m c c l number ,
n u m o p e r number ,
n u m t y p e o p e r number ,
d a t e o p e r d a t e d e f a u l t s y s d a t e not null ,
m o n t a n t o p e r number not null ,
l i b e l o p e r varchar2 ( 3 0 )
);
ALTER TABLE C L I E N T ADD
(
CONSTRAINT p k _ c l i e n t PRIMARY KEY ( n u m c l i ) ,
CONSTRAINT c k _ t e l e p h o n e CHECK( L E N G T H ( t e l )=10)
);
ALTER TABLE P E R S O N N E L ADD
(
CONSTRAINT p k _ p e r s o n n e l PRIMARY KEY ( n u m p e r s ) ,
CONSTRAINT c k _ s a l a i r e CHECK( S A L A I R E >= 1 2 5 4 . 2 8 )
);
ALTER TABLE T Y P E C C L ADD
CONSTRAINT p k _ t y p e c c l PRIMARY KEY ( n u m t y p e c c l ) ;
ALTER TABLE T Y P E O P E R A T I O N ADD
CONSTRAINT p k _ t y p e o p e r a t i o n PRIMARY KEY ( n u m t y p e o p e r ) ;
ALTER TABLE C O M P T E C L I E N T ADD
(
CONSTRAINT p k _ c o m p t e c l i e n t
PRIMARY KEY ( n u m c l i , n u m c c l ) ,
CONSTRAINT f k _ c c l _ t y p e c c l
FOREIGN KEY ( n u m t y p e c c l )
REFERENCES TYPECCL ( numtypeccl ) ,
CONSTRAINT f k _ c c l _ c l i e n t
FOREIGN KEY ( n u m c l i )
REFERENCES CLIENT ( numcli ) ,
CONSTRAINT f k _ c c l _ p e r s o n n e l
FOREIGN KEY ( n u m p e r s )
REFERENCES PERSONNEL ( numpers )
);
ALTER TABLE O P E R A T I O N ADD
(

72

CONSTRAINT p k _ o p e r a t i o n
PRIMARY KEY ( n u m c l i , n u m c c l , n u m o p e r ) ,
CONSTRAINT f k _ o p e r _ c c l
FOREIGN KEY ( n u m c l i , n u m o p e r )
REFERENCES COMPTECLIENT ( numcli , numccl ) ,
CONSTRAINT f k _ o p e r _ c o d e o p e r
FOREIGN KEY ( n u m t y p e o p e r )
REFERENCES typeoperation ( numtypeoper ) ,
CONSTRAINT m o n t a n t _ o p e r a t i o n
CHECK( m o n t a n t o p e r <> 0 )
);
INSERT INTO T Y P E C C L VALUES (
(SELECT n v l (MAX( n u m t y p e c c l ) , 0 ) + 1
FROM T Y P E C C L
),
Compte c o u r a n t ) ;
INSERT INTO T Y P E C C L VALUES (
(SELECT n v l (MAX( n u m t y p e c c l ) , 0 ) + 1
FROM T Y P E C C L
),
livret );
INSERT INTO T Y P E C C L VALUES (
(SELECT n v l (MAX( n u m t y p e c c l ) , 0 ) + 1
FROM T Y P E C C L
),
PEL ) ;
INSERT INTO T Y P E O P E R A T I O N VALUES (
(SELECT n v l (MAX( n u m t y p e o p e r ) , 0 ) + 1
FROM T Y P E O P E R A T I O N
),
p

c At
dA
esp Aces
);
INSERT INTO T Y P E O P E R A T I O N VALUES (
(SELECT n v l (MAX( n u m t y p e o p e r ) , 0 ) + 1
FROM T Y P E O P E R A T I O N
),
l

c Avement
prA
);
INSERT INTO T Y P E O P E R A T I O N VALUES (
(SELECT n v l (MAX( n u m t y p e o p e r ) , 0 ) + 1
FROM T Y P E O P E R A T I O N
),
virement ) ;
INSERT INTO T Y P E O P E R A T I O N VALUES (
(SELECT n v l (MAX( n u m t y p e o p e r ) , 0 ) + 1
FROM T Y P E O P E R A T I O N
),
retrait );

73

A.7
DROP
DROP
DROP
DROP
DROP
DROP

Comptes bancaires avec exceptions

TABLE
TABLE
TABLE
TABLE
TABLE
TABLE

OPERATION ;
COMPTECLIENT ;
TYPECCL ;
TYPEOPERATION ;
PERSONNEL ;
CLIENT ;

CREATE TABLE C L I E N T
( n u m c l i number ,
n o m c l i varchar2 ( 3 0 ) ,
p r e n o m c l i varchar2 ( 3 0 ) ,
a d r e s s e varchar2 ( 6 0 ) ,
tel varchar (10)
);
CREATE TABLE P E R S O N N E L
( n u m p e r s number ,
n o m p e r s varchar2 ( 3 0 ) ,
p r e n o m p e r s varchar2 ( 3 0 ) ,
m a n a g e r number ,
s a l a i r e number
);
CREATE TABLE T Y P E C C L
( n u m t y p e c c l number ,
n o m t y p e c c l varchar2 ( 3 0 )
);
CREATE TABLE C O M P T E C L I E N T
( n u m c l i number ,
n u m c c l number ,
n u m t y p e c c l number ,
d a t e c c l d a t e d e f a u l t s y s d a t e not null ,
n u m p e r s number
);
CREATE TABLE T Y P E O P E R A T I O N
( n u m t y p e o p e r number ,
n o m t y p e o p e r varchar2 ( 3 0 )
);
CREATE TABLE O P E R A T I O N
( n u m c l i number ,
n u m c c l number ,
n u m o p e r number ,
n u m t y p e o p e r number ,
d a t e o p e r d a t e d e f a u l t s y s d a t e not null ,
m o n t a n t o p e r number not null ,
l i b e l o p e r varchar2 ( 3 0 )
);
ALTER TABLE C L I E N T ADD
(
CONSTRAINT p k _ c l i e n t PRIMARY KEY ( n u m c l i ) ,
CONSTRAINT c k _ t e l e p h o n e CHECK( L E N G T H ( t e l )=10)
);
ALTER TABLE P E R S O N N E L ADD
(
CONSTRAINT p k _ p e r s o n n e l PRIMARY KEY ( n u m p e r s ) ,
CONSTRAINT c k _ s a l a i r e CHECK( S A L A I R E >= 1 2 5 4 . 2 8 )
);
ALTER TABLE T Y P E C C L ADD
CONSTRAINT p k _ t y p e c c l PRIMARY KEY ( n u m t y p e c c l ) ;
ALTER TABLE T Y P E O P E R A T I O N ADD
CONSTRAINT p k _ t y p e o p e r a t i o n PRIMARY KEY ( n u m t y p e o p e r ) ;
ALTER TABLE C O M P T E C L I E N T ADD
(
CONSTRAINT p k _ c o m p t e c l i e n t
PRIMARY KEY ( n u m c l i , n u m c c l ) ,
CONSTRAINT f k _ c c l _ t y p e c c l
FOREIGN KEY ( n u m t y p e c c l )
REFERENCES TYPECCL ( numtypeccl ) ,
CONSTRAINT f k _ c c l _ c l i e n t
FOREIGN KEY ( n u m c l i )
REFERENCES CLIENT ( numcli ) ,
CONSTRAINT f k _ c c l _ p e r s o n n e l
FOREIGN KEY ( n u m p e r s )
REFERENCES PERSONNEL ( numpers )
);
ALTER TABLE O P E R A T I O N ADD
(

74

CONSTRAINT p k _ o p e r a t i o n
PRIMARY KEY ( n u m c l i , n u m c c l , n u m o p e r ) ,
CONSTRAINT f k _ o p e r _ c c l
FOREIGN KEY ( n u m c l i , n u m o p e r )
REFERENCES COMPTECLIENT ( numcli , numccl ) ,
CONSTRAINT f k _ o p e r _ c o d e o p e r
FOREIGN KEY ( n u m t y p e o p e r )
REFERENCES typeoperation ( numtypeoper ) ,
CONSTRAINT m o n t a n t _ o p e r a t i o n
CHECK( m o n t a n t o p e r <> 0 AND m o n t a n t o p e r >= 1000 AND m o n t a n t o p e r <= 1 0 0 0 )
);
INSERT INTO T Y P E C C L VALUES (
(SELECT n v l (MAX( n u m t y p e c c l ) , 0 ) + 1
FROM T Y P E C C L
),
Compte c o u r a n t ) ;
INSERT INTO T Y P E C C L VALUES (
(SELECT n v l (MAX( n u m t y p e c c l ) , 0 ) + 1
FROM T Y P E C C L
),
livret );
INSERT INTO T Y P E C C L VALUES (
(SELECT n v l (MAX( n u m t y p e c c l ) , 0 ) + 1
FROM T Y P E C C L
),
PEL ) ;
INSERT INTO T Y P E O P E R A T I O N VALUES (
(SELECT n v l (MAX( n u m t y p e o p e r ) , 0 ) + 1
FROM T Y P E O P E R A T I O N
),
p

c At
dA
esp Aces
);
INSERT INTO T Y P E O P E R A T I O N VALUES (
(SELECT n v l (MAX( n u m t y p e o p e r ) , 0 ) + 1
FROM T Y P E O P E R A T I O N
),
l

c Avement
prA
);
INSERT INTO T Y P E O P E R A T I O N VALUES (
(SELECT n v l (MAX( n u m t y p e o p e r ) , 0 ) + 1
FROM T Y P E O P E R A T I O N
),
virement ) ;
INSERT INTO T Y P E O P E R A T I O N VALUES (
(SELECT n v l (MAX( n u m t y p e o p e r ) , 0 ) + 1
FROM T Y P E O P E R A T I O N
),
retrait );

75

A.8
DROP
DROP
DROP
DROP
DROP
DROP

Secr
etariat p
edagogique

TABLE
TABLE
TABLE
TABLE
TABLE
TABLE

RESULTAT ;
EXAMEN ;
PREREQUIS ;
INSCRIPTION ;
MODULE ;
ETUDIANT ;

CREATE TABLE E T U D I A N T
( n u m E t u d number ,
n o m varchar2 ( 4 0 ) ,
p r e n o m varchar2 ( 4 0 ) ,
d a t e n a i s s date ,
c i v i l i t e varchar2 ( 4 ) ,
p a t r o n y m e varchar2 ( 4 0 ) ,
n u m s e c u varchar2 ( 1 5 ) NOT NULL) ;
CREATE TABLE M O D U L E
( c o d M o d number ,
n o m M o d varchar2 ( 1 5 ) ,
e f f e c M a x number DEFAULT 3 0 ) ;
CREATE TABLE E X A M E N
( c o d M o d number ,
c o d E x a m number ,
dateExam date ) ;
CREATE TABLE I N S C R I P T I O N
( n u m E t u d number ,
c o d M o d number ,
dateInsc date default sysdate ) ;
CREATE TABLE P R E R E Q U I S
( c o d M o d number ,
c o d M o d P r e r e q number ,
n o t e M i n number ( 4 , 2 ) NOT NULL) ;
CREATE TABLE R E S U L T A T
( c o d M o d number ,
c o d E x a m number ,
n u m E t u d number ,
n o t e number ( 4 , 2 ) ) ;
ALTER TABLE E T U D I A N T ADD
CONSTRAINT p k _ e t u d i a n t
PRIMARY KEY ( n u m E t u d ) ;
ALTER TABLE M O D U L E ADD
CONSTRAINT p k _ m o d u l e
PRIMARY KEY ( c o d M o d ) ;
ALTER TABLE E X A M E N ADD
CONSTRAINT p k _ e x a m e n
PRIMARY KEY ( c o d M o d , c o d E x a m ) ;
ALTER TABLE P R E R E Q U I S ADD
CONSTRAINT p k _ p r e r e q u i s
PRIMARY KEY ( c o d M o d , c o d M o d P r e r e q ) ;
ALTER TABLE I N S C R I P T I O N ADD
CONSTRAINT p k _ i n s c r i p t i o n
PRIMARY KEY ( c o d M o d , n u m E t u d ) ;
ALTER TABLE R E S U L T A T ADD
CONSTRAINT p k _ r e s u l t a t
PRIMARY KEY ( c o d M o d , n u m E t u d , c o d E x a m ) ;
ALTER TABLE I N S C R I P T I O N ADD
(CONSTRAINT f k _ i n s c r i p t i o n _ e t u d i a n t
FOREIGN KEY ( n u m E t u d )
REFERENCES ETUDIANT ( numEtud ) ,
CONSTRAINT f k _ i n s c r i p t i o n _ m o d u l e
FOREIGN KEY ( c o d M o d )
REFERENCES MODULE ( codMod ) ) ;
ALTER TABLE P R E R E Q U I S ADD
(CONSTRAINT f k _ p r e r e q u i s _ c o d m o d
FOREIGN KEY ( c o d M o d )
REFERENCES MODULE ( codMod ) ,
CONSTRAINT f k _ p r e r e q u i s _ c o d m o d p r e r e q
FOREIGN KEY ( c o d M o d P r e r e q )
REFERENCES MODULE ( codMod ) ) ;
ALTER TABLE E X A M E N ADD
CONSTRAINT f k _ e x a m e n
FOREIGN KEY ( c o d M o d )
REFERENCES MODULE ( codMod ) ;
ALTER TABLE R E S U L T A T ADD
(CONSTRAINT f k _ r e s u l t a t _ e x a m e n
FOREIGN KEY ( c o d M o d , c o d E x a m )
REFERENCES EXAMEN ( codMod , codExam ) ,
CONSTRAINT f k _ r e s u l t a t _ i n s c r i p t i o n
FOREIGN KEY ( c o d M o d , n u m E t u d )
REFERENCES INSCRIPTION ( codMod , numEtud ) ) ;

76

ALTER TABLE E T U D I A N T ADD


(CONSTRAINT c k _ c i v i l i t e
CHECK
(
c i v i l i t e IN ( Mr , Mme , M l l e )
),
CONSTRAINT c k _ c i v i l i t e _ n u m s e c u
CHECK
(
SUBSTR( n u m s e c u , 1 , 1 ) = 2 OR p a t r o n y m e I S NULL
),
CONSTRAINT c k _ l e n g t h _ n u m s e c u
CHECK
(
l e n g t h ( n u m s e c u ) = 15
),
CONSTRAINT c k _ a n n e e _ n u m s e c u CHECK
(
t o _ c h a r ( d a t e n a i s s , yy ) = substr ( n u m s e c u , 2 , 2 )
)
);

77

A.9

Mariages

CREATE TABLE P E R S O N N E
( n u m p e r s number PRIMARY KEY,
n o m varchar2 ( 3 0 ) NOT NULL,
p r e n o m varchar2 ( 3 0 ) ,
pere REFERENCES PERSONNE ( numpers ) ,
mere REFERENCES PERSONNE ( numpers )
);
CREATE TABLE M A R I A G E
(
n u m m a r i NUMBER R E F E R E N C E S P E R S O N N E ( n u m p e r s ) ,
n u m f e m m e NUMBER R E F E R E N C E S P E R S O N N E ( n u m p e r s ) ,
d a t e m a r i a g e DATE DEFAULT S Y S D A T E ,
d a t e d i v o r c e DATE DEFAULT NULL,
PRIMARY KEY( n u m m a r i , n u m f e m m e , d a t e M a r i a g e )
);

78

Vous aimerez peut-être aussi