Professional Documents
Culture Documents
Alexandre Meslé
4 octobre 2008
Table des matières
1 Notes de cours 4
1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1.1 Qu’est-ce qu’un SGBD ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1.2 Organisation relationnelle des données . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1.3 Survol de SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.1.4 SQL+ et iSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2 Contraintes déclaratives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.1 Valeurs par défaut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.2 Champs non renseignés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.3 Clé primaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.4 Clé étrangère . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.5 Syntaxe alternative . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.3 Requêtes mono-tabulaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3.1 Compléments sur SELECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3.2 Instruction WHERE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3.3 Conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3.4 Suppression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.3.5 Mise à jour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4 Requêtes multi-tabulaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4.2 Produit cartésien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.4.3 Jointure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.4.4 Jointures refléxives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.5 Agrégation de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.5.1 Fonctions d’agrégation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.5.2 Groupage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.6 Vues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.6.1 Définition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.6.2 Syntaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.6.3 Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.6.4 Suppression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.7 Requêtes imbriquées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
1.7.1 Sous requêtes renvoyant une valeur scalaire . . . . . . . . . . . . . . . . . . . . . . 23
1.7.2 Sous requêtes renvoyant une colonne . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.7.3 Sous requêtes non correlées renvoyant une table . . . . . . . . . . . . . . . . . . . . 25
1.7.4 Sous requêtes correlées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
1.8 Compléments sur les types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.8.1 Types numériques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.8.2 Types chaine de caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.8.3 Types date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.8.4 La fonction inclassable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.8.5 Contraintes CHECK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.9 Noyau impératif du PL/SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
1
1.9.1 PL/SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
1.9.2 Blocs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
1.9.3 Affichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
1.9.4 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
1.9.5 Traitements conditionnels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
1.9.6 Traitements répétitifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
1.10 Tableaux et structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
1.10.1 Tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
1.10.2 Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
1.11 Applications du PL/SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
1.11.1 Affectation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
1.11.2 Tables et structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
1.11.3 Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
1.12 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
1.12.1 Rattraper une exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
1.12.2 Exceptions prédéfinies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
1.12.3 Codes d’erreur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
1.12.4 Déclarer et lancer ses propres exceptions . . . . . . . . . . . . . . . . . . . . . . . . 42
1.13 Sous-programmes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.13.1 Procédures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.13.2 Fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.14 Curseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.14.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.14.2 Les curseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.15 Curseurs parametrés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
1.15.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
1.15.2 Définition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
1.15.3 Déclaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
1.15.4 Ouverture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
1.15.5 Lecture d’une ligne, fermeture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
1.15.6 Boucle pour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
1.15.7 Exemple récapitulatif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
1.16 Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
1.16.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
1.16.2 Classification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
1.16.3 Création . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
2 Exercices 54
2.1 Contraintes déclaratives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
2.2 Requêtes monotabulaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
2.3 Requêtes multitabulaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
2.4 Agrégation de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
2.5 Vues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
2.6 Requêtes imbriquées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
2.7 Compléments sur les types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
2.8 Révisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
2.9 Examen Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
2.10 Introduction au PL/SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
2.11 Tableaux et Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
2.12 Applications du PL/SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
2.13 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
2.14 Sous-programmes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
2.15 Curseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
2.16 Curseurs parametrés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
2.17 Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
2
3 Corrigés 90
3.1 Contraintes déclaratives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
3.2 Requêtes monotabulaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
3.3 Requêtes multitabulaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
3.4 Agrégation de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
3.5 Vues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
3.6 Requêtes imbriquées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
3.7 Compléments sur les types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
3.8 Révisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
3.9 Examen Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
3.10 Introduction au PL/SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
3.11 Tableaux et Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
3.12 Application du PL/SQL et Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
3.13 Sous-programmes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
3.14 Curseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
3.15 Curseurs paramétrés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
3.16 Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
3
Chapitre 1
Notes de cours
1.1 Introduction
1.1.1 Qu’est-ce qu’un SGBD ?
– Définition : logiciel qui stocke des données de façon organisée et cohérente.
– Access : version édulcorée. Mais mono-utilisateur, et faible capacité.
– Les données sont stockées dans des fichiers gérés par le serveur de base de données. Cette opération
est opaque. On transmet depuis un client des instructions à la base par l’intermédiaire du langage
SQL.
Avantages :
– permet de maintenir de façon fiable l’intégrité des données
– opérations de bas niveau opaques
– rapide
– multi-utilisateurs
– moins de trafic sur le réseau
– sécurité
Inconvénient :
– Un peu plus long que bien programmé en C, et encore...
Plusieurs façons d’organiser les données :
– hiérarchique
– relationnel
– déductif
– objet
– etc.
Les gros SGBD-R :
– DB2 (IBM)
– Oracle
– Microsoft SQL Server
– mySQL
SQL
Structured Query Language. SQL est le langage standard de la base de données. D’un SGBD à l’autre,
le SQL change très peu. Ce cours est surtout un cours de SQL.
4
– Table : tableau à deux entrées.
Le MPD nous donne, pour chaque table, les colonnes (i.e. champs) que doit comporter la table.
nomtable ( c o l o n n e 1 , c o l o n n e 2 , . . . , c o l o n n e n )
Par exemple :
CLIENT( numero , prenom , nom , e m a i l )
Nous pouvons représenter la base, avec quelques données insérées, par des tableaux
5
#numero client #numero commande #numero produit quantite
1 1 5 2
1 2 4 29
1 2 7 1
2 1 1 4
3 1 9 238
6
1.1.4 SQL+ et iSQL
Connection
login : scott
password : tiger
SELECT t a b l e n a m e FROM u s e r t a b l e s ;
Description des tables
Syntaxe :
DESC <nomtable >;
Exemple :
DESC c l i e n t ;
Attention
Les commandes de SQL+ se terminent par un point-virgule !
7
1.2 Contraintes déclaratives
1.2.1 Valeurs par défaut
create table c l i e n t
(
numcli number,
nom varchar2 ( 2 5 6 ) default ’ Moi ’ ,
prenom varchar2 ( 2 5 6 )
)
fait de ’Moi’ le nom par défaut.
1.2.2 Champs non renseignés
create table c l i e n t
(
numcli number,
nom varchar2 ( 2 5 6 ) NOT NULL,
prenom varchar2 ( 2 5 6 ) NOT NULL
)
force la saisie des champs nom et prénom.
1.2.3 Clé primaire
Une clé primaire est :
– toujours renseignée
– unique
On peut préciser PRIMARY KEY dans la création de table
create table c l i e n t
(
numcli number PRIMARY KEY,
nom varchar2 ( 2 5 6 ) ,
prenom varchar2 ( 2 5 6 )
)
La colonne numcli est clé primaire, toute insertion ne respectant pas la contraine de clé primaire sera
refusée par Oracle.
create table c l i e n t
(
numcli number PRIMARY KEY,
nom varchar2 ( 2 5 6 ) ,
prenom varchar2 ( 2 5 6 ) ,
numdept number REFERENCES DEPT ( nd )
)
Une ligne ne pourra être insérée dans la table client que s’il existe dans la table DEPT une ligne dont la
valeur nd est la même que la valeur numdept en cours d’insertion.
On remarque qu’il devient impossible d’écraser la table DEPT si elle est référencée par une clé étrangère.
8
1.2.5 Syntaxe alternative
9
1.3 Requêtes mono-tabulaires
1.3.1 Compléments sur SELECT
Il est possible d’utiliser SELECT pour n’afficher que certaines colonnes d’une table. Syntaxe :
SELECT <c o l o n n e 1 >, <c o l o n n e 2 >, . . . , <c o l o n n e n >
FROM <table>
Cette instruction s’appelle une requête, elle affichera pour chaque ligne de la table les valeurs des colonnes
colonne1 à colonnen . Il est possible de supprimer les lignes en double à l’aide du mot-clé DISTINCT. Par
exemple :
SELECT DISTINCT <c o l o n n e 1 >, <c o l o n n e 2 >, . . . , <c o l o n n e n >
FROM <table>
Pour trier les données, on utilise ORDER BY. Exemple :
SELECT <c o l o n n e 1 >, <c o l o n n e 2 >, . . . , <c o l o n n e n >
FROM <table>
ORDER BY <c o l o n n e 1 b i s >, <c o l o n n e 2 b i s >, . . . , <c o l o n n e n b i s >
Cette instruction trie les données par colonne1bis croissants. En cas d’égalité, le tri est fait par colonne2bis
croissants, etc. Pour trier par ordre décroissant, on ajoute DESC après le nom de la colonne choisie comme
critère décroissant. Par exemple :
SELECT <c o l o n n e 1 >, <c o l o n n e 2 >, . . . , <c o l o n n e n >
FROM <table>
ORDER BY <c o l o n n e 1 b i s > DESC, <c o l o n n e 2 b i s >, . . . , <c o l o n n e n b i s >
1.3.3 Conditions
Comparaison
Les conditions peuvent être des relations d’égalité (=), de différence (<>), d’inégalité (<, >, >= ou <=)
sur des colonnes :
numero client = 2
nom client = ’ Chirac ’
p r e n o m c l i e n t <> ’ Hubert ’
s a l a r y < 230
t a x e s >= 23000
10
Négation
La négation d’une condition s’obtient à l’aide de NOT. Par exemple, il est possible de ré-ecrire les conditions
ci-avant :
NOT ( n u m e r o c l i e n t <> 2 )
NOT ( n o m c l i e n t <> ’ C h i r a c ’ )
NOT ( p r e n o m c l i e n t = ’ Hubert ’ )
NOT ( s a l a r y >= 2 3 0 )
NOT ( taxes < 23000)
Connecteurs logiques
De même, vous avez à votre disposition tous les connecteurs logiques binaires : AND, OR. Ainsi, les deux
conditions suivantes sont les mêmes :
NOT( ( nom = ’ Bush ’ ) AND ( prenom <> ’ Medor ’ ) )
(nom <> ’ Bush ’ ) OR ( prenom = ’ Medor ’ )
NULLité
Un champ non renseigné a la valeur NULL, dans une comparaison, NULL n’est jamais égal à quelque valeur
qu’il soit ! La condition suivante est toujours fausse :
NULL = NULL;
La requête suivante ne renvoie aucune ligne :
SELECT ∗ FROM EMP WHERE COMM=NULL;
Pour tester la nullité d’un champ, on utilise IS NULL, par exemple :
SELECT ∗ FROM EMP WHERE COMM IS NULL;
La non-nullité se teste de deux façons :
WHERE NOT (COMM IS NULL) ;
WHERE COMM IS NOT NULL
Encadrement
Une valeur numérique peut être encadrée à l’aide de l’opérateur BETWEEN, par exemple les deux conditions
suivantes sont équivalentes :
SALAIRE BETWEEN 1000 AND 5000
(SALAIRE >= 1 0 0 0 ) AND (SALAIRE <= 5 0 0 0 )
Inclusion
L’opérateur IN permet de tester l’appartenance à une liste de valeurs. Les deux propositions suivantes
sont équivalentes
NAME IN ( ’ Mesle ’ , ’ Bush ’ , ’ Medor ’ )
(NAME = ’ Mesle ’ ) OR (NAME = ’ Bush ’ ) OR (NAME = ’ Medor ’ )
11
LIKE
LIKE sert à comparer le contenu d’une variable à un littéral générique. Par exemple, la condition
NAME LIKE ’M%’
sera vérifiée si NAME commence par un ’M’. Ca fonctionne aussi sur les valeurs de type numérique, la
condition
SALARY LIKE ’ %000000000 ’
sera vérifiée si SALARY se termine par 000000000. Le caractère % peut remplacer dans le littéral n’importe
que suite, vide ou non, de caractères ; il a le même rôle que * en DOS et en SHELL. Le caractère
remplace un et un seul caractère dans le littéral. Par exemple, la condition
NAME LIKE ’ B s%’
ne sera vérifiée que si NAME commence par un ’B’ et contient un ’s’ en troisième position.
1.3.4 Suppression
L’expression
DELETE FROM <NOMTABLE> WHERE <CONDITION>
efface de la table NOMTABLE toutes les lignes vérifiant condition. Attention ! La commande
DELETE FROM <NOMTABLE>
efface toutes les lignes de la table NOMTABLE !
12
1.4 Requêtes multi-tabulaires
1.4.1 Principe
Etant donné le code ci-dessous,
CREATE TABLE MODULE
(numMod number primary key ,
nomMod varchar2 ( 3 0 )
);
NUMMOD
−−−−−−−−−−
6
Ensuite, cherchons les numéros des modules prérequis pour s’inscrire dans le module numéro 6,
SQL> SELECT numModPrereq FROM p r e r e q u i s WHERE numMod = 6 ;
NUMMODPREREQ
−−−−−−−−−−−−
1
5
Et pour finir, allons récupérer les noms de ces modules,
SQL> SELECT nomMod FROM module WHERE numMod IN ( 1 , 5 ) ;
NOMMOD
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
13
Oracle
Merise
Vous êtes probablement tous en train de vous demander s’il n’existe pas une méthode plus simple et plus
rapide, et surtout une façon d’automatiser ce que nous venons de faire. Il existe un moyen de sélectionner
des données dans plusieurs tables simultanément. Pour traiter la question ci-dessus il suffisait de saisir :
SQL> SELECT m2 . nomMod
2 FROM module m1, module m2, p r e r e q u i s p
3 WHERE m1 . numMod = p . numMod AND m2 . numMod = p . numModprereq
4 AND m1 . nomMod = ’PL/SQL O r a c l e ’ ;
NOMMOD
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Oracle
Merise
Le but de ce chapitre est d’expliciter ce type de commande.
16 l i g n e ( s ) s e l e c t i o n n e e ( s ) .
Placer une liste de tables dans le FROM revient à former toutes les combinaisons de lignes possibles.
Cependant, cela a relativement peu de sens.
14
1.4.3 Jointure
Il serait plus intéressant, dans le cas présent, de ne voir s’afficher que des lignes dont les numéros de
produits concordent. Pour ce faire, il suffit d’utiliser WHERE. Par exemple,
SQL> SELECT ∗ FROM p r o p o s e r , p r o d u i t
2 WHERE p r o p o s e r . numprod = p r o d u i t . numprod ;
NOMFOU NOMPROD
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
f1 Roue de s e c o u r s
f2 Poupee Batman
f1 Poupee Batman
f3 Cotons t i g e s
NOMFOU NOMPROD
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
f1 Roue de s e c o u r s
f2 Poupee Batman
f1 Poupee Batman
f3 Cotons t i g e s
Le renommage permet entre autres de faire des jointures réflexives, c’est à dire entre une table et elle
même. Par exemple, en reprenant la table intervalle,
SQL> SELECT ∗ FROM i n t e r v a l l e ;
BORNEINF BORNESUP
15
−−−−−−−−−− −−−−−−−−−−
0 30
2 3
2 56
5 10
7 32
8 27
12 3
12 30
21 8
34 26
10 l i g n e ( s ) s e l e c t i o n n e e ( s ) .
La commande ci-dessous affiche tous les couples d’intervalles ayant une borne en commun,
SQL> SELECT ∗ FROM i n t e r v a l l e i , i n t e r v a l l e j
2 WHERE ( i . b o r n e I n f = j . b o r n e I n f OR i . borneSup = j . borneSup )
3 AND i . rowid <> j . rowid ;
8 ligne ( s ) selectionnee ( s ).
Que ceux qui ont du courage reformulent la requête sans utiliser le rowid !
16
1.5 Agrégation de données
1.5.1 Fonctions d’agrégation
Exemple introductif
Nous voulons connaı̂tre le nombre de lignes de table produit. Deux façons de procéder :
1. Solution pour les boeufs
SQL> SELECT ∗ FROM PRODUIT;
NUMPROD NOMPROD
−−−−−−−−−− −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
1 Roue de s e c o u r s
2 Poupee Batman
3 Cotons t i g e s
4 Cornichons
4 ligne ( s ) selectionnee ( s ).
On a la réponse avec le nombre de lignes sélectionnées.
2. Solution pour les boss
SQL> SELECT count ( ∗ ) FROM PRODUIT;
COUNT( ∗ )
−−−−−−−−−−
4
1 ligne selectionnee .
La réponse est le résultat de la requête.
Que s’est-il passé ? Qu’est-ce donc que cette requête ésotérique ? Réponse : Le cours d’aujourd’hui.
Définition
Une fonction d’agrégation retourne une valeur calculée sur toutes les lignes de la requête (nombre,
moyenne...). Nous allons utiliser les suivantes :
– COUNT(col) : retourne le nombre de lignes dont le champ col est non NULL.
– AVG(col) : retourne la moyenne des valeurs col sur toutes les lignes dont le champ col est non
NULL.
– MAX(col) : retourne la plus grande des valeurs col sur toutes les lignes dont le champ col est non
NULL.
– MIN(col) : retourne la plus petite des valeurs col sur toutes les lignes dont le champ col est non
NULL.
– SUM(col) : retourne la somme des valeurs col sur toutes les lignes dont le champ col est non NULL.
Exemples d’utilisation
L’exemple suivant retourne le prix du produit proposé au prix maximal.
SQL> SELECT MAX( p r i x )
2 FROM PROPOSER;
MAX(PRIX)
−−−−−−−−−−
200
17
1 ligne selectionnee .
Il est possible de renommer la colonne MAX(prix), en utilisant le mot clé AS :
SQL> SELECT MAX( p r i x ) AS PRIX MAXIMAL
2 FROM PROPOSER;
PRIX MAXIMAL
−−−−−−−−−−−−
200
1 ligne selectionnee .
Les requêtes suivantes récupèrent le nom du fournisseur proposant l’article ’Poupée Batman’ au prix le
moins élevé :
SQL> SELECT MIN( p r i x ) AS PRIX MINIMUM
2 FROM PROPOSER PR, PRODUIT P
3 WHERE PR. numprod = P . numprod
4 AND nomprod = ’ Poupee Batman ’ ;
PRIX MINIMUM
−−−−−−−−−−−−
1
1 ligne selectionnee .
NOMFOU
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
f2
1 ligne selectionnee .
Il est possible de faire cela avec une seule requête en récupérant le prix minimum dans une requête
imbriquée. Mais cela sera pour un cours ultérieur.
NB PROD
−−−−−−−−−−
2
1 ligne selectionnee .
18
On aurait aussi pu saisir :
SQL> SELECT COUNT( numprod ) AS NB PROD
2 FROM FOURNISSEUR F , PROPOSER P
3 WHERE F . numfou = P . numfou
4 AND nomfou = ’ f 1 ’ ;
NB PROD
−−−−−−−−−−
2
1 ligne selectionnee .
Pour connaı̂tre le nombre de produits proposés, c’est à dire dont le numprod a une occurence dans la table
PROPOSER, on procède de la façon suivante :
SQL> SELECT COUNT(DISTINCT numprod ) AS NB PRODUITS PROPOSES
2 FROM PROPOSER;
NB PRODUITS PROPOSES
−−−−−−−−−−−−−−−−−−−−
3
1 ligne selectionnee .
Le DISTINCT nous sert à éviter qu’un même produit proposé par des fournisseurs différents soit compta-
bilisé plusieurs fois.
1.5.2 Groupage
L’instruction GROUP BY
Les opération d’agrégation considérées jusqu’à maintenant portent sur la totalité des lignes retournées
par les requêtes, l’instruction GROUP BY permet de former des paquets à l’intérieur desquels les données
seront agrégées. Cette instruction s’utilise de la manière suivante
SELECT . . .
FROM . . .
WHERE. . .
GROUP BY < l i s t e c o l o n n e s >
ORDER BY . . .
La liste des colonnes sert de critère pour répartir les lignes dans des paquets de lignes. Si par exemple
nous souhaitons afficher la liste des nombres de produits proposés par chaque fournisseur :
SQL> SELECT nomfou , COUNT(DISTINCT numprod ) AS NB PRODUITS PROPOSES
2 FROM FOURNISSEUR F , PROPOSER P
3 WHERE F . numfou = P . numfou
4 GROUP BY nomfou ;
3 ligne ( s ) selectionnee ( s ).
19
L’instruction HAVING
Supposons que de la requête précédente, nous ne souhaitions garder que les lignes pour lesquelles la
valeur NB PRODUITS PROPOSES est égale à 1. Ajouter une condition dans WHERE serait inutile, le filtrage
occasionné par WHERE est effectué avant l’agrégation. Il nous faudrait une instruction pour n’inclure que
des groupes de données répondant certains critères. L’instruction utilisée pour ce faire est HAVING. Son
utilisation est la suivante :
SELECT . . .
FROM . . .
WHERE . . .
GROUP BY. . .
HAVING <c o n d i t i o n >
ORDER BY . . .
Par exemple,
SQL> SELECT nomfou , COUNT(DISTINCT numprod ) AS NB PRODUITS PROPOSES
2 FROM FOURNISSEUR F , PROPOSER P
3 WHERE F . numfou = P . numfou
4 GROUP BY nomfou
5 HAVING COUNT(DISTINCT numprod ) = 1
6 ORDER BY nomfou DESC;
2 ligne ( s ) selectionnee ( s ).
Affichons les noms des fournisseurs qui ont livré strictement plus d’un produit différent (toutes livraisons
confondues),
SQL> SELECT nomfou
2 FROM FOURNISSEUR F , DETAILLIVRAISON D
3 WHERE F . numfou = D. numfou
4 GROUP BY nomfou
5 HAVING count (DISTINCT D. numprod ) > 1 ;
NOMFOU
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
f1
1 ligne selectionnee .
20
1.6 Vues
1.6.1 Définition
Une vue est une table contenant des données calculées sur celle d’une autre table. Les données d’une vue
sont tout le temps à jour. Si vous modifiez les données d’une des tables sur lesquelles est calculée la vue,
alors les modifications sont automatiquement répercutées sur la vue.
1.6.2 Syntaxe
Appréciez la simplicité de la syntaxe :
CREATE VIEW <nom vue> AS <r e q u e t e >
1.6.3 Application
Par exemple, la requête suivante met en correpondance les noms des produits avec le nombre de fournis-
seurs qui le proposent :
SQL> SELECT nomprod , COUNT( numfou ) AS NB FOURNISSEURS
2 FROM PRODUIT P
3 LEFT OUTER JOIN PROPOSER PR
4 ON P . numprod = PR. numprod
5 GROUP BY nomprod
6 ORDER BY COUNT( numfou ) ;
NOMPROD NB FOURNISSEURS
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− −−−−−−−−−−−−−−−
Cornichons 0
Cotons t i g e s 1
Roue de s e c o u r s 1
Poupee Batman 2
4 ligne ( s ) selectionnee ( s ).
Ce type de requête sera explité dans un cours ultérieur. Pour le moment, notez juste que les outils dont
vous disposez pour le moment ne vous permettront pas de formuler une requête affichant les noms des
produits n’ayant aucun fournisseur. Créons une vue pour ne pas avoir à se farcir la requête chaque fois
que nous aurons besoin de ces informations :
SQL> CREATE VIEW NB FOURNISSEURS PAR PRODUIT AS
2 SELECT nomprod , COUNT( numfou ) AS NB FOURNISSEURS
3 FROM PRODUIT P
4 LEFT OUTER JOIN PROPOSER PR
5 ON P . numprod = PR. numprod
6 GROUP BY nomprod
7 ORDER BY COUNT( numfou ) ;
Vue c r e e e .
Une fois créée, on peut interroger une vue de la même façon qu’on interroge une table :
SQL> SELECT ∗
2 FROM NB FOURNISSEURS PAR PRODUIT ;
NOMPROD NB FOURNISSEURS
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− −−−−−−−−−−−−−−−
Cornichons 0
21
Cotons t i g e s 1
Roue de s e c o u r s 1
Poupee Batman 2
4 ligne ( s ) selectionnee ( s ).
Notez que toute modification dans la table PROPOSER ou PRODUIT sera immédiatement répercutée sur la
vue.
SQL> INSERT INTO PROPOSER VALUES ( 3 , 4 , 9 ) ;
1 ligne creee .
SQL> SELECT ∗
2 FROM NB FOURNISSEURS PAR PRODUIT ;
NOMPROD NB FOURNISSEURS
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− −−−−−−−−−−−−−−−
Cornichons 1
Cotons t i g e s 1
Roue de s e c o u r s 1
Poupee Batman 2
4 ligne ( s ) selectionnee ( s ).
Maintenant, nous souhaitons voir s’afficher, pour tout i, le nombre de produits proposés par exactement
i fournisseurs.
SQL> SET head o f f
SQL> SELECT ’ I l y a ’ | | COUNT(NOMPROD) | | ’ p r o d u i t ( s ) q u i e s t / s o n t ’ | |
2 ’ p r o p o s e ( s ) par ’ | | NB FOURNISSEURS | | ’ f o u r n i s s e u r ( s ) . ’
3 FROM NB FOURNISSEURS PAR PRODUIT
4 GROUP BY NB FOURNISSEURS
5 ORDER BY NB FOURNISSEURS ;
I l y a 3 p r o d u i t ( s ) q u i e s t / s o n t p r o p o s e ( s ) par 1 f o u r n i s s e u r ( s ) .
I l y a 1 p r o d u i t ( s ) q u i e s t / s o n t p r o p o s e ( s ) par 2 f o u r n i s s e u r ( s ) .
2 ligne ( s ) selectionnee ( s ).
1.6.4 Suppression
On supprime une vue avec l’instruction suivante :
DROP VIEW <nom vue >;
22
1.7 Requêtes imbriquées
Oracle permet d’imbriquer les requêtes, c’est-à-dire de placer des requêtes dans les requêtes. Une requête
imbriquée peut renvoyer trois types de résultats :
– une valeur scalaire
– une colonne
– une table
COUNT( ∗ )
−−−−−−−−−−
21
On peut placer dans une requête une sous-requête calculant un résultat scalaire. Un tel type de sous-
requête se place soit comme une colonne supplémentaire, soit comme une valeur servant à évaluer des
conditions (WHERE ou HAVING).
Colonne fictive
On peut ajouter une colonne dans une requête, et choisir comme valeurs pour cette colonne le résultat
d’une requête. Ce type de requête est souvent une alternative à GROUP BY. Par exemple, la requête suivante
nous renvoie, pour tout produit, le nombre de fournisseurs proposant ce produit :
SQL> SELECT nomprod , (SELECT COUNT( ∗ )
2 FROM PROPOSER PR
3 WHERE PR. numprod = P . numprod )
4 AS NB FOURNISSEURS
5 FROM PRODUIT P ;
NOMPROD NB FOURNISSEURS
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− −−−−−−−−−−−−−−−
Roue de s e c o u r s 1
Poupee Batman 2
Cotons t i g e s 1
Cornichons 0
Conditions complexes
On peut construire une condition en utilisant le résultat d’une requête. Pour notre exemple, déclarons
d’abord une vue contenant le nombe d’articles proposés par chaque fournisseur,
SQL> CREATE VIEW NB PROD PAR FOU AS
2 SELECT numfou , (SELECT COUNT( ∗ )
3 FROM PROPOSER P
4 WHERE P . numfou = F . numfou )
5 AS NB PROD
6 FROM FOURNISSEUR F ;
Vue c r e e e .
Ensuite, recherchons les noms des fournisseurs proposant le plus de produits :
23
SQL> SELECT nomfou
2 FROM FOURNISSEUR F , NB PROD PAR FOU N
3 WHERE F . numfou = N. numfou
4 AND NB PROD = (SELECT MAX(NB PROD)
5 FROM NB PROD PAR FOU ) ;
NOMFOU
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
f1
La requête SELECT MAX(NB PROD) FROM NB PROD PAR FOU est évaluée avant, et son résultat lui est sub-
stitué dans l’expression de la requête. Comme on a
SQL> SELECT MAX(NB PROD) FROM NB PROD PAR FOU ;
MAX(NB PROD)
−−−−−−−−−−−−
2
Alors la requête précédente, dans ce contexte, est équivalente à
SQL> SELECT nomfou
2 FROM FOURNISSEUR F , NB PROD PAR FOU N
3 WHERE F . numfou = N. numfou
4 AND NB PROD = 2 ;
NOMFOU
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
f1
INSERT et UPDATE
On peut placer dans des instructions de mises à jour ou d’insertions des requêtes imbriquées. Par exemple,
SQL> INSERT INTO PERSONNE ( numpers , nom , prenom )
2 VALUES ( (SELECT MAX( numpers ) + 1 FROM PERSONNE) ,
3 ’ Darth ’ , ’ Vador ’ ) ;
1 ligne creee .
SQL> UPDATE PERSONNE SET
2 p e r e = (SELECT numpers
3 FROM PERSONNE
4 WHERE nom = ’ S o c r a t e ’
5 AND prenom IS NULL) ,
6 mere = (SELECT numpers
7 FROM PERSONNE
8 WHERE nom = ’ Fabian ’
9 AND prenom = ’ Lara ’ )
10 WHERE numpers = (SELECT numpers
11 FROM PERSONNE
12 WHERE nom = ’ Darth ’
13 AND prenom = ’ Vador ’ ) ;
1 l i g n e mise a j o u r .
24
1.7.2 Sous requêtes renvoyant une colonne
On considère une colonne comme une liste de valeurs, on peut tester l’appartance d’un élément à cette
liste à l’aide de l’opérateur IN. On peut s’en servir comme une alternative aux jointures, par exemple,
réécrivons la requête de la section précédente. La requête suivante nous renvoie le nombre de produits
proposés par les fournisseurs proposant le plus de produits :
SQL> SELECT MAX(NB PROD) FROM NB PROD PAR FOU ;
MAX(NB PROD)
−−−−−−−−−−−−
2
Maintenant, recherchons les numéros des fournisseurs proposant un tel nombre de produits :
SQL> SELECT N. numfou
2 FROM NB PROD PAR FOU N
3 WHERE NB PROD = (SELECT MAX(NB PROD)
4 FROM NB PROD PAR FOU ) ;
NUMFOU
−−−−−−−−−−
1
Notons que s’il existe plusieurs fournisseurs proposant 2 produits, cette requête renverra plusieurs lignes.
C’est donc par hasard qu’elle ne retourne qu’une ligne. Le numéro du fournisseur proposant le plus de
produits est donc le 1. Cherchons ce fournisseur :
SQL> SELECT nomfou
2 FROM FOURNISSEUR F
3 WHERE F . numfou IN ( 1 ) ;
NOMFOU
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
f1
Il suffit donc dans la requête ci-dessous de remplacer le 1 par la requête qui a retourné 1. On a finalement :
SQL> SELECT nomfou
2 FROM FOURNISSEUR F
3 WHERE F . numfou IN (SELECT N. numfou
4 FROM NB PROD PAR FOU N
5 WHERE NB PROD = (SELECT MAX(NB PROD)
6 FROM NB PROD PAR FOU ) ) ;
NOMFOU
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
f1
25
6 FROM FOURNISSEUR F ;
NB PROD
−−−−−−−−−−
2
1
1
0
Cette table contient, pour chaque fournisseur, le nombre de produits proposés. Si l’on souhaite connaı̂tre
le plus grand nombre de produits proposés, on se sert du résultat de la requête ci-dessus comme d’une
table :
SQL> SELECT MAX(NB PROD) AS MAX NB PROD
2 FROM
3 (SELECT
4 (SELECT COUNT( ∗ )
5 FROM PROPOSER PR
6 WHERE PR. numfou = F . numfou
7 ) AS NB PROD
8 FROM FOURNISSEUR F
9 );
MAX NB PROD
−−−−−−−−−−−
2
Ce type de requête est une alternative aux vues. Récupérons maintenant les noms des fournisseurs pro-
posant le plus de produits (sans jointure et sans vue !) :
SQL> SELECT nomfou
2 FROM FOURNISSEUR
3 WHERE numfou IN
4 (SELECT numfou
5 FROM
6 (SELECT numfou ,
7 (SELECT COUNT( ∗ )
8 FROM PROPOSER PR
9 WHERE PR. numfou = F . numfou
10 ) AS NB PROD
11 FROM FOURNISSEUR F
12 ) N
13 WHERE NB PROD =
14 (SELECT MAX(NB PROD)
15 FROM
16 (SELECT numfou ,
17 (SELECT COUNT( ∗ )
18 FROM PROPOSER PR
19 WHERE PR. numfou = F . numfou
20 ) AS NB PROD
21 FROM FOURNISSEUR F
22 ) N
23 )
24 );
NOMFOU
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
26
f1
Vous constatez que la solution utilisant les vues est nettement plus simple.
NUMFOU NB PROD L
−−−−−−−−−− −−−−−−−−−−
1 45
2
3 10
4
Cette même requête, une fois évaluée, peut server de requête non correlée si on souhaite connaı̂tre les
noms de ces fournisseurs :
SQL> SELECT nomfou , NB PROD L
2 FROM FOURNISSEUR F ,
3 (SELECT numfou ,
4 (SELECT SUM( q t e )
5 FROM DETAILLIVRAISON D
6 WHERE D. numfou = F . numfou
7 ) NB PROD L
8 FROM FOURNISSEUR F
9 ) L
10 WHERE F . numfou = L . numfou ;
NOMFOU NB PROD L
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− −−−−−−−−−−
f1 45
f2
f3 10
f4
Amusons-nous : quel sont, pour chaque fournisseur, les produits qui ont été les plus livrés ?
SQL> SELECT nomfou , nomprod
2 FROM FOURNISSEUR F , PRODUIT P ,
3 (SELECT FF . numfou , PP . numprod
4 FROM FOURNISSEUR FF , PRODUIT PP
5 WHERE
6 (SELECT SUM( q t e )
7 FROM DETAILLIVRAISON L
8 WHERE L . numfou = FF . numfou
9 AND L . numprod = PP . numprod
27
10 )
11 =
12 (SELECT MAX(NB PROD L)
13 FROM
14 (SELECT numfou , SUM( q t e ) AS NB PROD L
15 FROM DETAILLIVRAISON L
16 GROUP BY numprod , numfou
17 ) Q
18 WHERE Q. numfou = FF . numfou
19 )
20 GROUP BY numfou , numprod
21 ) M
22 WHERE M. numprod = P . numprod
23 AND M. numfou = F . numfou ;
NOMFOU NOMPROD
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
f1 Roue de s e c o u r s
f3 Cotons t i g e s
Dans la requête précédente, quelles sous-requêtes sont correlées et lesquelles ne le sont pas ?
28
1.8 Compléments sur les types
1.8.1 Types numériques
NUMBER(p, s) définit un type numérique de au plus (p − s) chiffres avant la virgule et au plus s chiffres
après la virgule.
SQL> CREATE TABLE TOTO
2 ( t u t u number( 4 , 2 )
3 );
Table c r e e e .
1 ligne creee .
1 ligne creee .
1 ligne creee .
1 ligne creee .
1 ligne creee .
1 ligne creee .
SQL> SELECT ∗
2 FROM TOTO;
TUTU
−−−−−−−−−−
29
10 ,2
10
,01
21 ,01
21
21 ,01
6 ligne ( s ) selectionnee ( s ).
DT
−−−−−−−−
30/10/06
30/10/06
SQL> SELECT t o c h a r ( d a t e l i , ’ yyyy ’ ) AS ANNEE
2 FROM LIVRAISON ;
ANNE
−−−−
2006
2006
SQL> SELECT t o c h a r ( d a t e l i , ’ yyyy /mm/dd ’ ) AS DT
2 FROM LIVRAISON ;
DT
−−−−−−−−−−
2006/10/30
2006/10/30
SQL> SELECT t o c h a r ( d a t e l i , ’yyyymmdd ’ ) AS DT
2 FROM LIVRAISON ;
DT
−−−−−−−−
20061030
20061030
On convertit une chaine de caractères en date avec la fonction to date(date, format). Par exemple :
30
SQL> UPDATE LIVRAISON
2 SET d a t e l i = t o d a t e ( ’ 1934 ’ | | t o c h a r ( d a t e l i , ’mmdd ’ ) , ’yyyymmdd ’ ) ;
2 l i g n e ( s ) mise ( s ) a j o u r .
SQL> SELECT ∗
2 FROM LIVRAISON ;
2 l i g n e ( s ) mise ( s ) a j o u r .
6 l i g n e ( s ) supprimee ( s ) .
SUM(TUTU)
−−−−−−−−−−
NVL(SUM(TUTU) , 0 )
−−−−−−−−−−−−−−−−
0
31
SQL> ALTER TABLE EMP ADD CONSTRAINT c k s a l a r y CHECK(SAL > 0 ) ;
Table m o d i f i e e .
32
1.9 Noyau impératif du PL/SQL
1.9.1 PL/SQL
Le PL de PL/SQL signifie Procedural Language. Il s’agit d’une extension procédurale du SQL permettant
d’effectuer des traitements complexes sur une base de données. Les possibilités offertes sont les mêmes
qu’avec des langages impératifs (instructions en séquence) classiques.
Ecrivez-le dans un éditeur dont vous copierez le contenu dans SQL+. Un script écrit en PL/SQL se termine
obligatoirement par un /, sinon SQL+ ne l’interprète pas. S’il contient des erreurs de compilation, il est
possible d’afficher les messages d’erreur avec la commande SQL+ : SHOW ERRORS.
1.9.2 Blocs
Tout code écrit dans un langage procédural est formé de blocs. Chaque bloc comprend une section de
déclaration de variables, et un ensemble d’instructions dans lequel les variables déclarées 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.9.3 Affichage
Pour afficher le contenu d’une variable, les procédures DBMS OUPUT.PUT() et DBMS OUPUT.PUT LINE()
prennent en argument une valeur à afficher ou une variable dont la valeur est à afficher. Par défaut, les
fonctions d’affichage sont desactivées. Il convient, à moins que vous ne vouliez rien voir s’afficher, de les
activer avec la commande SQL+ SET SERVEROUTPUT ON.
1.9.4 Variables
Une variable se déclare de la sorte :
nom type [ : = i n i t i a l i s a t i o n ] ;
L’initisation est optionnelle. Nous utiliserons les mêmes 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 ;
33
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 mêmes qu’en SQL. Le switch du langage C s’implémente en PL/SQL de la façon
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 é f a u t ∗/
END CASE
34
1.10 Tableaux et structures
1.10.1 Tableaux
Création d’un type tableau
Les types tableau doivent être définis explicitement par une déclaration 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 crée par cette instruction
– taille est le nombre maximal d’éléments qu’il est possible de placer dans le tableau.
– typeElements est le type des éléments qui vont être stockés dans le tableau, il peut s’agir de
n’importe quel type.
Par exemple, créons un type tableau de nombres indicé de 1 à 10, que nous appelerons numberTab
TYPE numberTab IS VARRAY ( 1 0 ) OF NUMBER;
35
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 d’utiliser les éléments du tableau t(1), t(2), t(3)
et t(4). Il n’est pas possible ”d’étendre” un tableau à une taille supérieure à celle spécifiée lors de la
création du type tableau associé.
1.10.2 Structures
Un structure est un type regroupant plusieurs types. Une variable de type structuré contient plusieurs
variables, ces variables s’appellent aussi des champs.
36
TYPE p o i n t IS RECORD
(
a b s c i s s e NUMBER,
ordonnee NUMBER
);
Notez bien que les types servant à définir un type structuré peuvent être quelconques : variables scalaires,
tableaux, structures, etc.
37
1.11 Applications du PL/SQL
Ce cours est une introduction aux interactions possibles entre la base de données et les scripts PL/SQL.
1.11.1 Affectation
On place dans une variable le résultat d’une requête en utilisant le mot-clé INTO. Les instructions
SELECT champ 1 INTO v 1 , . . . , champ n INTO v n
FROM . . .
affecte aux variables v 1, ..., v n les valeurs retournées par la requête. Par exemple
SET SERVEROUTPUT ON
DECLARE
num NUMBER;
nom VARCHAR2( 3 0 ) := ’ Poupé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 numéro ’ | | num ) ;
END;
/
Prêtez attention au fait que la requête doit retourner une et une une seule ligne, sinon, une erreur se
produit à l’exécution.
38
WHERE nomprod = nom ;
DBMS OUTPUT. PUT LINE( ’L ’ ’ a r t i c l e ’ | |
l i g n e . nomprod | | ’ a pour numéro ’ | | l i g n e . numprod ) ;
END;
/
1.11.3 Transactions
Un des mécanismes les plus puissants des SGBD récent réside dans le système des transactions. Un
transaction est un ensemble d’opérations “atomiques”, c’est-à-dire indivisible. Nous considérerons qu’un
ensemble d’opérations est indivisible si une exécution partielle de ces instructions poserait des problèmes
d’intégrité dans la base de données. Par exemple, dans le cas d’une base de données de gestion de comptes
en banque, un virement d’un compte à un autre se fait en deux temps : créditer un compte d’une somme
s, et débiter un autre de la même somme s. Si une erreur survient pendant la deuxième opération, et que
la transaction est interrompue, le virement est incomplet et le patron va vous assasiner.
La variable d’environnement AUTOCOMMIT, qui peut être positionnée à ON ou à OFF permet d’activer
la gestion des transactions. Si elle est positionnée à ON, chaque instruction a des répercussions immédiates
dans la base, sinon, les modifications ne sont effectives qu’une fois qu’un COMMIT a été exécuté.
39
1.12 Exceptions
Le mécanisme des exceptions est implémenté dans la plupart des langages récent, notament orientés
objet. Cette façon de programmer a quelques avantages immédiats :
– obliger les programmeurs à traiter les erreurs : combien de fois votre prof de C a hurlé
en vous suppliant de vérifier les valeurs retournées par un malloc, ou un fopen ? La plupart des
compilateurs des langages à exceptions (notamment java) ne compilent que si pour chaque erreur
potentielle, vous avez préparé un bloc de code (éventuellement vide...) pour la traiter. Le but est
de vous assurer que vous n’avez pas oublié d’erreur.
– Rattraper les erreurs en cours d’exécution : Si vous programmez un système de sécurité
de centrale nucléaire ou un pilote automatique pour l’aviation civile, une erreur de mémoire qui
vous afficherait l’écran bleu de windows, ou le message “Envoyer le rapport d’erreur ?”, ou plus
simplement le fameux “Segmentation fault” produirait un effet des plus mauvais. Certaines erreurs
d’éxecution sont rattrapables, autrement dit, il est possible de résoudre le problème sans interrompre
le programme.
– Ecrire le traitement des erreurs à part : Pour des raisons fiabilité, de lisibilité, il a été
considéré que mélanger le code “normal” et le traitement des erreurs était un style de programmation
perfectible... Dans les langages à exception, les erreurs sont traitées à part.
40
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) ;
END;
Les deux variables globales SQLCODE et SQLERRM contiennent respectivement le code d’erreur Oracle et
un message d’erreur correspondant à la dernière exception levée. Chaque exception a donc, en plus d’un
nom, un code et un message.
41
/∗ 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 e t r e . . . ’ ) ;
END;
C’est souvent le cas lors de violation de contraintes.
42
1.13 Sous-programmes
1.13.1 Procédures
Syntaxe
On définit une procédure 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ètres sont une simple liste de couples nom type. Par exemple, la procedure suivante affiche un
compte à rebours.
CREATE OR REPLACE PROCEDURE compteARebours ( c p t NUMBER) IS
BEGIN
IF n >= 0 THEN
DBMS OUTPUT. PUT LINE( c p t ) ;
compteARebours ( c p t − 1 ) ;
END IF ;
END;
Invocation
En PL/SQL, une procédure s’invoque tout simplement avec son nom. Mais sous SQL+, on doit utili-
ser le mot-clé CALL. Par exemple, on invoque le compte à rebours sous SQL+ avec la commande CALL
compteARebours(20).
Passage de paramètres
Oracle permet le passage de paramètres par référence. Il existe trois types de passage de paramètres :
– IN : passage par valeur
– OUT : aucune valeur passée, sert de valeur de retour
– IN OUT : passage de paramètre par référence
Par défaut, le passage de paramètre se fait de type IN.
CREATE OR REPLACE PROCEDURE i n c r ( v a l IN OUT NUMBER) IS
BEGIN
v a l := v a l + 1 ;
END;
1.13.2 Fonctions
Syntaxe
On crée une nouvelle fonction de la façon 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;
L’instruction RETURN sert à retourner une valeur. Par exemple,
43
CREATE OR REPLACE module ( a NUMBER, b NUMBER) RETURN NUMBER IS
BEGIN
IF a < b THEN
RETURN a ;
ELSE
RETURN module ( a − b , b ) ;
END IF ;
END;
Invocation
Tout comme les procédures, l’invocation des fonctions ne pose aucun problème en PL/SQL, par contre, sous
SQL+, c’est quelque peu particulier. On passe par une pseudo-table nommée DUAL de la façon suivante :
SELECT module ( 2 1 , 1 2 ) FROM DUAL;
Passage de paramètres
Les paramètres sont toujours passés avec le type IN.
44
1.14 Curseurs
1.14.1 Introduction
Les instructions de type SELECT ... INTO ... manquent de souplesse, elles ne fontionnent que sur des
requêtes retourant une et une seule valeur. Ne serait-il pas intéressant de pouvoir placer dans des variables
le résultat d’une requête retournant plusieurs lignes ? A méditer...
déclaration
Un curseur se déclare dans une section DECLARE :
CURSOR /∗ nomcurseur ∗/ IS /∗ r e q u ê t e ∗/ ;
Par exemple, si on tient à récupérer tous les employés de la table EMP, on déclare le curseur suivant.
CURSOR emp cur IS
SELECT ∗ FROM EMP;
Ouverture
Lors de l’ouverture d’un curseur, la requête du curseur est évaluée, et le curseur contient toutes les données
retournées par la requête. 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;
45
END LOOP;
/∗ . . . ∗/
END;
Fermeture
Après utilisation, il convient de fermer le curseur.
CLOSE /∗ nomcurseur ∗/ ;
Complétons notre exemple,
DECLARE
CURSOR emp cur IS
SELECT ∗ FROM EMP;
l i g n e emp cur%rowtype ;
BEGIN
OPEN emp cur ;
LOOP
FETCH emp cur INTO l i g n e ;
EXIT WHEN emp cur%NOTFOUND;
DBMS OUTPUT. PUT LINE( l i g n e . ename ) ;
END LOOP;
CLOSE emp cur ;
END;
/
Le programme ci-dessus peut aussi s’écrire
DECLARE
CURSOR emp cur IS
SELECT ∗ FROM EMP;
l i g n e emp cur%rowtype ;
BEGIN
OPEN emp cur ;
FETCH emp cur INTO l i g n e ;
WHILE emp cur%FOUND LOOP
DBMS OUTPUT. PUT LINE( l i g n e . ename ) ;
FETCH emp cur INTO l i g n e ;
END LOOP;
CLOSE emp cur ;
END;
Boucle FOR
Il existe une boucle FOR se chargeant de l’ouverture, de la lecture des lignes du curseur et de sa fermeture,
FOR l i g n e IN emp cur LOOP
/∗ Traitement ∗/
END LOOP;
Par exemple,
DECLARE
CURSOR emp cur IS
SELECT ∗ FROM EMP;
l i g n e emp cur%rowtype ;
BEGIN
FOR l i g n e IN emp cur
46
DBMS OUTPUT. PUT LINE( l i g n e . ename ) ;
END LOOP;
END;
/
47
1.15 Curseurs parametrés
1.15.1 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;
/
Réponse : non. La requête d’un curseur ne peut pas contenir de variables dont les valeurs ne sont pas
fixées. Pourquoi ? Parce que les valeurs des ces sont susceptibles de changer entre la déclaration du curseur
et son ouverture. Le remède est un curseur paramétré.
1.15.2 Définition
Un curseur paramétré est un curseur dont la requête contient des variables dont les valeurs ne seront
fixées qu’à l’ouverture.
1.15.3 Déclaration
On précise la liste des noms et des type des paramètres entre parenthèses après le nom du curseur :
CURSOR /∗ nom ∗/ ( /∗ l i s t e d e s p a r a mè t r e s ∗/ ) IS
/∗ r e q u ê t e ∗/
Par exemple, créeons une requête qui, pour une personne donnée, nous donne la liste des noms et prénoms
de ses enfants :
CURSOR e n f a n t s ( numparent NUMBER) IS
SELECT ∗
FROM PERSONNE
WHERE p e r e = numparent
OR mere = numparent ;
1.15.4 Ouverture
On ouvre un curseur paramétré en passant en paramètre les valeurs des variables :
OPEN /∗ nom ∗/ ( /∗ l i s t e d e s p a r a mè t r e s ∗/ )
Par exemple,
OPEN e n f a n t s ( 1 ) ;
48
1.15.5 Lecture d’une ligne, fermeture
la lecture d’une ligne suit les mêmes règles qu’avec un curseur non paramétré.
DECLARE
CURSOR p a r e n t IS
SELECT ∗
FROM PERSONNE;
p p a r e n t%rowtype ;
CURSOR e n f a n t s ( numparent NUMBER) IS
SELECT ∗
FROM PERSONNE
WHERE p e r e = numparent
OR mere = numparent ;
e e n f a n t%rowtype ;
BEGIN
FOR p IN p a r e n t LOOP
DBMS OUTPUT. PUT LINE( ’ Les e n f a n t s de ’ | | p . nom | |
’ ’ | | p . prenom | | ’ s o n t : ’ ) ;
FOR e IN e n f a n t s ( p . numpers ) LOOP
DBMS OUTPUT. PUT LINE( ’ ’ | | e . nompers
| | ’ ’ | | e . prenompers ) ;
END LOOP;
END LOOP;
END;
49
1.16 Triggers
1.16.1 Principe
Un trigger est une procédure stockée qui se lance automatiquement lorsqu’un événement se produit. Par
événement, on entend dans ce cours toute modification des données se trouvant dans les tables. On s’en
sert pour contrôler ou appliquer des contraintes qu’il est impossible de formuler de façon déclarative.
1.16.2 Classification
Type d’événement
Lors de la création d’un trigger, il convient de préciser quel est le type d’événement qui le déclenche.
Nous réaliserons dans ce cours des triggers pour les événements suivants :
– INSERT
– DELETE
– UPDATE
Moment de l’éxecution
On précise aussi si le trigger doit être éxecuté avant (BEFORE) ou après (AFTER) l’événement.
1.16.3 Création
Syntaxe
On déclare un trigger avec l’instruction suivante :
CREATE OR REPLACE TRIGGER n o m t r i g g e r
[BEFORE | AFTER] [INSERT | DELETE | UPDATE] ON nomtable
[FOR EACH ROW | ]
/∗ 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> CREATE OR REPLACE TRIGGER p a s D e D e l e t e D a n s C l i e n t
2 BEFORE DELETE ON CLIENT
3 BEGIN
4 RAISE APPLICATION ERROR( −20555 , ’Va t e f a i r e . . . ’ ) ;
5 END;
6 /
Dé c l e n c h e u r c r é é .
50
COUNT( ∗ )
−−−−−−−−−−
21
COUNT( ∗ )
−−−−−−−−−−
21
L’instruction RAISE APPLICATION ERROR(code, message) lève une exception sans nom portant un code
code et un message d’erreur message. Vous remarquer que comme l’erreur a été levée avant la suppression,
les données sont toujours présentes dans la table CLIENT. Le trigger a contrôlé une règle, et comme ette
n’était pas respectée, il a lancé une erreur.
Attention !
Il est impossible, dans un trigger de type FOR EACH ROW de faire un SELECT sur la table en cours de
modification.
SQL> CREATE OR REPLACE TRIGGER b e f o r e S t a t e m e n t
2 BEFORE UPDATE ON CLIENT
3 DECLARE
4 NB NUMBER;
5 BEGIN
6 SELECT COUNT( ∗ ) INTO NB
7 FROM CLIENT ;
8 END;
9 /
Dé c l e n c h e u r c r é é .
SQL>
SQL> CREATE OR REPLACE TRIGGER a f t e r S t a t e m e n t
2 AFTER UPDATE ON CLIENT
3 DECLARE
4 NB NUMBER;
5 BEGIN
6 SELECT COUNT( ∗ ) INTO NB
7 FROM CLIENT ;
8 END;
51
9 /
Dé c l e n c h e u r c r é é .
SQL>
SQL> UPDATE CLIENT SET n o m c l i = n o m c l i ;
21 l i g n e ( s ) mise ( s ) à j o u r .
SQL>
SQL> CREATE OR REPLACE TRIGGER beforeForEachRow
2 BEFORE UPDATE ON CLIENT
3 FOR EACH ROW
4 DECLARE
5 NB NUMBER;
6 BEGIN
7 SELECT COUNT( ∗ ) INTO NB
8 FROM CLIENT ;
9 END;
10 /
Dé c l e n c h e u r c r é é .
SQL>
SQL> UPDATE CLIENT SET n o m c l i = n o m c l i ;
UPDATE CLIENT SET n o m c l i = n o m c l i
∗
ERREUR à l a l i g n e 1 :
ORA−04091: l a table SCOTT. CLIENT e s t en mutation ; l e dé c l e n c h e u r ou l a
f o n c t i o n ne peut l a v o i r
ORA−06512: à ”SCOTT.BEFOREFOREACHROW” , l i g n e 4
ORA−04088: e r r e u r l o r s d e xé c u t i o n du dé c l e n c h e u r ’SCOTT.BEFOREFOREACHROW’
Dé c l e n c h e u r supprimé .
SQL>
SQL>
SQL> CREATE OR REPLACE TRIGGER afterForEachRow
2 AFTER UPDATE ON CLIENT
3 FOR EACH ROW
4 DECLARE
5 NB NUMBER;
6 BEGIN
7 SELECT COUNT( ∗ ) INTO NB
8 FROM CLIENT ;
9 END;
10 /
Dé c l e n c h e u r c r é é .
SQL>
52
SQL> UPDATE CLIENT SET n o m c l i = n o m c l i ;
UPDATE CLIENT SET n o m c l i = n o m c l i
∗
ERREUR à l a l i g n e 1 :
ORA−04091: l a table SCOTT. CLIENT e s t en mutation ; l e dé c l e n c h e u r ou l a
f o n c t i o n ne peut l a v o i r
ORA−06512: à ”SCOTT.AFTERFOREACHROW” , l i g n e 4
ORA−04088: e r r e u r l o r s d e xé c u t i o n du dé c l e n c h e u r ’SCOTT.AFTERFOREACHROW’
53
Chapitre 2
Exercices
Exercice 1
Modifiez le script de façon à ce que les saisies des valeurs suivantes soit obligatoire :
– Le prix des articles proposés
– La quantité des produits livrés
Exercice 2
Repérez les colonnes, couples de colonnes, voire triplets de colonnes, à choisir comme clés primaires.
Modifiez le script de façon à ce que cela se fasse.
54
Exercice 3
Faites de même pour les clés étrangères, sans oublier qu’il ne peut figurer dans une livraison que des
produits proposés par le fournisseur qui effectue cette livraison.
Exercice 4
Insérez quelques lignes dans chaque table.
Exercice 5
Repérez toutes les contraintes des questions précédentes dans user constraints, supprimez-les.
Exercice 6
Redéfinissez toutes ces contraintes avec la syntaxe ALTER TABLE
55
2.2 Requêtes monotabulaires
Nous souhaitons gérer un secrétatiat pédagogique, les modules sont répertoriés dans une table, et les
modules pré-requis pour s’y inscrire (avec la note minimale) se trouvent dans la table prerequis. Une
ligne de la table PREREQUIS nous indique que pour s’inscrire dans le module numéro numMod, il faut avoir
eu au moins noteMin au module numModPrereq.
Les sorties générées par les deux premières questions sont données. Après, ça sera à vous de vérifier si les
résultats de vos requêtes est cohérent ou non.
Exercice 1
Afficher la liste des noms des modules.
Oracle
C++
C
Algo
Merise
PL/SQL Oracle
mySQL
Algo avancé
8 ligne(s) sélectionnée(s).
56
Exercice 2
Afficher la liste des numéros des modules prerequis pour d’autres modules.
1
3
5
3 ligne(s) sélectionnée(s).
Exercice 3
En utilisant le résultat de la requête précédente, et l’opérateur IN, affichez les noms de ces trois modules.
Exercice 4
Augmentez les notesMin nécessaires pour s’inscrire en ’Algo avancé’ de deux points. Celles nécessaires
pour aller en ’PL/SQL Oracle’ d’un point.
Exercice 5
Affichez, par ordre de noteMin croissantes, les numéros des modules nécessaires pour accéder au module
’PL/SQL Oracle’.
Exercice 6
Affichez les numéros des modules dans lequels je ne peux pas m’inscrire avec 10 en merise.
Exercice 7
Affichez les noms de tous les modules dont le libellé contient les mots ’Algo’ ou ’SQL’.
Exercice 8
On définit pour les questions suivantes les tables
57
INSERT INTO INTERVALLE VALUES (0, 30);
INSERT INTO INTERVALLE VALUES (21, 8);
La table INTERVALLE contient des intervalles spécifiés par leurs bornes inférieure et supérieure. Supprimer
de la table intervalle tous les intervalles qui n’en sont pas avec une seule instruction.
Exercice 9
La table RECTANGLE contient des rectangles spécifiés par les coordonnées de deux sommets diamétralement
opposés, leurs arêtes sont parallèles aux axes. Certains rectangles ont des coordonnées erronnées, c’est-à
dire que soit ils sont des segments, soit les coordonnées de certains points ne sont pas dans le bon ordre.
Supprimez, avec une seule instruction, tous les rectangles-segments.
Exercice 10
Affichez tous les intervalles contenant la valeur 10.
Exercice 11
Afficher tous les intervalles qui contiennent [5, 7]. Puis tous les intervalles contenus dans [5, 35]. Puis tous
les intervalles ayant une intersection non vide avec [15, 20].
Exercice 12
Certains des rectangles sont pathologiques, dans le sens où les valeurs des coordonnées font que l’on n’a
pas un point en haut à gauche et un en bas à droite. Afficher à ces rectangles.
Exercice 13
Certains rectangles mal définis peuvent être réparés si on permute les valeurs de xHautGauche et de
xBasDroit et/ou celles de yHautGauche et de yBasDroit. Faites-le avec deux instructions UPDATE.
Exercice 14
Soit le point de coordonnées (x, y) = (2, 2), afficher les coordonnées des rectangles qui contiennent ce
point.
Exercice 15
Afficher tous les rectangles ayant une intersection non vide avec le rectangle (4, 9, 5, 10).
58
2.3 Requêtes multitabulaires
Reprenons pour ce tp la base de donées du tp sur les contraintes :
59
INSERT INTO FOURNISSEUR values (1, ’f1’);
INSERT INTO FOURNISSEUR values (2, ’f2’);
INSERT INTO FOURNISSEUR values (3, ’f3’);
INSERT INTO FOURNISSEUR values (4, ’f4’);
Exercice 1
Afficher tous les noms des produits dont le numéro a une occurence dans la table PROPOSER.
NOMPROD
------------------------------
Cotons tiges
Poupée Batman
Roue de secours
Exercice 2
Afficher tous les noms des fournisseurs dont le numéro a une occurence dans la table PROPOSER.
NOMFOU
------------------------------
f1
f2
f3
Exercice 3
Afficher les noms des fournisseurs avec pour chaque fournisseur la liste des produits proposés.
NOMFOU NOMPROD
------------------------------ ------------------------------
f1 Roue de secours
f1 Poupée Batman
f2 Poupée Batman
f3 Cotons tiges
Exercice 4
Afficher les nom des fournisseurs proposant des ’Poupées Batman’ par ordre de prix croissant.
60
Exercice 5
Afficher les dates des livraisons effectuées par le fournisseur ’f1’ ;
Exercice 6
Afficher les noms de tous les produits déjà livrés par le fournisseur ’f3’ ;
Exercice 7
Afficher toutes les lignes de la table LIVRAISON correspondant à des livraisons dans lesquelles figure le
produit ’Poupée Batman’.
Exercice 8
Pour les exercices suivants, nous travaillerons sur les données suivantes,
INSERT INTO PERSONNE VALUES (1, ’de Montmirail, dit le Hardi’, ’Godefroy’, NULL, NULL);
INSERT INTO PERSONNE VALUES (16, ’ET’, NULL, NULL, NULL);
INSERT INTO PERSONNE VALUES (2, ’Le Croquant’, ’Jacqou’, 1, 16);
INSERT INTO PERSONNE VALUES (3, ’La Fripouille’, ’Jacqouille’, 1, 16);
INSERT INTO PERSONNE VALUES (4, ’Bush’, ’Kate’, NULL, NULL);
INSERT INTO PERSONNE VALUES (13, ’Granger’, ’Hermione’, NULL, NULL);
INSERT INTO PERSONNE VALUES (5, ’Du Fémur’, ’Médor’, 3,4 );
INSERT INTO PERSONNE VALUES (12, ’Kobalevskaı̈a’, ’Sofia’, NULL, NULL);
INSERT INTO PERSONNE VALUES (6, ’Rieu’, ’André’, NULL, NULL);
INSERT INTO PERSONNE VALUES (7, ’Bontoutou’, ’Rex’, 6, 4);
INSERT INTO PERSONNE VALUES (8, ’Dijkstra’, ’Edvard’, 2, 13);
INSERT INTO PERSONNE VALUES (9, ’Leibniz’, ’Gottfrie1d Wilhem’, 8, 12);
INSERT INTO PERSONNE VALUES (10, ’Bach’, ’Johann Sebastien’, 5, 12);
INSERT INTO PERSONNE VALUES (17, ’Mathieu’, ’Mireille’, NULL, NULL);
INSERT INTO PERSONNE VALUES (11, ’Lemarchal’, ’Gregory’, 10, 17);
INSERT INTO PERSONNE VALUES (15, ’Socrate’, NULL, 3, 13);
INSERT INTO PERSONNE VALUES (19, ’Leroy’, ’Nolwen’, NULL, NULL);
INSERT INTO PERSONNE VALUES (20, ’Bartoli’, ’Jennifer’, 9, 19);
INSERT INTO PERSONNE VALUES (21, ’Fabian’, ’Lara’, 10, 17);
INSERT INTO PERSONNE VALUES (14, ’Stone’, ’Sharon’, 15, 20);
INSERT INTO PERSONNE VALUES (18, ’Frege’, ’Elodie’, 7, 13);
Le champ pere contient le numéro du père de la personne, le champ mere contient le numéro de la mère
de la personne. Dans les questions où il vous est demandé de formuler des requêtes retournant plusieurs
personne, il faut qu’il y ait une ligne par personne. Afficher les noms et prénoms des enfants de Sofia
Kobalevskaı̈a.
NOM PRENOM
------------------------------ ------------------------------
Leibniz Gottfried Wilhem
Bach Johann Sebastien
61
Exercice 9
Afficher les noms et prénoms des parents de Edvard Dijkstra.
NOM PRENOM
------------------------------ ------------------------------
Jacqou Le Croquant
Granger Hermione
Exercice 10
Afficher les noms et prénoms des enfants de jean-Sebastien Bach et Mireille Mathieu.
Exercice 11
Afficher les noms et prénoms du frère de Jacqouille la Fripouille.
Exercice 12
Afficher les noms et prénoms du cousin germain de Dijkstra du coté de son père.
Exercice 13
Afficher les noms et prenoms du demi-frère (du coté de sa mère) du père de Lara Fabian.
Exercice 14
Afficher les noms et prénoms des pères des enfants de Kate Bush.
Exercice 15
Afficher les noms et prénoms du neveu de Jacqou le Croquant.
Exercice 16
Afficher les noms et prénoms de la mère du fils du fils d’André Rieu.
Exercice 17
Afficher les noms et prénoms des parents et grand-parents de Sharon Stone.
NOM PRENOM
------------------------------ ------------------------------
Bartoli Jennifer
Granger Hermione
La Fripouille Jacqouille
Leibniz Gottfrie1d Wilhem
Leroy Nolwen
Socrate
6 ligne(s) sélectionnée(s).
N’oubliez pas : une ligne par personne.
62
2.4 Agrégation de données
Nous utiliserons pour ce tp les données suivantes :
63
INSERT INTO FOURNISSEUR values (1, ’f1’);
INSERT INTO FOURNISSEUR values (2, ’f2’);
INSERT INTO FOURNISSEUR values (3, ’f3’);
INSERT INTO FOURNISSEUR values (4, ’f4’);
Amusez-vous bien !
Exercice 1
Donner le nombre de fournisseurs.
Exercice 2
Donner le nombre de fournisseurs ayant déjà effectué une livraison.
Exercice 3
Quel est le prix du produit proposé au prix le plus élevé par ’f1’ ?
Exercice 4
Combien de produits sont proposés pour chaque fournisseur proposant au moins un produit ?
Exercice 5
Afficher le nombre de produits qui ne sont proposés par aucun fournisseur.
Exercice 6
Afficher, pour chaque produit (dont on affichera le nom), le nombre de fournisseurs l’ayant déjà livré.
Exercice 7
Donner pour chaque livraison le nom du fournisseur, le numero de livraison et le nombre de produits
livrés.
Exercice 8
Donner pour chaque livraison le nom du fournisseur, le numero de livraison, la date et le montant de la
facture.
64
Exercice 9
Donner les noms des produits qui ne sont proposés que par un seul fournisseur.
Exercice 10
Donner les noms des fournisseurs qui ont livré au moins une fois chaque produit qu’ils proposent.
65
2.5 Vues
Nous utiliserons pour ce tp les mêmes données que dans le tp précédent. N’hésitez pas, pour tester vos
requêtes, à insérer d’autres données dans la base.
Exercice 1
Créez une vue affichant pour chaque produit ayant déjà été livré le numéro du produit et la somme des
quantités livrées (toutes livraisons confondues).
Exercice 2
Affichez la quantité totale livrée du produit dont la quantité totale livrée est la plus élevée.
Exercice 3
Créez une vue affichant pour chaque livraison, le montant de la facture.
Exercice 4
Créez une vue affichant pour chaque fournisseur, le total des factures sur toutes les livraisons.
Exercice 5
Affichez le total des factures du fournisseurs dont le total des factures est le moins élevé.
Exercice 6
Affichez le nombre de produits distincts livrés par le fournisseur ayant livré le plus de produits distincts.
Par nombre de produits distincts, on entend sans tenir compte de la quantité.
66
2.6 Requêtes imbriquées
Nous utiliserons pour ce tp les données du tp précédant le tp précédent. Presque tous les stratagèmes sont
autorisés, vous pouvez utiliser des fonctions d’agrégation, des vues, et des requêtes imbriquées partout
sauf dans le FROM (ça sera l’objet du cours suivant). Bon courage, l’aspirine n’est pas fournie.
Exercice 1
Donner, pour chaque fournisseur (afficher son nom), le nombre de produits proposés, même si ce fournis-
seur n’en propose aucun. Il est interdit d’utiliser OUTER JOIN !
Exercice 2
Afficher les noms des fournisseurs qui proposent le produit numéro 2, il est interdit de faire des jointures !
Exercice 3
Afficher les noms des fournisseurs qui proposent des poupées Batman.
Exercice 4
Afficher les noms des fournisseurs qui ont déjà livré des poupées Batman.
Exercice 5
Quels sont les noms des fournisseurs qui ont déjà livré tous leurs produits au moins une fois ?
Exercice 6
Donner, pour chaque fournisseur (afficher son nom), le produit proposé au prix le plus élevé.
Exercice 7
Pour chaque produit p, quel sont les noms des fournisseurs qui, sur toutes ses livraisons, ont livré la plus
grande quantité cumulée de produits p.
Exercice 8
¡Afficher le nombre de produits proposés par les fournisseurs proposant le moins de produits. Norma-
lement, un 0 devrait s’afficher... Pas un 1.
Exercice 9
Afficher le(s) nom(s) du(des) fournisseur(s) proposant le moins de produits.
Exercice 10
Afficher, pour chaque produit, le(s) nom(s) du(des) fournisseur(s) qui l’a(ont) le plus livré (en quantité
cumulée).
67
2.7 Compléments sur les types
Nous utiliserons pour ce tp les mêmes données que dans le tp précédent.
Exercice 1
Rendez, à l’aide de contraintes de type CHECK les saisies des champs qte, prix et dateli oligatoires.
Exercice 2
Empêchez la saisie de prix négatifs ou nuls et de quantités négatives ou nulles.
Exercice 3
On sait que la base a été créée vers le mois d’Octobre 2006, empêchez l’ajout de livraisons antérieures à
ce mois.
Exercice 4
Implémentez une contrainte déclarative empêchant les livraisons les premiers mai de chaque année.
Exercice 5
Implémentez une contrainte déclarative obligeant les noms des produits à commencer par une majuscule
et à ne comporter ensuite sur des minuscules. Si l’ajout d’une des contraintes est refusée, demandez vous
pourquoi et faites le nécessaire (une commande UPDATE sera la bienvenue...) pour y remédier.
68
2.8 Révisions
Nous utiliserons pour ce tp les mêmes données que dans le tp précédent.
Exercice 1
Donner le nombre de fournisseurs ayant effectué un nombre de livraisons supérieur au égal à deux.
Exercice 2
Quelles sont les années pendant lesquelles le plus de livraisons ont été effectuées ?
Exercice 3
Parmi les fournisseurs qui ont livré au moins une fois chaque produit qu’ils proposent, quels sont les
derniers à avoir effectué une livraison.
69
2.9 Examen Type
Soit les données suivantes :
– ETUDIANT(numEtud, nom, prenom, datenaiss, civilite, patronyme, numsecu)
Répertorie les étudiants. Un numéro de sécu comporte 15 chiffres.
– MODULE(codMod, nomMod, effecMax)
Répertorie les modules
– EXAMEN(codMod, codeExam, dateExam)
CodeExam numérote les examens à l’intérieur de chaque module.
– INSCRIPTION(numEtud, codMmod, dateInsc)
Inscription d’un élève à un module.
– RESULTAT(numEtud, codMmod, CodeExam, note)
Résultat de l’étudiant numEtud à l’examen (codMod, codeExam).
– PREREQUIS(codMod, codeModPrereq, noteMin)
Pour s’inscrire au module codMod il est nécessaire d’avoir eu au moins la note noteMin au module
numéro codeModPrereq.
70
Exercice 5 - Requêtes
Vous n’hésiterez pas à ajouter des données pour tester la validité de vos requêtes. Si un étudiant a eu
plusieurs notes à un même module, sa note définitive est la plus élevée.
1. Liste des noms des étudiants.
2. Liste des noms des étudiants inscrits en maths.
3. Liste des noms des étudiants avec leur note (définitive) de maths.
4. Liste des noms des étudiants ayant validé leur examen de maths.
5. Liste des noms des étudiants n’ayant pas passé leur examen de maths.
6. Le(s) nom(s) de(s) (l’)étudiant(s) ayant eu la meilleure note en maths.
7. Le(s) nom(s) de(s) (l’)étudiant(s) dont la note la plus basse est la plus élevée.
8. Les noms des modules dans lesquels peut s’inscrire JosephF ourier.
71
2.10 Introduction au PL/SQL
Exercice 1
Ecrivez un programme affectant les valeurs 1 et 2 à deux variables a et b, puis permutant les valeurs de
ces deux variables.
Exercice 2
Ecrivez un programme plaçant la valeur 10 dans une variable a, puis affichant la factorielle de a.
Exercice 3
Ecrivez un programme plaçant les valeurs 48 et 84 dans deux variables a et b puis affichant le pgcd de a
et b.
72
2.11 Tableaux et Structures
Exercice 1
1. Créez un type tableau pouvant contenir jusqu’à 50 entiers.
2. Créez une variable de ce type , faites une allocation dynamique et dimensionnez ce tableau à 20
emplacements.
3. Placez dans ce tableau la liste des 20 premiers carrés parfaits : 1, 4, 9, 16, 25, . . .
4. Inversez l’ordre des éléments du tableau
5. Affichez le tableau.
Exercice 2
Triez le tableau précédent avec la méthode du tri à bulle.
Exercice 3
Recherchez, par dichotomie, si l’élément 225 se trouve dans le tableau.
Exercice 4
On implémente des listes chaı̂nées avec des tableaux de la sorte,
SET SERVEROUTPUT ON
DECLARE
-- Maillon d’une liste cha^ ınée
TYPE CELL IS RECORD
(
-- Donnée de chaque maillon
data INTEGER,
-- Indice du maillon précédent de la liste,
-- -1 s’il n’y en a pas
previous INTEGER,
-- Indice du maillon suivant de la liste,
-- -1 s’il n’y 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 élément de la liste
first integer;
-- indice du dernier élément 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;
73
first := 1;
last := 19;
t(first).previous := -1;
t(last).next := -1;
-- 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 l’ordre des éléments de la liste, sans changer les indices des maillons (seulement en modifiant le
chaı̂nage).
Exercice 5
Utilisez le tri à bulle pour remettre les éléments dans l’ordre. Les indications sont les mêmes : ne déplacez
pas les maillons, vous n’avez le droit de toucher qu’au chaı̂nage. Bon courage, l’aspirine n’est pas fournie.
74
2.12 Applications du PL/SQL
Nous travaillerons sur les données suivantes :
75
ALTER TABLE CLIENT ADD
(
CONSTRAINT pk_client PRIMARY KEY (numcli),
CONSTRAINT ck_telephone CHECK(LENGTH(tel)=10)
);
76
REFERENCES COMPTECLIENT (numcli, numccl),
CONSTRAINT fk_oper_codeoper
FOREIGN KEY (numtypeoper)
REFERENCES typeoperation (numtypeoper),
CONSTRAINT montant_operation
CHECK(montantoper <> 0)
);
77
nom varchar2(30) NOT NULL,
prenom varchar2(30),
pere REFERENCES PERSONNE(numpers),
mere REFERENCES PERSONNE(numpers)
);
INSERT INTO PERSONNE VALUES (1, ’de Montmirail, dit le Hardi’, ’Godefroy’, NULL, NULL);
INSERT INTO PERSONNE VALUES (16, ’Canat de Chizy’, ’Edith’, NULL, NULL);
INSERT INTO PERSONNE VALUES (2, ’Le Croquant’, ’Jacqou’, 1, 16);
INSERT INTO PERSONNE VALUES (3, ’La Fripouille’, ’Jacqouille’, 1, 16);
INSERT INTO PERSONNE VALUES (4, ’Bush’, ’Kate’, NULL, NULL);
INSERT INTO PERSONNE VALUES (13, ’Granger’, ’Hermione’, NULL, NULL);
INSERT INTO PERSONNE VALUES (5, ’Du Fémur’, ’Médor’, 3,4 );
INSERT INTO PERSONNE VALUES (12, ’Kobalevskaı̈a’, ’Sofia’, NULL, NULL);
INSERT INTO PERSONNE VALUES (6, ’Rieu’, ’André’, NULL, NULL);
INSERT INTO PERSONNE VALUES (7, ’Bontoutou’, ’Rex’, 6, 4);
INSERT INTO PERSONNE VALUES (8, ’Dijkstra’, ’Edvard’, 2, 13);
INSERT INTO PERSONNE VALUES (9, ’Leibniz’, ’Gottfrie1d Wilhem’, 8, 12);
INSERT INTO PERSONNE VALUES (10, ’Bach’, ’Johann Sebastien’, 5, 12);
INSERT INTO PERSONNE VALUES (17, ’Mathieu’, ’Mireille’, NULL, NULL);
INSERT INTO PERSONNE VALUES (11, ’Lemarchal’, ’Gregory’, 10, 17);
INSERT INTO PERSONNE VALUES (15, ’Socrate’, NULL, 3, 13);
INSERT INTO PERSONNE VALUES (19, ’Leroy’, ’Nolwen’, NULL, NULL);
INSERT INTO PERSONNE VALUES (20, ’Bartoli’, ’Jennifer’, 9, 19);
INSERT INTO PERSONNE VALUES (21, ’Fabian’, ’Lara’, 10, 17);
INSERT INTO PERSONNE VALUES (14, ’Stone’, ’Sharon’, 15, 20);
INSERT INTO PERSONNE VALUES (18, ’Frege’, ’Elodie’, 7, 13);
COMMIT;
Vous n’oublierez 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 séquence de nombres de
1 à 21. Utilisez une boucle dans laquelle vous placerez une requête pour recopier les couples nom/prénom
de la table personne dans la table CLIENT.
Exercice 2
Ecrivez un script récupérant le client de clé primaire la plus élevée, et injectant ce client dans la table
PERSONNEL.
Exercice 3
Ouvrez un compte courant pour chaque personne, effectuez un dépôt en espèce égal à 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 qu’il ne reste plus que 500 sur leur compte.
78
2.13 Exceptions
Nous utiliserons les données suivantes, même si cela annihile le travail de la séance précédente...
79
ALTER TABLE CLIENT ADD
(
CONSTRAINT pk_client PRIMARY KEY (numcli),
CONSTRAINT ck_telephone CHECK(LENGTH(tel)=10)
);
80
(SELECT nvl(MAX(numtypeccl), 0) + 1
FROM TYPECCL
),
’livret’);
INSERT INTO PERSONNE VALUES (1, ’de Montmirail, dit le Hardi’, ’Godefroy’, NULL, NULL);
INSERT INTO PERSONNE VALUES (16, ’Canat de Chizy’, ’Edith’, NULL, NULL);
INSERT INTO PERSONNE VALUES (2, ’Le Croquant’, ’Jacqou’, 1, 16);
INSERT INTO PERSONNE VALUES (3, ’La Fripouille’, ’Jacqouille’, 1, 16);
INSERT INTO PERSONNE VALUES (4, ’Bush’, ’Kate’, NULL, NULL);
INSERT INTO PERSONNE VALUES (13, ’Granger’, ’Hermione’, NULL, NULL);
INSERT INTO PERSONNE VALUES (5, ’Du Fémur’, ’Médor’, 3,4 );
INSERT INTO PERSONNE VALUES (12, ’Kobalevskaı̈a’, ’Sofia’, NULL, NULL);
INSERT INTO PERSONNE VALUES (6, ’Rieu’, ’André’, NULL, NULL);
81
INSERT INTO PERSONNE VALUES (7, ’Bontoutou’, ’Rex’, 6, 4);
INSERT INTO PERSONNE VALUES (8, ’Dijkstra’, ’Edvard’, 2, 13);
INSERT INTO PERSONNE VALUES (9, ’Leibniz’, ’Gottfrie1d Wilhem’, 8, 12);
INSERT INTO PERSONNE VALUES (10, ’Bach’, ’Johann Sebastien’, 5, 12);
INSERT INTO PERSONNE VALUES (17, ’Mathieu’, ’Mireille’, NULL, NULL);
INSERT INTO PERSONNE VALUES (11, ’Lemarchal’, ’Gregory’, 10, 17);
INSERT INTO PERSONNE VALUES (15, ’Socrate’, NULL, 3, 13);
INSERT INTO PERSONNE VALUES (19, ’Leroy’, ’Nolwen’, NULL, NULL);
INSERT INTO PERSONNE VALUES (20, ’Bartoli’, ’Jennifer’, 9, 19);
INSERT INTO PERSONNE VALUES (21, ’Fabian’, ’Lara’, 10, 17);
INSERT INTO PERSONNE VALUES (14, ’Stone’, ’Sharon’, 15, 20);
INSERT INTO PERSONNE VALUES (18, ’Frege’, ’Elodie’, 7, 13);
COMMIT;
Vous êtes invités à modifier le code de la séance précédente. Chaque fois qu’un SELECT ... INTO ...
sera effectué, vous rattraperez les exceptions NO DATA FOUND et TOO MANY ROWS. A chaque insertion, vous
ratrapperez l’exception DUP VAL ON INDEX.
Exercice 1
Faites de sorte que les scripts important les données des tables CLIENT ne puissent être exécutés qu’une
seule fois.
Exercice 2
Les scripts remplissant la table Operation ne fonctionneront pas aujourd’hui... Même s’il fonctionnaient
la dernière fois. Trouvez les codes d’erreurs des exceptions levées par ces scripts, rattrapez-les de la façon
la plus appropriée qui soit.
82
2.14 Sous-programmes
Exercice 1
Ecrire une fonction récursive retournant bn , avec n entier positif ou nul.
Exercice 2
Améliorer la fonction précédente en utilisant le fait que
n
bn = (b2 ) 2
si n est pair.
INSERT INTO PERSONNE VALUES (1, ’de Montmirail, dit le Hardi’, ’Godefroy’, NULL, NULL);
INSERT INTO PERSONNE VALUES (16, ’Canat de Chizy’, ’Edith’, NULL, NULL);
INSERT INTO PERSONNE VALUES (2, ’Le Croquant’, ’Jacqou’, 1, 16);
INSERT INTO PERSONNE VALUES (3, ’La Fripouille’, ’Jacqouille’, 1, 16);
INSERT INTO PERSONNE VALUES (4, ’Bush’, ’Kate’, NULL, NULL);
INSERT INTO PERSONNE VALUES (13, ’Granger’, ’Hermione’, NULL, NULL);
INSERT INTO PERSONNE VALUES (5, ’Du Fémur’, ’Médor’, 3,4 );
INSERT INTO PERSONNE VALUES (12, ’Kobalevskaı̈a’, ’Sofia’, NULL, NULL);
INSERT INTO PERSONNE VALUES (6, ’Rieu’, ’André’, NULL, NULL);
INSERT INTO PERSONNE VALUES (7, ’Bontoutou’, ’Rex’, 6, 4);
INSERT INTO PERSONNE VALUES (8, ’Dijkstra’, ’Edvard’, 2, 13);
INSERT INTO PERSONNE VALUES (9, ’Leibniz’, ’Gottfrie1d Wilhem’, 8, 12);
INSERT INTO PERSONNE VALUES (10, ’Bach’, ’Johann Sebastien’, 5, 12);
INSERT INTO PERSONNE VALUES (17, ’Mathieu’, ’Mireille’, NULL, NULL);
INSERT INTO PERSONNE VALUES (11, ’Lemarchal’, ’Gregory’, 10, 17);
INSERT INTO PERSONNE VALUES (15, ’Socrate’, NULL, 3, 13);
INSERT INTO PERSONNE VALUES (19, ’Leroy’, ’Nolwen’, NULL, NULL);
INSERT INTO PERSONNE VALUES (20, ’Bartoli’, ’Jennifer’, 9, 19);
INSERT INTO PERSONNE VALUES (21, ’Fabian’, ’Lara’, 10, 17);
INSERT INTO PERSONNE VALUES (14, ’Stone’, ’Sharon’, 15, 20);
INSERT INTO PERSONNE VALUES (18, ’Frege’, ’Elodie’, 7, 13);
COMMIT;
Exercice 3
Ecrire une fonction demi-freres prenant deux numéros de personnes en paramètre et retournant vrai si et
seulement si ces deux personnes ont un parent en commun.
83
Exercice 4
Ecrire une fonction cousins germains prenant deux numéros de personnes en paramètre et retournant vrai
si et seulement si ces deux deux individus sont cousins germains.
Exercice 5
Ecrire une procédure récursive affichant le nom de la personne dont le numéro est passé en paramètre et
se rappellant récursivement sur le père de cette personne. Faites de sorte à ne pas utiliser d’exceptions.
Exercice 6
Ecrire une procédure récursive affichant les noms des ascendants de sexe masculin de la personne dont le
numéro est passé en paramètre.
Exercice 7
Ecrire une fonction récursive prenant deux numéros de personne A et B et retournant vrai si A est un
ascendant de B.
Exercice 8
Ecrire une fonction prenant en paramètre deux numéros de personne A et B et retournant, si l’un est un
ascendant de l’autre, le nombre de générations les séparant, −1 si l’un n’est pas un ascendant de l’autre.
Exercice 9
Préparez un verre d’aspirine et écrivez une requête retournant le(s) couples(s) personnes séparées par le
plus de générations.
Exercice 10
Reprendre le code du tp précédent, le découper en sous-programmes de la façon la moins inintelligente
possible. Bon courage.
84
2.15 Curseurs
Exercice 1
Refaites le td application du PL/SQL en utilisant les curseurs.
Exercice 2
En utlisant la table PERSONNE du tp précédent, ecrivez une fonction affichant toute la descendance d’une
personne.
85
2.16 Curseurs parametrés
L’intérêt de ce tp étant de vous familiariser avec les curseurs paramétrés, vous ferez en sorte de ne pas
contourner leur usage.
Exercice 1
Ecrire une procédure qui affiche tous les clients, et pour chaque client, la liste des comptes.
Exercice 2
Ecrire une procédure qui affiche tous les clients, et pour chaque client, la liste des comptes, et pour chacun
de ces comptes, l’historique des opérations.
86
2.17 Triggers
Étant donnée la base suivante :
87
ALTER TABLE PREREQUIS ADD
CONSTRAINT pk_prerequis
PRIMARY KEY (codMod, codModPrereq);
ALTER TABLE INSCRIPTION ADD
CONSTRAINT pk_inscription
PRIMARY KEY (codMod, numEtud);
ALTER TABLE RESULTAT ADD
CONSTRAINT pk_resultat
PRIMARY KEY (codMod, numEtud, codExam);
88
to_char(datenaiss, ’yy’) = substr(numsecu, 2, 2)
)
);
Implémentez les contraintes suivantes. Vous ferez des sous-programme tenant sur une page, et ne contenant
pas plus de trois niveaux d’imbrication. Vous répertorierez les numéros d’erreurs que vous affecterez à
chaque levée d’exception.
1. Il ne doit pas être possible de modifier la note min dans la table prerequis.
2. Dans un module, il ne doit pas y avoir plus de effecMax élèves inscrits.
3. On ne peut créer un examen pour un module que s’il y a des élèves inscrits dans ce module.
4. Un élève ne peut passer un examen que si sa date d’inscription est antérieure à la date de l’examen.
5. Il ne doit pas y avoir de circuit dans la table prerequis (il existe une façon de la vérifier en PL/SQL,
mais comme vous ne la connaissez pas, faites un parcours en profondeur du graphe des pré-requis)
6. Un élève s’inscrivant à un module doit avoir eu au moins la note min à tous les modules pré-requis.
7. Ajouter dans étudiant un champ moyenne, celui-ci contiendra la moyenne de chaque étudiant s’il a
passé les examens de tous les modules dans lesquels il est inscrit.
8. Revenez sur la première contrainte : il ne doit être possible de modifier une note min dans la table
prerequis que s’il n’existe pas d’élève dont une inscription serait invalidée.
9. Il ne doit être possible de modifier effecMax que si des étudiants ne se retrouvent pas avec une
inscription invalidée.
Libre à vous par la suite de trouver d’autres contraintes et de les implémenter.
89
Chapitre 3
Corrigés
−− q u e s t i o n 4
90
INSERT INTO LIVRAISON ( numfou , numli ) values ( 1 , 1);
INSERT INTO LIVRAISON ( numfou , numli ) values ( 1 , 2);
INSERT INTO LIVRAISON ( numfou , numli ) values ( 3 , 1);
−− q u e s t i o n 5
−− Le s c r i p t c i −d e s s o u s va vous a f f i c h e r l a s o l u t i o n .
−− Vous pouvez p r o cé d e r de deux f a ç o n s :
−− ∗ c o p i e r −c o l l e r c e t t e s o l u t i o n a f f i c h é e
−− par c e t t e s é r i e de commandes
s e t und o f f
set heading o f f
set f e e d o f f
s e l e c t ’ a l t e r t a b l e ’ | | t a b l e n a m e | | ’ drop c o n s t r a i n t ’ ||
c o n s t r a i n t n a m e | | ’ ; ’ from u s e r c o n s t r a i n t s
where t a b l e n a m e in
( ’PRODUIT ’ , ’FOURNISSEUR ’ , ’PROPOSER ’ ,
’LIVRAISON ’ , ’DETAILLIVRAISON ’ )
AND c o n s t r a i n t t y p e IN ( ’R ’ , ’P ’ )
ORDER BY c o n s t r a i n t t y p e DESC ;
s e t und on
s e t h e a d i n g on
s e t f e e d on
−− ∗ p l a c e r c e c i dans l e f i c h i e r dp . s q l
−− e t l ’ e x é c u t e r en s a i s i s s a n t @<cheminabsolu >/dp . s q l
set trimout o f f ;
Set f e e d o f f ;
set echo o f f ;
set heading o f f ;
s e t termou t o f f ;
set v e r i f y o f f ;
s e t space 0 ;
SET NEWPAGE 0 ;
SET PAGESIZE 0 ;
spool drop constraints . l s t
s e l e c t ’ a l t e r t a b l e ’ | | t a b l e n a m e | | ’ drop c o n s t r a i n t ’ ||
c o n s t r a i n t n a m e | | ’ ; ’ from u s e r c o n s t r a i n t s
where t a b l e n a m e in
( ’PRODUIT ’ , ’FOURNISSEUR ’ ,
’PROPOSER ’ , ’LIVRAISON ’ , ’DETAILLIVRAISON ’ )
AND c o n s t r a i n t t y p e IN ( ’R ’ , ’P ’ )
ORDER BY c o n s t r a i n t t y p e DESC ;
spool o f f
@drop constraints . l s t
s e t t r i m o u t on ;
Set f e e d on ;
s e t e c h o on ;
s e t h e a d i n g on ;
s e t termou t on ;
s e t v e r i f y on ;
−− q u e s t i o n 6
a l t e r t a b l e p r o d u i t add
constraint p k p r o d u i t
PRIMARY KEY ( numprod ) ;
a l t e r t a b l e f o u r n i s s e u r add
constraint p k f o u r n i s s e u r
PRIMARY KEY ( numfou ) ;
a l t e r t a b l e p r o p o s e r add
constraint p k p r o p o s e r
PRIMARY KEY ( numfou , numprod ) ;
a l t e r t a b l e l i v r a i s o n add
constraint p k l i v r a i s o n
PRIMARY KEY ( numfou , numli ) ;
a l t e r t a b l e d e t a i l l i v r a i s o n add
constraint p k d e t a i l l i v r a i s o n
PRIMARY KEY ( numfou , numli , numprod ) ;
a l t e r t a b l e p r o p o s e r add
constraint f k p r o p o s e r f o u r n i s s e u r
FOREIGN KEY ( numfou )
91
REFERENCES f o u r n i s s e u r ( numfou ) ;
a l t e r t a b l e 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
FOREIGN KEY ( numprod )
REFERENCES p r o d u i t ( numprod ) ;
a l t e r t a b l e 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
FOREIGN KEY ( numfou )
REFERENCES f o u r n i s s e u r ( numfou ) ;
a l t e r t a b l e 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
FOREIGN KEY ( numfou , numli )
REFERENCES l i v r a i s o n ( numfou , numli ) ;
a l t e r t a b l e 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
FOREIGN KEY ( numfou , numprod )
REFERENCES p r o p o s e r ( numfou , numprod ) ;
92
3.2 Requêtes monotabulaires
−− E x e r c i c e 1
SELECT nomMod
FROM MODULE;
−− E x e r c i c e 2
−− E x e r c i c e 3
SELECT nomMod
FROM MODULE
WHERE numMod IN ( 1 , 3 , 5 ) ;
−− E x e r c i c e 4
NUMMOD NOMMOD
−−−−−−−−−− −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
8 Algo a v a n cé e
1 ligne s é l e c t i o n n é e .
NUMMOD NOMMOD
−−−−−−−−−− −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
6 PL/SQL O r a c l e
1 l i g n e s é l e c t i o n n é e .
SQL> UPDATE p r e r e q u i s SET noteMin = 11 WHERE numMod = 6 ;
−− E x e r c i c e 5
−− E x e r c i c e 6
SELECT numMod
FROM p r e r e q u i s
WHERE numModPrereq = 5
AND noteMin > 1 0 ;
−− E x e r c i c e 7
SELECT nomMod
FROM module
WHERE nomMod LIKE ’%Algo% ’
OR nomMod LIKE ’%SQL% ’ ;
−− E x e r c i c e 8
DELETE FROM i n t e r v a l l e
WHERE borneSup < b o r n e I n f ;
−− E x e r c i c e 9
DELETE FROM r e c t a n g l e
WHERE xHautGauche = x B a s D r o i t
OR yHautGauche = y B a s D r o i t ;
−− E x e r c i c e 10
SELECT ∗
FROM i n t e r v a l l e
WHERE 10 BETWEEN b o r n e I n f AND borneSup ;
−− E x e r c i c e 11
SELECT ∗
FROM i n t e r v a l l e
93
WHERE b o r n e I n f <= 5 AND borneSup >= 7 ;
SELECT ∗
FROM i n t e r v a l l e
WHERE b o r n e I n f >= 5 AND borneSup <= 3 5 ;
SELECT ∗
FROM i n t e r v a l l e
WHERE ( 1 5 BETWEEN b o r n e I n f AND borneSup )
OR ( 2 0 BETWEEN b o r n e I n f AND borneSup )
OR ( b o r n e I n f BETWEEN 15 AND 2 0 ) ;
−− E x e r c i c e 12
SELECT ∗
FROM r e c t a n g l e
WHERE ( xHautGauche > x B a s D r o i t )
OR ( yHautGauche < y B a s D r o i t ) ;
−− E x e r c i c e 13
UPDATE r e c t a n g l e SET
xHautGauche = xBasDroit ,
x B a s D r o i t = xHautGauche
WHERE xHautGauche > x B a s D r o i t ;
UPDATE r e c t a n g l e SET
yHautGauche = yBasDroit ,
y B a s D r o i t = yHautGauche
WHERE yHautGauche < y B a s D r o i t ;
−− E x e r c i c e 14
SELECT ∗
FROM r e c t a n g l e
WHERE ( 2 BETWEEN xHautGauche AND x B a s D r o i t )
AND ( 2 BETWEEN y B a s D r o i t AND yHautGauche ) ;
94
3.3 Requêtes multitabulaires
−− E x e r c i c e 1
SELECT d i s t i n c t nomprod
FROM p r o d u i t , p r o p o s e r
WHERE p r o d u i t . numprod = p r o p o s e r . numprod ;
−− E x e r c i c e 2
SELECT d i s t i n c t nomfou
FROM f o u r n i s s e u r f , p r o p o s e r p
WHERE f . numfou = p . numfou ;
−− E x e r c i c e 3
−− E x e r c i c e 4
SELECT nomfou , p r i x
FROM f o u r n i s s e u r f , p r o d u i t p , p r o p o s e r pr
WHERE f . numfou = pr . numfou
AND pr . numprod = p . numprod
AND nomProd = ’ Poupée Batman ’
ORDER BY p r i x ;
−− E x e r c i c e 5
SELECT d a t e l i
FROM l i v r a i s o n l , f o u r n i s s e u r f
WHERE l . numfou = f . numfou
AND f . nomFou = ’ f 1 ’ ;
−− E x e r c i c e 6
SELECT nomprod
FROM f o u r n i s s e u r f , p r o d u i t p , detaillivraison d
WHERE nomfou = ’ f 3 ’
AND f . numfou = d . numfou
AND d . numprod = p . numprod ;
−− E x e r c i c e 7
−− E x e r c i c e 8
−− E x e r c i c e 9
−− E x e r c i c e 10
−− E x e r c i c e 11
95
WHERE f . p e r e = j . p e r e
AND f . mere = j . mere
AND j . nom = ’ La F r i p o u i l l e ’
AND j . nom <> f . nom ;
−− E x e r c i c e 12
−− E x e r c i c e 13
−− E x e r c i c e 14
−− E x e r c i c e 15
−− E x e r c i c e 16
−− E x e r c i c e 17
96
3.4 Agrégation de données
−− E x e r c i c e 1
SELECT COUNT( ∗ )
FROM FOURNISSEUR ;
−− E x e r c i c e 2
−− E x e r c i c e 3
−− E x e r c i c e 4
−− E x e r c i c e 5
−− E x e r c i c e 6
−− E x e r c i c e 7
−− E x e r c i c e 8
−− E x e r c i c e 9
SELECT nomprod
FROM PRODUIT P , PROPOSER PR
WHERE P . numprod = PR . numprod
GROUP BY nomprod
HAVING COUNT(D. numfou ) = 1 ;
−− E x e r c i c e 10
SELECT nomfou
FROM FOURNISSEUR F , PROPOSER P , DETAILLIVRAISON L
WHERE F . numfou = P . numfou
AND L . numfou = F . numfou
GROUP BY nomfou
HAVING COUNT(DISTINCT P . numprod ) = COUNT(DISTINCT L . numprod ) ;
97
3.5 Vues
−− E x e r c i c e 1
−− E x e r c i c e 2
−− E x e r c i c e 3
−− E x e r c i c e 4
−− E x e r c i c e 5
−− E x e r c i c e 6
98
3.6 Requêtes imbriquées
−− E x e r c i c e 1
SELECT nomfou ,
(SELECT COUNT( numprod )
FROM PROPOSER P
WHERE P . numfou = F . numfou
) AS NB PROD PROPOSES
FROM FOURNISSEUR F ;
−− E x e r c i c e 2
SELECT nomfou
FROM FOURNISSEUR
WHERE numfou IN
(SELECT numfou
FROM PROPOSER
WHERE numprod = 2 ) ;
−− E x e r c i c e 3
SELECT nomfou
FROM FOURNISSEUR
WHERE numfou IN
(SELECT numfou
FROM PROPOSER
WHERE numprod =
(SELECT numprod
FROM PRODUIT
WHERE nomprod = ’ Poupée Batman ’
)
);
−− E x e r c i c e 4
SELECT nomfou
FROM FOURNISSEUR
WHERE numfou IN
(SELECT numfou
FROM DETAILLIVRAISON
WHERE numprod IN
(SELECT numprod
FROM PRODUIT
WHERE nomprod = ’ Poupée Batman ’
)
);
−− E x e r c i c e 5
SELECT nomfou
FROM FOURNISSEUR F
WHERE
(SELECT COUNT( ∗ )
FROM PROPOSER PR
WHERE F . numfou = PR . numfou
) > 0
AND
(SELECT COUNT(DISTINCT numprod )
FROM DETAILLIVRAISON D
WHERE F . numfou = D. numfou
)
=
(SELECT COUNT( ∗ )
FROM PROPOSER PR
WHERE F . numfou = PR . numfou
);
−− E x e r c i c e 6
SELECT nomfou ,
(SELECT nomprod
FROM PRODUIT P
WHERE P . numprod IN
(SELECT numprod
FROM PROPOSER PR1
WHERE PR1 . numfou = F . numfou
AND p r i x =
(SELECT MAX( p r i x )
FROM PROPOSER PR2
WHERE PR2 . numfou = F . numfou
99
)
)
)
FROM FOURNISSEUR F ;
−− E x e r c i c e 7
−− E x e r c i c e 8
−− E x e r c i c e 9
SELECT nomfou
FROM FOURNISSEUR
WHERE numfou IN
(sELECT numfou
FROM
(SELECT numfou ,
(SELECT COUNT( ∗ )
FROM PROPOSER PR
WHERE F . numfou = PR . numfou
) AS NB PROD
FROM FOURNISSEUR F
)
WHERE NB PROD =
(SELECT MIN(NB PROD)
FROM
(SELECT numfou ,
(SELECT COUNT( ∗ )
FROM PROPOSER PR
WHERE F . numfou = PR . numfou
) AS NB PROD
FROM FOURNISSEUR F
)
)
);
−− E x e r c i c e 10
100
(SELECT numprod , SUM(QTE) AS NB LIV
FROM DETAILLIVRAiSON D
GROUP BY numprod , numfou
) Q
WHERE Q. numprod = P1 . numprod
)
) M
WHERE P . numprod = M. numprod
AND F . numfou = M. numfou ;
101
3.7 Compléments sur les types
−− E x e r c i c e 1
−− E x e r c i c e 2
−− E x e r c i c e 3
−− E x e r c i c e 4
−− E x e r c i c e 5
102
3.8 Révisions
−− E x e r c i c e 1
SELECT nomfou
FROM FOURNISSEUR F
WHERE
(
SELECT COUNT( ∗ )
FROM LIVRAISON L
WHERE L . numfou = F . numfou
)
>= 2 ;
−− E x e r c i c e 2
SELECT ANNEE
FROM LIVRAISONS PAR ANNEE
WHERE NB LIVRAISONS =
(
SELECT MAX( NB LIVRAISONS )
FROM LIVRAISONS PAR ANNEE
);
−− E x e r c i c e 3
SELECT nomfou
FROM FOURNISSEUR
WHERE numfou IN
(
SELECT F . numfou
FROM FOU KI ONT TOU LIVRE F , DERNIERE LI PAR FOU D
WHERE F . numfou = D. numfou
AND DATE MAX =
(
SELECT MAX(DATE MAX)
FROM FOU KI ONT TOU LIVRE F , DERNIERE LI PAR FOU D
WHERE F . numfou = D. numfou
)
);
103
3.9 Examen Type
DROP TABLE RESULTAT;
DROP TABLE EXAMEN;
DROP TABLE PREREQUIS ;
DROP TABLE INSCRIPTION ;
DROP TABLE MODULE;
DROP TABLE ETUDIANT;
−− E x e r c i c e 1 e t 3
−− E x e r c i c e 2
104
ALTER TABLE EXAMEN ADD
CONSTRAINT f k e x a m e n
FOREIGN KEY ( codMod )
REFERENCES MODULE( codMod ) ;
ALTER TABLE RESULTAT ADD
(CONSTRAINT f k r e s u l t a t e x a m e n
FOREIGN KEY ( codMod , codExam )
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 ( codMod , numEtud )
REFERENCES INSCRIPTION ( codMod , numEtud ) ) ;
−− E x e r c i c e 3
−− I l i m p o s s i b l e de l i m i t e r de f a ç o n d é c l a r a t i v e l e nombre d ’ é t u d i a n t s
−− i n s c r i t s à un module .
−− E x e r c i c e 4
105
UPDATE RESULTAT SET n o t e = 20
wHERE
numEtud = (SELECT numEtud FROM ETUDIANT WHERE nom = ’ F o u r i e r ’ )
AND codMod = (SELECT codMod FROM MODULE WHERE nomMod = ’ Maths ’ )
AND codExam = 1 ;
−− E x e r c i c e 5
−− r e q u ê t e 1
SELECT nom
FROM ETUDIANT;
−− r e q u ê t e 2
SELECT nom
FROM ETUDIANT
WHERE numEtud IN
(
SELECT numEtud
FROM INSCRIPTION
WHERE codMod IN
(
SELECT codMod
FROM MODULE
WHERE nomMod = ’ Maths ’
)
);
−− r e q u ê t e 3
−− r e q u ê t e 4
−− r e q u ê t e 5
106
) = 0 ;
−− r e q u ê t e 6
−− r e q u ê t e 7
−− r e q u ê t e 8
SELECT nomMod
FROM MODULE M
WHERE
(
SELECT COUNT( ∗ )
107
FROM PREREQUIS P
WHERE M. codMod = P . codMod
AND noteMin >
(
SELECT NOTE DEF
FROM NOTE PAR ETU MOD N
WHERE N . codMod = P . codModPrereq
AND N . numEtud =
(
SELECT numEtud
FROM ETUDIANT
WHERE nom = ’ F o u r i e r ’
)
)
) = 0
AND M. codMod NOT IN
(
SELECT codMod
FROM INSCRIPTION
WHERE numEtud IN
(
SELECT numEtud
FROM ETUDIANT
WHERE nom = ’ F o u r i e r ’
)
);
108
3.10 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. PUT LINE ( ’ a = ’ | | a ) ;
DBMS OUTPUT. PUT LINE ( ’ b = ’ | | b ) ;
DBMS OUTPUT. PUT LINE ( ’ Let ’ ’ s swap a and b . . . The r e s u l t is : ’ );
t := a ;
a := b ;
b := t ;
DBMS OUTPUT. PUT LINE ( ’ a = ’ | | a ) ;
DBMS OUTPUT. 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 c o u n t e r > 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 LOOP;
DBMS OUTPUT. PUT LINE ( a | | ’ != ’ | | r e s ) ;
END;
/
−− E x e r c i c e 3
DECLARE
a NUMBER := 4 8 ;
b NUMBER := 8 4 ;
amodb NUMBER;
BEGIN
DBMS OUTPUT.PUT( ’PGCD( ’ | | a | | ’ , ’ | | b | | ’ ) = ’ ) ;
WHILE b > 0 LOOP
amodb := a ;
WHILE amodb >= b LOOP
amodb := amodb − b ;
END LOOP;
a := b ;
b := amodb ;
END LOOP;
DBMS OUTPUT. PUT LINE ( a ) ;
END;
/
109
3.11 Tableaux et Structures
SET SERVEROUTPUT ON
−− Tableaux
DECLARE
TYPE montab I S VARRAY ( 5 0 ) OF INTEGER;
t montab ;
BEGIN
t := montab ( ) ;
t . extend ( 2 0 ) ;
−− I n i t i a l i s a t i o n
FOR i IN 1 . . 2 0 LOOP
t ( i ) := i ∗ i ;
END LOOP;
−− I n v e r s i o n de l ’ o r d r e d e s é lé m e n t s
DECLARE
temp i n t e g e r ;
BEGIN
FOR i IN 1 . . 1 0 LOOP
temp := t ( i ) ;
t ( i ) := t (20− i + 1 ) ;
t (20− i +1) := temp ;
END LOOP;
END;
−− A f f i c h a g e
FOR i IN 1 . . 2 0 LOOP
DBMS OUTPUT. PUT LINE ( ’ t ( ’ | |
i || ’) = ’ || t( i ));
END LOOP;
−− Tri à b u l l e
DECLARE
temp i n t e g e r ;
BEGIN
FOR i IN REVERSE 2 . . 2 0 LOOP
FOR j IN 2 . . i LOOP
IF t ( j − 1 ) > t ( j ) THEN
temp := t ( j ) ;
t ( j ) := t ( j − 1 ) ;
t ( j −1) := temp ;
END IF ;
END LOOP;
END LOOP;
END;
−− A f f i c h a g e
FOR i IN 1 . . 2 0 LOOP
DBMS OUTPUT. PUT LINE ( ’ t ( ’ | |
i || ’) = ’ || t( i ));
END LOOP;
110
DBMS OUTPUT. PUT LINE (X | |
’ n” e s t p as dans l e t a b l e a u ’ ) ;
END IF ;
END;
END;
/
−− 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 aı̂ né e
TYPE CELL I S RECORD
(
−− Donnée 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é cé 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 I S 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 é lé m e n t de l a l i s t e
f i r s t integer ;
−− i n d i c e du d e r n i e r é lé m e n t de l a l i s t e
l a s t integer ;
BEGIN
t := TREE ( ) ;
t . extend ( 1 9 ) ;
−− I n i t i a l i s a t i o n
FOR i IN 1 . . 1 9 LOOP
t ( i ) . d a t a := power ( i , 5 ) mod 19 ;
t ( i ) . p r e v i o u s := i −1;
t ( i ) . next := i +1;
END LOOP;
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
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;
−− I n v e r s i o n de l ’ o r d r e d e s é lé m e n t s
DECLARE
temp INTEGER;
BEGIN
FOR i IN 1 . . 1 9 LOOP
temp := 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 := temp ;
END LOOP;
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
WHILE p <> −1 LOOP
DBMS OUTPUT. PUT LINE ( ’ ( ’ | |
p || ’ , ’ ||
t ( p ) . data | | ’ , ’ | |
t (p ) . previous | | ’ , ’ ||
t ( p ) . next | | ’ ) ’ ) ;
111
p := t ( p ) . next ;
END LOOP;
END;
−− Tri à b u l l e
DECLARE
i i n t e g e r := l a s t ;
j integer ;
BEGIN
WHILE t ( t ( i ) . p r e v i o u s ) . p r e v i o u s <> −1 LOOP
j := f i r s t ;
WHILE i <>j LOOP
−− 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 aı̂ n 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 ;
IF 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 IF ;
IF 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 IF ;
IF a f t e r J = i THEN
i := j ;
END IF ;
END;
ELSE
j := t ( j ) . next ;
END IF ;
END LOOP;
i := t ( i ) . p r e v i o u s ;
END LOOP;
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
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;
END;
/
112
3.12 Application du PL/SQL et Exceptions
SET SERVEROUTPUT ON
SET AUTOCOMMIT OFF
−− E x e r c i c e 1
DECLARE
u n C l i e n t PERSONNE%ROWTYPE;
numClient PERSONNE. numpers%t y p e ;
Y A EU UNE MERDE EXCEPTION;
BEGIN
FOR numClient IN 1 . . 2 1 LOOP
BEGIN
SELECT ∗ INTO u n C l i e n t
FROM PERSONNE
WHERE numpers = numClient ;
−− E x e r c i c e 2
DECLARE
u n C l i e n t CLIENT%rowtype ;
BEGIN
SELECT ∗ INTO u n C l i e n t
FROM CLIENT WHERE numCli =
(
SELECT MAX( n u m c l i )
FROM CLIENT
);
INSERT INTO PERSONNEL VALUES
(
1,
unClient . nomcli ,
unClient . prenomcli ,
NULL,
1254.28
);
COMMIT;
EXCEPTION
WHEN NO DATA FOUND THEN
DBMS OUTPUT. PUT LINE ( ’ Aucun c l i e n t ’ ) ;
WHEN DUP VAL ON INDEX THEN
DBMS OUTPUT. PUT LINE (
’ I l y a un g r o s p r o b lè m e . . . J ” comprends pas c ” q u i s ” p a s s e ’ ) ;
END;
/
−− E x e r c i c e 3
113
DECLARE
numClient CLIENT . n u m c l i%TYPE;
tCCL TYPECCL. n u m t y p e c c l%TYPE;
n t o TYPEOPERATION. numtypeoper%TYPE;
Y A UN GRO BLEME EXCEPTION;
BEGIN
SELECT numtypeoper INTO n t o
FROM TYPEOPERATION
WHERE nomtypeoper = ’ dé p ô t e s p è c e s ’ ;
SELECT n u m t y p e c c l INTO tCCL
FROM TYPECCL
WHERE nomtypeCCL = ’ Compte c o u r a n t ’ ;
FOR numClient IN 1 . . 2 1 LOOP
BEGIN
INSERT INTO COMPTECLIENT VALUES
(
numClient ,
1,
tCCL ,
SYSDATE,
1
);
INSERT INTO OPERATION VALUES
(
numClient ,
1,
1,
nto ,
SYSDATE,
numClient ∗ 1 0 0 ,
’ i n a u g u r a t i o n du compte ’
);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
−− Adaptez l e numéro du code ,
−− c h e z moi ça donne −2290
IF SQLCODE = −2290 THEN
DECLARE
t o t a l OPERATION. montantoper%TYPE := numClient ∗ 1 0 0 ;
t o I n s e r t OPERATION. montantoper%TYPE;
c p t NUMBER := 1 ;
BEGIN
WHILE t o t a l > 0 LOOP
IF 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 IF ;
INSERT INTO OPERATION VALUES
(
numClient ,
1,
(SELECT n v l (MAX( numoper ) , 0 ) + 1
FROM OPERATION
WHERE n u m c l i = numClient
AND numccl = 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 LOOP;
EXCEPTION
WHEN OTHERS THEN
DBMS OUTPUT. PUT LINE ( ’MOD( t o t a l , 1 0 0 0 ) = ’ | | MOD( t o t a l , 1000));
DBMS OUTPUT. PUT LINE ( ’SQLCODE = ’ | | SQLCODE ) ;
DBMS OUTPUT. PUT LINE ( ’SQLERRM = ’ | | SQLERRM) ;
RAISE Y A UN GRO BLEME ;
END;
ELSE
DBMS OUTPUT. PUT LINE ( ’SQLCODE = ’ | | SQLCODE ) ;
DBMS OUTPUT. PUT LINE ( ’SQLERRM = ’ | | SQLERRM) ;
ROLLBACK;
END IF ;
END;
END LOOP;
EXCEPTION
114
WHEN NO DATA FOUND THEN
DBMS OUTPUT. PUT LINE ( ’ Pas de d o n né e s ! ’ ) ;
WHEN TOO MANY ROWS THEN
DBMS OUTPUT. PUT LINE ( ’ Trop de d o n né e s ! ’ ) ;
WHEN Y A UN GRO BLEME THEN
DBMS OUTPUT. PUT LINE ( ’ I l y a un g r o s p r o b lè m e ! ’ ) ;
DBMS OUTPUT. PUT LINE ( ’SQLCODE = ’ | | SQLCODE ) ;
DBMS OUTPUT. PUT LINE ( ’SQLERRM = ’ | | SQLERRM) ;
WHEN OTHERS THEN
DBMS OUTPUT. PUT LINE ( ’SQLCODE = ’ | | SQLCODE ) ;
DBMS OUTPUT. PUT LINE ( ’SQLERRM = ’ | | SQLERRM) ;
END;
/
−− E x e r c i c e 4
DECLARE
numClient CLIENT . n u m c l i%TYPE := 2 ;
numCompteLivret TYPECCL. numtypeCCL%TYPE;
n t o TYPEOPERATION. numtypeoper%TYPE;
montant OPERATION. montantoper%TYPE;
Y A UN GRO BLEME EXCEPTION;
BEGIN
SELECT numtypeoper INTO n t o
FROM TYPEOPERATION
WHERE nomtypeoper = ’ v i r e m e n t ’ ;
SELECT n u m t y p e c c l INTO numCompteLivret
FROM TYPECCL
WHERE nomtypeCcl = ’ l i v r e t ’ ;
WHILE numClient <= 21 LOOP
BEGIN
montant := 100 ∗ numClient − 5 0 0 ;
INSERT INTO COMPTECLIENT VALUES
(
numClient ,
2,
numCompteLivret ,
SYSDATE,
1
);
INSERT INTO OPERATION VALUES
(
numClient ,
1,
(SELECT n v l (MAX( numoper ) , 0 ) + 1
FROM OPERATION
WHERE n u m c l i = numClient
AND numccl = 1 ) ,
nto ,
SYSDATE,
−montant ,
’ versement l i v r e t ’
);
INSERT INTO OPERATION VALUES
(
numClient ,
2,
(SELECT n v l (MAX( numoper ) , 0 ) + 1
FROM OPERATION
WHERE n u m c l i = numClient
AND numccl = 2 ) ,
nto ,
SYSDATE,
montant ,
’ versement l i v r e t ’
);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
−− idem
IF SQLCODE = −2290 THEN
DECLARE
t o t a l OPERATION. montantoper%TYPE := montant ;
toMove OPERATION. montantoper%TYPE;
c p t NUMBER := 1 ;
BEGIN
WHILE t o t a l > 1000 LOOP
IF t o t a l > 1000 THEN
toMove := 1 0 0 0 ;
ELSE
tomove := t o t a l ;
115
END IF ;
INSERT INTO OPERATION VALUES
(
numClient ,
1,
(SELECT n v l (MAX( numoper ) , 0 ) + 1
FROM OPERATION
WHERE n u m c l i = numClient
AND numccl = 1 ) ,
nto ,
SYSDATE,
−toMove ,
’ versement l i v r e t ’ | | cpt
);
INSERT INTO OPERATION VALUES
(
numClient ,
2,
(SELECT n v l (MAX( numoper ) , 0 ) + 1
FROM OPERATION
WHERE n u m c l i = numClient
AND numccl = 2 ) ,
nto ,
SYSDATE,
toMove ,
’ versement l i v r e t ’ | | cpt
);
t o t a l := t o t a l − toMove ;
c p t := c p t + 1 ;
END LOOP;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
RAISE Y A UN GRO BLEME ;
END;
ELSE
DBMS OUTPUT. PUT LINE ( ’SQLCODE = ’ | | SQLCODE ) ;
DBMS OUTPUT. PUT LINE ( ’SQLERRM = ’ | | SQLERRM) ;
ROLLBACK;
END IF ;
END;
COMMIT;
numClient := numClient + 2 ;
END LOOP;
EXCEPTION
WHEN NO DATA FOUND THEN
DBMS OUTPUT. PUT LINE ( ’ Pas de d o n né e s ! ’ ) ;
WHEN TOO MANY ROWS THEN
DBMS OUTPUT. PUT LINE ( ’ Trop de d o n né e s ! ’ ) ;
WHEN Y A UN GRO BLEME THEN
DBMS OUTPUT. PUT LINE ( ’ I l y a un g r o s p r o b lè m e ! ’ ) ;
DBMS OUTPUT. PUT LINE ( ’SQLCODE = ’ | | SQLCODE ) ;
DBMS OUTPUT. PUT LINE ( ’SQLERRM = ’ | | SQLERRM) ;
WHEN OTHERS THEN
DBMS OUTPUT. PUT LINE ( ’SQLCODE = ’ | | SQLCODE ) ;
DBMS OUTPUT. PUT LINE ( ’SQLERRM = ’ | | SQLERRM) ;
END;
/
116
3.13 Sous-programmes
−− E x e r c i c e 1
−− E x e r c i c e 2
−− E x e r c i c e 3
−− E x e r c i c e 4
−− E x e r c i c e 5
117
CREATE OR REPLACE PROCEDURE
a i e u l (P PERSONNE. numpers%t y p e ) I S
row PERSONNE%rowtype ;
nb NUMBER;
BEGIN
SELECT count ( ∗ ) INTO NB
FROM PERSONNE
WHERE numpers = P ;
IF (NB = 1 ) THEN
SELECT ∗ INTO row
FROM PERSONNE
WHERE numpers = P ;
DBMS OUTPUT. PUT LINE ( row . nom ) ;
a i e u l ( row . p e r e ) ;
END IF ;
END;
/
−− E x e r c i c e 6
−− E x e r c i c e 7
END;
/
BEGIN
IF ( a s c e n d a n t ( 1 , 8 ) ) THEN
DBMS OUTPUT. PUT LINE ( ’OK ’ ) ;
ELSE
DBMS OUTPUT. PUT LINE ( ’ pas OK ’ ) ;
END IF ;
END;
/
−− E x e r c i c e 8
118
END IF ;
END;
/
−− E x e r c i c e 9
−− E x e r c i c e 10
119
3.14 Curseurs
CREATE OR REPLACE PROCEDURE copyFromPersonneToClient I S
CURSOR C I S
SELECT ∗
FROM PERSONNE;
ROW C%rowtype ;
BEGIN
FOR ROW IN C LOOP
INSERT INTO CLIENT
( numcli , n o m c l i , p r e n o m c l i )
VALUES
(ROW. numpers , ROW. nom , ROW. prenom ) ;
END LOOP;
COMMIT;
EXCEPTION
WHEN DUP VAL ON INDEX THEN
DBMS OUTPUT. PUT LINE ( ’ Copy can be done o n l y o n c e . ’ ) ;
END;
/
CALL copyFromPersonneToClient ( ) ;
CALL t a k e C l i e n t T o P e r s o n n e l ( ) ;
120
CREATE OR REPLACE PROCEDURE
c r e a t e V i r e m e n t ( n u m c l i e n t CLIENT . n u m c l i%type , value NUMBER) I S
BEGIN
INSERT INTO OPERATION VALUES
( numclient ,
1,
(SELECT n v l (MAX( numoper ) , 0 ) + 1
FROM OPERATION
WHERE n u m c l i = n u m c l i e n t
AND numccl = 1
),
(SELECT numtypeoper
FROM TYPEOPERATION
WHERE nomtypeoper = ’ v i r e m e n t ’
),
sysdate ,
−value ,
’ cadeau ! ’
);
INSERT INTO OPERATION VALUES
( numclient ,
2,
(SELECT n v l (MAX( numoper ) , 0 ) + 1
FROM OPERATION
WHERE n u m c l i = n u m c l i e n t
AND numccl = 1
),
(SELECT numtypeoper
FROM TYPEOPERATION
WHERE nomtypeoper = ’ v i r e m e n t ’
),
sysdate ,
value ,
’ cadeau ! ’
);
EXCEPTION
WHEN OTHERS THEN
IF (SQLCODE = −22900) THEN
DBMS OUTPUT. PUT LINE ( ’ Too much money a t o n c e . ’ ) ;
END IF ;
END;
/
121
);
INSERT INTO COMPTECLIENT VALUES
( numclient ,
2,
(SELECT n u m t y p e c c l
FROM TYPECCL
WHERE n o m t y p e c c l = ’ v i r e m e n t ’
),
sysdate ,
(SELECT numpers
FROM PERSONNEL
WHERE numpers =
(
SELECT MAX( n u m c l i )
FROM CLIENT
)
)
);
creditAccount ( numclient , numclient ∗ 1 0 0 ) ;
moveToLivret ( n u m c l i e n t , n u m c l i e n t ∗ 100 − 5 0 0 ) ;
EXCEPTION
WHEN DUP VAL ON INDEX THEN
DBMS OUTPUT. PUT LINE ( ’ T h i s a c c o u n t h as a l r e a d y been opened . ’ ) ;
END;
/
CALL openAccounts ( ) ;
122
3.15 Curseurs paramétrés
−− E x e r c i c e 1
call afficheComptesClients ( ) ;
−− E x e r c i c e 2
call afficheOperComptesClients ( ) ;
123
3.16 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
124
FOREIGN KEY ( codModPrereq )
REFERENCES MODULE( codMod ) ) ;
ALTER TABLE EXAMEN ADD
CONSTRAINT f k e x a m e n
FOREIGN KEY ( codMod )
REFERENCES MODULE( codMod ) ;
ALTER TABLE RESULTAT ADD
(CONSTRAINT f k r e s u l t a t e x a m e n
FOREIGN KEY ( codMod , codExam )
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 ( codMod , numEtud )
REFERENCES INSCRIPTION ( codMod , numEtud ) ) ;
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−− C o n t r a i n t e 1 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−− C o n t r a i n t e 2 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
125
/
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 codmod
FROM MODULE
WHERE e f f e c < e f f e c M a x ;
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−− 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 codMod
FROM MODULE M
WHERE
(
SELECT COUNT( ∗ )
126
FROM INSCRIPTION I
WHERE I . codmod = M. codmod
) > 0 ;
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−− 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 . numetud , E . codmod , E . codexam
FROM INSCRIPTION I , EXAMEN E
WHERE I . codmod = E . codmod
AND I . d a t e I n s c < E . dateExam ;
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−− C o n t r a i n t e 5 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
127
SELECT codmod
FROM MIRRORPREREQ
WHERE codmodprereq = r o o t ;
SON C%rowtype ;
BEGIN
FOR SON IN C LOOP
IF
( son . codmod = moduleToFind OR
f i n d M o d u l e ( son . codmod , moduleToFind ) )
THEN
RETURN TRUE;
END IF ;
END LOOP;
RETURN FALSE;
END;
/
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
128
CREATE OR REPLACE 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
BEFORE INSERT OR UPDATE ON PREREQUIS
FOR EACH ROW
BEGIN
IF INSERTING THEN
i n s e r t M i r r o r P r e r e q ( : new . codmod , : new . codmodprereq , : new . noteMin ) ;
END IF ;
IF UPDATING THEN
u p d a t e M i r r o r P r e r e q ( : o l d . codmod , : new . codmod ,
: o l d . codmodprereq , : new . codmodprereq , : new . noteMin ) ;
END IF ;
IF ( f i n d M o d u l e ( : new . codmod , : new . codmod ) ) THEN
IF INSERTING THEN
d e l e t e M i r r o r P r e r e q ( : new . codmod , : new . codmodprereq ) ;
END IF ;
IF UPDATING THEN
u p d a t e M i r r o r P r e r e q ( : new . codmod , : o l d . codmod ,
: new . codmodprereq , : o l d . codmodprereq , : o l d . noteMin ) ;
END IF ;
RAISE APPLICATION ERROR( −20003 , ’ C i r c u i t dans p r e r e q u i s . ’ ) ;
END IF ;
END;
/
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−− C o n t r a i n t e 6 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−− C o n t r a i n t e 7 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
129
−− l e 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
−− l e s n o t e s o b e t n u e s par l e s e l e v e s .
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
130
END;
/
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−− C o n t r a i n t e 9 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
131
FOR EACH ROW
BEGIN
IF ( : new . e f f e c m a x < : new . e f f e c ) THEN
RAISE APPLICATION ERROR( −20005 ,
’ L e f f e c t i f ne p e u t ê t r e en d e s s o u s de ’ || : new . e f f e c ) ;
END IF ;
END;
/
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−− C o n t r a i n t e 8 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−− Quelques i n s e r t i o n s pour t e s t e r −−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
132
(
(SELECT codMod FROM MODULE WHERE nomMod = ’ Maths ’ ) ,
1,
t o d a t e ( ’ 0 2 0 1 2 0 0 8 ’ , ’ ddmmyyyy ’ )
);
133