Beruflich Dokumente
Kultur Dokumente
Alexandre Meslé
13 octobre 2009
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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1.4 SQL+ et iSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.3 Introduction aux requêtes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3.1 Compléments sur SELECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3.2 Instruction WHERE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3.3 Conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3.4 Suppression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.3.5 Mise à jour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4 Jointures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4.2 Produit cartésien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.4.3 Jointure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.7.3 Sous requêtes non correlées renvoyant une table . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.7.4 Sous requêtes correlées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
1.8 Compléments sur les types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.8.1 Types numériques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.8.2 Types chaine de caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.8.3 Types date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.8.4 La fonction inclassable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.8.5 Contraintes CHECK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.9 Introduction au PL/SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.9.1 PL/SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.9.2 Blocs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.9.3 Affichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.9.4 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1
1.9.5 Traitements conditionnels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.9.6 Traitements répétitifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
1.10 Tableaux et structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
1.10.1 Tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
1.10.2 Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
1.11 Utilisation du PL/SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
1.11.1 Affectation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
1.11.2 Tables et structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
1.11.3 Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
1.12 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
1.12.1 Rattraper une exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
1.12.2 Exceptions prédéfinies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
1.12.3 Codes d’erreur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
1.12.4 Déclarer et lancer ses propres exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
1.13 Sous-programmes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
1.13.1 Procédures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
1.13.2 Fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
1.14 Curseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.14.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.14.2 Les curseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.15 Curseurs parametrés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.15.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.15.2 Définition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.15.3 Déclaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.15.4 Ouverture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.15.5 Lecture d’une ligne, fermeture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.15.6 Boucle pour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
1.15.7 Exemple récapitulatif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
1.16 Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
1.16.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
1.16.2 Classification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
1.16.3 Création . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
1.16.4 Accès aux lignes en cours de modification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
1.16.5 Contourner le problème des tables en mutation . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
1.17 Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
1.17.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
1.17.2 Spécification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
1.17.3 Corps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
2 Exercices 55
2.1 Contraintes déclaratives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
2.2 Introduction aux requêtes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
2.3 Jointures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
2.4 Agrégation de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
2.5 Vues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
2.6 Requêtes imbriquées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
2.7 Compléments sur les types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
2.8 Révisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
2.9 Introduction au PL/SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
2.10 Tableaux et Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
2.11 Utilisation PL/SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
2.12 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
2.13 Sous-programmes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
2.14 Curseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
2.15 Curseurs parametrés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
2.16 Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
2.17 Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
2.18 Révisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
2
3 Corrigés 76
3.1 Contraintes déclaratives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
3.2 Introduction aux requêtes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
3.3 Jointures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
3.4 Agrégation de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
3.5 Vues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
3.6 Requêtes imbriquées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
3.7 Compléments sur les types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
3.8 Révisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
3.9 Examen Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
3.10 Introduction au PL/SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
3.11 Tableaux et Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
3.12 Application du PL/SQL et Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
3.13 Sous-programmes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
3.14 Curseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
3.15 Curseurs paramétrés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
3.16 Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
3.17 Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
3.18 Révisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
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.
Par exemple :
4
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
– DDL : Data definition language
– DML : Data manipulation language
– DQL : Data query language
– DCL : Data control language
A cela s’ajoute le PL/SQL. Celui-ci permet de gérer presque toutes les contraintes et de maintenir la cohérence de
la base de données. Mais c’est beaucoup plus compliqué...
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 :
6
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
descriptioncontrainte d’une clé primaire :
PRIMARY KEY(< c o l o n n e 1 >, . . . , <c o l o n n e n >)
descriptioncontrainte d’une clé étrangère :
FOREIGN KEY(< c o l o n n e 1 >, . . . , <c o l o n n e n >)
REFERENCES <t a b l e r e f e r e n c e e > (< c o l o n n e 1 >, . . . , <c o l o n n e n >)
Il est aussi possible de placer une descriptioncontrainte dans le CREATE TABLE. Par exemple,
create table c l i e n t
(
numcli number,
nom varchar2 ( 2 5 6 ) ,
prenom varchar2 ( 2 5 6 ) ,
numdept number,
PRIMARY KEY (number) ,
FOREIGN KEY ( numdept ) REFERENCES DEPT ( nd )
)
On remarque qu’il est possible de nommer une contrainte. C’est utile si on souhaite la supprimer :
ALTER TABLE <nomtable> DROP CONSTRAINT <nomcontrainte >
Pour lister les contraintes :
SELECT ∗ FROM USER CONSTRAINTS
9
1.3 Introduction aux requêtes
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
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)
10
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 ’ )
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 !
11
1.3.5 Mise à jour
L’expression
UPDATE <NOMTABLE> SET
<c o l o n n e 1 > = <v a l e u r 1 >,
<c o l o n n e 2 > = <v a l e u r 2 >,
... ,
<c o l o n n e n > = <v a l e u r n >
WHERE <CONDITION>
modifie les lignes de la table NOMTABLE vérifiant condition. Elle affecte au champ colonnei la valeur valeuri . Par
exemple,
UPDATE CLIENT SET NAME = ’ Medor ’ WHERE LUNCH = ’ Bones ’
affecte la valeur ’Médor’ aux champs noms de toutes les lignes dont la valeur LUNCH est égale à ’Bones’. Il est possible,
dans une modification, d’utiliser les valeurs des autres champs de la ligne, voire même l’ancienne valeur de ce champ.
Par exemple,
UPDATE CLIENT SET SALARY = SALARY + 5000
augmente tous les salaires de 5000 (choisissez l’unité !).
12
1.4 Jointures
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
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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 :
13
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.
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 ;
14
3 3 2 3 Cotons t i g e s
Nous avons mis en correspondance des lignes de la table proposer avec des lignes de la table produit en utilisant le
fait que numprod est une clé étrangère dans proposer. Comme la colonne numprod apparait deux fois dans la requête,
il est nécessaire de la préfixer par le nom de la table de sorte que chaque colonne puisse être désignée de façon non
ambiguë. Si on veut mettre face à face les noms des produits et les noms des fournisseurs, il suffit de saisir la requête
SQL> SELECT nomfou , nomprod
2 FROM p r o d u i t , f o u r n i s s e u r , p r o p o s e r
3 WHERE p r o d u i t . numProd = p r o p o s e r . numProd
4 AND f o u r n i s s e u r . numFou = p r o p o s e r . numFou ;
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
−−−−−−−−−− −−−−−−−−−−
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 ;
15
BORNEINF BORNESUP BORNEINF BORNESUP
−−−−−−−−−− −−−−−−−−−− −−−−−−−−−− −−−−−−−−−−
0 30 12 30
2 3 2 56
2 3 12 3
2 56 2 3
12 3 2 3
12 3 12 30
12 30 0 30
12 30 12 3
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 moche
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 belle
SQL> SELECT count ( ∗ ) FROM PRODUIT;
COUNT( ∗ )
−−−−−−−−−−
4
1 ligne selectionnee .
La réponse est le résultat de la requête.
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
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
17
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 .
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 :
18
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 comptabilisé
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 ).
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
19
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 confon-
dues),
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 fournisseurs 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
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− −−−−−−−−−−−−−−−
Cor n i c h o n s 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
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− −−−−−−−−−−−−−−−
Cor n i c h o n s 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 ).
21
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
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− −−−−−−−−−−−−−−−
Cor n i c h o n s 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 fournis-
seurs.
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
Cor n i c h o n s 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 :
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
23
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
f1
La requête SELECT MAX(NB PROD) FROM NB PROD PAR FOU est évaluée avant, et son résultat lui est substitué 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 .
MAX(NB PROD)
−−−−−−−−−−−−
2
Maintenant, recherchons les numéros des fournisseurs proposant un tel nombre de produits :
24
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
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
25
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 proposant 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
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
f1
Vous constatez que la solution utilisant les vues est nettement plus simple.
NUMFOU NB PROD L
−−−−−−−−−− −−−−−−−−−−
1 45
2
3 10
4
26
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
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 ?
27
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
−−−−−−−−−−
10 ,2
10
,01
21 ,01
28
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 :
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 ;
29
−−−−−−−−−− −−−−−−−−−− −−−−−−−−
1 1 30/10/34
3 1 30/10/34
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
Table m o d i f i e e .
30
1.9 Introduction au 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 obliga-
toirement 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 OUTPUT.PUT() et DBMS OUTPUT.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 ;
31
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;
32
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;
33
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.
34
p point ;
permet de déclarer une variable p de type point.
35
1.11 Utilisation 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 , . . . , champ n INTO v 1 , . . . , v n
FROM . . .
affecte aux variables v 1, ..., v n les valeurs retournées par la requête. Par exemple
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.
36
1.11.3 Transactions
Un des mécanismes les plus puissants des SGBD récents réside dans le système des transactions. Une 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 assassiner.
Il convient donc de disposer d’un mécanisme permettant de se protéger de ce genre de désagrément. Plutôt que
se casser la tête à tester les erreurs à chaque étape et à balancer des instructions permettant de “revenir en arrière”,
nous allons utiliser les instructions COMMIT et ROLLBACK.
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é.
37
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.
38
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.
39
BEGIN
RAISE GLUBARF;
EXCEPTION
WHEN GLUBARF THEN
DBMS OUTPUT. PUT LINE( ’ g l u b a r f r a i s e d . ’ ) ;
END;
/
40
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 ( n NUMBER) IS
BEGIN
IF n >= 0 THEN
DBMS OUTPUT. PUT LINE( n ) ;
compteARebours ( n − 1 ) ;
END IF ;
END;
Invocation
En PL/SQL, une procédure s’invoque tout simplement avec son nom. Mais sous SQL+, on doit utiliser 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,
CREATE OR REPLACE FUNCTION module ( a NUMBER, b NUMBER) RETURN NUMBER IS
BEGIN
IF a < b THEN
RETURN a ;
ELSE
RETURN module ( a − b , b ) ;
41
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.
42
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;
43
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 LOOP
DBMS OUTPUT. PUT LINE( l i g n e . ename ) ;
END LOOP;
END;
/
44
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 ) ;
45
1.15.6 Boucle pour
La boucle pour se charge de l’ouverture, il convient donc de placer les paramètre dans l’entête de la boucle,
FOR /∗ v a r i a b l e ∗/ IN /∗ nom ∗/ ( /∗ l i s t e p a r a mè t r e s ∗/ ) LOOP
/∗ i n s t r u c t i o n s ∗/
END LOOP;
Par exemple,
FOR e IN e n f a n t s ( 1 ) LOOP
DBMS OUTPUT. PUT LINE( e . nompers | | ’ ’ | | e . prenompers ) ;
END LOOP;
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 s%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 . prenom | |
’ ’ | | p . nom | | ’ s o n t : ’ ) ;
FOR e IN e n f a n t s ( p . numpers ) LOOP
DBMS OUTPUT. PUT LINE( ’ ∗ ’ | | e . prenom
| | ’ ’ | | e . nom );
END LOOP;
END LOOP;
END;
/
46
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 | ]
DECLARE
/∗ d e c l a r a t i o n s ∗/
BEGIN
/∗ i n s t r u c t i o n s ∗/
END;
Par exemple,
SQL> 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 é é .
COUNT( ∗ )
−−−−−−−−−−
21
47
DELETE FROM CLIENT
∗
ERREUR à l a l i g n e 1 :
ORA−20555: Va t e f a i r e . . .
ORA−06512: à ”SCOTT.PASDEDELETEDANSCLIENT” , l i g n e 2
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.PASDEDELETEDANSCLIENT ’
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 remarquez 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 elle n’était pas respectée, il a lancé
une erreur.
Combinaisons d’événements
Il est possible, en séparant les types d’événement par le mot-clé OR, de définir un trigger déclenché par plusieurs
événements. Les variables booléennes INSERTING, UPDATING et DELETING permettent d’identifier l’événement qui a
déclenché le trigger.
CREATE OR REPLACE TRIGGER a f f i c h e E v e n e m e n t
BEFORE INSERT OR UPDATE OR DELETE ON CLIENT
FOR EACH ROW
BEGIN
IF INSERTING THEN
DBMS OUTPUT. PUT LINE( ’ I n s e r t i o n dans CLIENT ’ ) ;
ELSIF UPDATING THEN
DBMS OUTPUT. PUT LINE( ’ Mise a j o u r dans CLIENT ’ ) ;
ELSE
DBMS OUTPUT. PUT LINE( ’ S u p p r e s s i o n dans CLIENT ’ ) ;
END IF ;
END;
Tables en mutation
Il est impossible, dans un trigger de type FOR EACH ROW de faire un SELECT sur la table en cours de modification.
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
48
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;
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>
49
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>
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’
Colonnes supplémentaires
Par exemple, si l’on souhaite empêcher un client d’avoir plus de 10 comptes en banque, une solution est de placer
dans la table client une colonne contenant le nombre de comptes.
ALTER TABLE CLIENT ADD nbComptes number ;
UPDATE CLIENT SET nbComptes = 0 ;
Une fois cette table crée, il convient de s’assurer que les données de la colonne nbComptes contient toujours les
bonnes valeurs. On le fait avec plusieurs sous-programmes :
CREATE OR REPLACE TRIGGER metAJourNbComptes
AFTER INSERT OR UPDATE OR DELETE ON COMPTECLIENT
BEGIN
UPDATE CLIENT SET nbComptes =
(
SELECT COUNT( ∗ )
FROM COMPTECLIENT CC
WHERE CC. numCli = numCli
);
END;
/
50
BEGIN
SELECT nbComptes INTO nbComptes
FROM CLIENT
WHERE numCli = : new . numcli ;
IF ( nbComptes >= 1 0 ) THEN
RAISE APPLICATION ERROR( −20556 ,
’ Ce c l i e n t a d e j a t r o p de comptes ’ ) ;
END IF ;
END;
/
On peut affiner en remplaçant metAJourNbComptes par plusieurs sous-programmes :
CREATE OR REPLACE TRIGGER i n i t i a l i s e N b C o m p t e s
BEFORE INSERT ON CLIENT
FOR EACH ROW
BEGIN
: new . nbComptes := 0 ;
END;
/
Tables supplémentaires
Si l’on souhaite par exemple empêcher les circuits dans la table PERSONNE, il est nécessaire de faire un parcours
de graphe. Ce qui nécessite des SELECT dans la table en cours de mutation. La seule solution est dans ce cas d’avoir
une table miroir qui contient les colonnes clés primaire et étrangères de cette table, et de s’en servir pour détecter les
circuits.
CREATE TABLE MIRRORPERSONNE
(
numpers NUMBER PRIMARY KEY,
p e r e NUMBER,
mere NUMBER
);
Nous allons ensuite procéder de même, en répercutant chaque opération de PERSONNE sur MIRRORPERSONNE.
CREATE OR REPLACE TRIGGER miseAJourMirrorPersonne
BEFORE UPDATE OR INSERT OR DELETE ON PERSONNE
FOR EACH ROW
BEGIN
IF DELETING OR UPDATING THEN
DELETE FROM MIRRORPERSONNE
WHERE numpers = : o l d . numpers ;
END IF ;
IF INSERTING OR UPDATING THEN
INSERT INTO MIRRORPERSONNE VALUES
51
( : new . numpers , : new . pere , : new . mere ) ;
END IF ;
END;
/
Une fois cela fait, il suffit de rechercher si une personne insérée est une descendante d’elle même dans MIRRORPERSONNE.
CREATE OR REPLACE FUNCTION t r o u v e C i r c u i t ( c u r r e n t NUMBER, toFind NUMBER)
RETURN BOOLEAN IS
numPere NUMBER;
numMere NUMBER;
BEGIN
IF ( c u r r e n t IS NULL) THEN
RETURN FALSE;
END IF ;
SELECT pere , mere INTO numPere , numMere
FROM MIRRORPERSONNE
WHERE numPers = c u r r e n t ;
RETURN ( numPere = toFind OR numMere = toFind OR
t r o u v e C i r c u i t ( numPere , toFind ) OR
t r o u v e C i r c u i t ( numMere , toFind ) ) ;
END;
/
52
1.17 Packages
1.17.1 Principe
Un package est un ensemble de sous-programmes et de variables formé par
– Une spécification : déclaration de variables et de sous-programmes
– Un corps : implémentation des sous-programmes
Tout ce qui se trouve dans la spécification doit se trouver dans le corps, mais la réciproque est fausse. Un package
satisfait les points suivants :
– encapsulation : certains traitements sont masqués, seule la spécification du package est visible. Cela a pour
avantage de simplifier la tâche de celui qui va utiliser le package.
– modularité : il est possible de développer séparément les diverses parties de l’application. le développement
devient ainsi un assemblage de package.
Ces deux aspects fournissent une souplesse certaine au niveau du développement : il est possible de modifier le
corps d’un package sans changer sa spécification, donc sans modifier le fonctionnement de l’application.
1.17.2 Spécification
La syntaxe permettant de créer l’entête est la suivante :
CREATE OR REPLACE PACKAGE nompackage IS
/∗
declarations
∗/
END nomPackage ;
/
Par exemple,
CREATE OR REPLACE PACKAGE compteur IS
procedure r e s e t ;
f u n c t i o n nextValue r e t u r n number ;
END compteur ;
/
1.17.3 Corps
La syntaxe permettant de créer le corps est la suivante :
CREATE OR REPLACE PACKAGE BODY nompackage IS
/∗
implementation
∗/
END nomPackage ;
/
Par exemple,
CREATE OR REPLACE PACKAGE BODY compteur IS
c p t NUMBER := 0 ;
PROCEDURE r e s e t IS
BEGIN
c p t := 0 ;
END;
53
On peut utiliser un package depuis n’importe quel script PL/SQL :
DECLARE
nb NUMBER;
BEGIN
FOR nb IN 4 . . 2 0 LOOP
DBMS OUTPUT. PUT LINE(COMPTEUR. nextValue ( ) ) ;
END LOOP;
COMPTEUR.RESET ( ) ;
FOR nb IN REVERSE 0 . . 1 0 LOOP
DBMS OUTPUT. PUT LINE(COMPTEUR. nextValue ( ) ) ;
END LOOP;
END;
/
54
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.
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 Introduction aux requêtes
Nous souhaitons gérer un secrétatiat pédagogique avec la base de A.2.
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).
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 utilisera pour les questions suivantes les tables de A.3.
56
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).
57
2.3 Jointures
Reprenons pour ce tp la base de donées de A.4.
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.
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 de A.5. Dans les questions où il vous est demandé de
formuler des requêtes retournant plusieurs personnes, 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
58
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.
59
2.4 Agrégation de données
Nous utiliserons les données de A.4. Il est demandé dans chaque exercice de formuler une requête.
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.
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.
60
2.5 Vues
Nous utiliserons les données de A.4. N’hésitez pas, pour tester vos requêtes et à 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é.
61
2.6 Requêtes imbriquées
Nous utiliserons les données de A.4. Presque tous les stratagèmes sont autorisés, vous pouvez utiliser des fonctions
d’agrégation, des vues, et des requêtes imbriquées. 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 fournisseur 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. Normalement, 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).
62
2.7 Compléments sur les types
Vous modifierez pour faire ces exercices le script de création de tables de A.4.
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.
63
2.8 Révisions
Nous utiliserons les données de A.4.
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.
64
2.9 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.
65
2.10 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;
first := 1;
last := 19;
t(first).previous := -1;
t(last).next := -1;
66
-- 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.
67
2.11 Utilisation PL/SQL
Nous travaillerons sur les données A.6 et A.5.
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.
68
2.12 Exceptions
Nous utiliserons les données de A.7 et A.5
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.
69
2.13 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.
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.
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.
70
2.14 Curseurs
Exercice 1
Refaites les exercices de 2.11 en utilisant les curseurs.
Exercice 2
En utlisant les donnees A.5, ecrivez une fonction affichant toute la descendance d’une personne.
71
2.15 Curseurs parametrés
L’intérêt de ces exercices étant de vous familiariser avec les curseurs paramétrés, vous ferez en sorte de ne pas
contourner leur usage. Nous utiliserons les données de A.6
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.
72
2.16 Triggers
Implémentez les contraintes suivantes dans les données de les données de A.8. Vous ferez des sous-programmes
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.
73
2.17 Packages
Exercice 1
Lancez deux sessions simultanément sur le même serveur et invoquez les sous-programmes du package compteur
depuis chacune des sessions. Que remarquez-vous ?
Exercice 2
Implémenter le corps du package suivant (utilisez les données de A.5).
CREATE OR REPLACE PACKAGE g e s t i o n a r b r e I S
c i r c u i t exception ;
p r o c e d u r e a j o u t e P e r s o n n e (nom p e r s o n n e . nom%type ,
prenom p e r s o n n e . prenom%type , p e r e p e r s o n n e . p e r e%type ,
mere p e r s o n n e . mere%t y p e ) ;
p r o c e d u r e m o d i f i e P a r e n t s ( p e r s p e r s o n n e . numpers%type ,
numPere p e r s o n n e . p e r e%type , numMere p e r s o n n e . mere%t y p e ) ;
END g e s t i o n a r b r e ;
/
74
2.18 Révisions
Implémentez les contraintes suivantes dans les données de A.9.
1. Les parents d’une même personne sont des personnes différentes.
2. L’arbre généalogique ne contient pas de circuit.
3. Les dates de divorce sont ultérieures aux dates de mariage.
4. Une même personne ne peut pas être mariée à plusieurs personnes simultanément.
5. Personne ne peut être père d’une personne et mère d’une autre.
6. Un mari ne peut pas être mère et une femme ne peut pas être père.
7. Deux personnes ayant du sang en commun ne peuvent se marier.
75
Chapitre 3
Corrigés
−− q u e s t i o n 4
76
INSERT INTO DETAILLIVRAISON values ( 1 , 1 , 2 , 2 0 ) ;
INSERT INTO DETAILLIVRAISON values ( 1 , 2 , 1 , 1 5 ) ;
INSERT INTO DETAILLIVRAISON values ( 1 , 2 , 2 , 1 7 ) ;
−− 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 termout 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 termout 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 )
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 ) ;
77
3.2 Introduction aux requêtes
−− 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
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 ∗
78
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 ) ;
79
3.3 Jointures
−− 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, livraison l
WHERE nomfou = ’ f 3 ’
AND f . numfou = l . numfou
AND l . numfou = d . numfou
AND l . numli = d . numli
AND d . numprod = p . numprod
AND d a t e l i < s y s d a t e ;
−− 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
80
−− 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
81
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 ) ;
82
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
83
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
)
)
)
FROM FOURNISSEUR F ;
−− E x e r c i c e 7
84
CREATE VIEW NB PROD LIVRES PAR FOU AS
SELECT numfou , numprod , SUM( q t e ) AS QTE
FROM DETAILLIVRAISON
GROUP BY numfou , numprod ;
−− 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
85
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
86
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
)
);
87
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
88
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
−− 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
89
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
−− r e q u ê t e 6
90
SELECT numEtud
FROM NOTE MATHS PAR ETU
WHERE NOTE MATHS
=
(
SELECT MAX(NOTE MATHS)
FROM NOTE MATHS PAR ETU
)
);
−− r e q u ê t e 7
−− r e q u ê t e 8
SELECT nomMod
FROM MODULE M
WHERE
(
SELECT COUNT( ∗ )
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 ’
)
);
91
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;
/
92
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;
93
−− 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 | | ’ ) ’ ) ;
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
94
−− 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;
/
95
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
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
96
FROM TYPEOPERATION
WHERE nomtypeoper = ’ dé p ô t e s p è c e s ’ ;
SELECT n um 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
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
97
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 um 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 ;
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 ,
98
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;
/
99
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
100
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
101
NB := −1;
ELSE
NB := e c a r t A s c e n d a n t (A, row . p e r e ) ;
END IF ;
IF ( row . mere I S NULL) THEN
NB := fmax ( −1 , NB ) ;
ELSE
NB := fmax ( e c a r t A s c e n d a n t (A, row . p e r e ) , NB ) ;
END IF ;
IF (NB <> −1) THEN
NB := NB + 1 ;
END IF ;
RETURN NB;
END;
/
−− E x e r c i c e 9
−− E x e r c i c e 10
102
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 ( ) ;
103
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;
/
104
)
)
);
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 ( ) ;
105
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 ( ) ;
106
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
107
(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 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
108
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
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( ∗ )
FROM INSCRIPTION I
WHERE I . codmod = M. codmod
) > 0 ;
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
109
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−− 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 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
110
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−− C o n t r a i n t e 6 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
111
FOR p IN p r e r e q LOOP
SELECT count ( ∗ ) INTO n b L i g n e s
FROM RESULTAT
WHERE codmod = p . codmodprereq
AND numetud = e t u d
AND n o t e < p . noteMin ;
IF ( n b L i g n e s = 0 ) THEN
RETURN FALSE;
END IF ;
END LOOP;
RETURN TRUE;
END;
/
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−− C o n t r a i n t e 7 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
112
(SELECT COUNT( ∗ ) AS nbNotes
FROM MEILLEURENOTE M
WHERE M. numetud = E . numetud
) AS nbNotes
FROM ETUDIANT E ;
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−− C o n t r a i n t e 9 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
113
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
−− 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 −−−−−−−−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
114
INSERT INTO MODULE
( codMod , nomMod)
VALUES
(
(SELECT n v l (MAX( codMod ) , 0 ) + 1 FROM MODULE) ,
’ Maths ’
);
115
3.17 Packages
CREATE OR REPLACE PACKAGE BODY g e s t i o n a r b r e I S
cursor f e u i l l e s r e t u r n p e r s o n n e%rowtype I S
SELECT ∗ FROM PERSONNE;
p r o c e d u r e m o d i f i e P a r e n t s ( p e r s p e r s o n n e . numpers%type ,
numPere p e r s o n n e . p e r e%type , numMere p e r s o n n e . mere%t y p e ) I S
BEGIN
IF ( descendDe ( p e r s , numPere ) OR descendDe ( p e r s , numMere ) ) THEN
RAISE CIRCUIT ;
END IF ;
UPDATE PERSONNE SET p e r e = numPere , mere = numMere
WHERE numPers = p e r s ;
END;
END;
/
CALL g e s t i o n A r b r e . m o d i f i e P a r e n t s ( 2 0 , 1 4 , 1 5 ) ;
116
3.18 Révisions
−− P r e p a r a t i f s . . .
−− C o n t r a i n t e 1
−− C o n t r a i n t e 2
117
p e r s MIRRORPERSONNE%rowtype ;
BEGIN
SELECT ∗ INTO p e r s
FROM MIRRORPERSONNE
WHERE numpers = d e s c e n d a n t ;
RETURN descendDe ( numpers , p e r s . p e r e )
OR descendDe ( numpers , p e r s . mere ) ;
END;
END IF ;
END;
PROCEDURE v e r i f i e C i r c u i t ( p e r s p e r s o n n e . numpers%t y p e ) I S
l i g n e m i r r o r p e r s o n n e%rowtype ;
BEGIN
SELECT ∗ INTO LIGNE
FROM m i r r o r p e r s o n n e
WHERE numpers = p e r s ;
IF ( descendDe ( p e r s , l i g n e . p e r e ) OR descendDe ( p e r s , l i g n e . mere ) ) THEN
RAISE CIRCUIT ;
END IF ;
END;
END;
/
−− C o n t r a i n t e 3
−− C o n t r a i n t e 4
END c o n t r a i n t e s M a r i a g e s ;
/
−− C o n t r a i n t e s 5 e t 6
CREATE OR REPLACE p a c k a g e c o n t r a i n t e s T r a n s I S
t r a n s EXCEPTION;
PROCEDURE v e r i f i e P e r e M e r e ( n o u v e l l e P e r s o n n e MIRRORPERSONNE%rowtype ) ;
PROCEDURE v e r i f i e M a r i F e m m e ( nouveauMariage MARIAGE%rowtype ) ;
118
end c o n t r a i n t e s T r a n s ;
/
PROCEDURE v e r i f i e P e r e M e r e ( n o u v e l l e P e r s o n n e MIRRORPERSONNE%rowtype ) I S
nb INT;
BEGIN
SELECT COUNT( ∗ ) INTO nb
FROM MIRRORPERSONNE
WHERE p e r e = n o u v e l l e P e r s o n n e . mere
OR mere = n o u v e l l e P e r s o n n e . p e r e ;
IF ( nb <> 0 ) THEN
RAISE TRANS;
END IF ;
SELECT COUNT( ∗ ) INTO nb
FROM MIRRORMARIAGE
WHERE numMari = n o u v e l l e P e r s o n n e . mere
OR numFemme = n o u v e l l e P e r s o n n e . p e r e ;
IF ( nb <> 0 ) THEN
RAISE TRANS;
END IF ;
END;
END c o n t r a i n t e s T r a n s ;
/
−− C o n t r a i n t e 7
119
nouveauMariage . numMari := : new . numMari ;
nouveauMariage . numFemme := : new . numFemme ;
nouveauMariage . d a t e M a r i a g e := : new . d a t e M a r i a g e ;
nouveauMariage . d a t e D i v o r c e := : new . d a t e D i v o r c e ;
c o n t r a i n t e M a r i a g e C o n s a n g u i n . v e r i f i e M a r i a g e C o n s a n g u i n ( nouveauMariage ) ;
END;
/
120
Annexe A
121
A.2 Modules et prerequis
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.
CREATE TABLE MODULE
(numMod number primary key ,
nomMod varchar2 ( 3 0 )
);
122
A.3 Géométrie
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.
CREATE TABLE INTERVALLE
( b o r n e I n f NUMBER,
borneSup NUMBER,
PRIMARY KEY ( b o r n e I n f , borneSup ) ) ;
123
A.4 Livraisons
CREATE TABLE PRODUIT
( numprod number ,
nomprod varchar2 ( 3 0 ) ) ;
a l t e r table p r o d u i t add c o n s t r a i n t p k p r o d u i t
PRIMARY KEY ( numprod ) ;
a l t e r table f o u r n i s s e u r add c o n s t r a i n t p k f o u r n i s s e u r
PRIMARY KEY ( numfou ) ;
a l t e r table p r o p o s e r add c o n s t r a i n t p k p r o p o s e r
PRIMARY KEY ( numfou , numprod ) ;
a l t e r table l i v r a i s o n add c o n s t r a i n t p k l i v r a i s o n
PRIMARY KEY ( numfou , numli ) ;
a l t e r table d e t a i l l i v r a i s o n add c o n s t r a i n t p k d e t a i l l i v r a i s o n
PRIMARY KEY ( numfou , numli , numprod ) ;
a l t e r table p r o p o s e r add c o n s t r a i n t f k p r o p o s e r f o u r n i s s e u r
FOREIGN KEY ( numfou ) REFERENCES f o u r n i s s e u r ( numfou ) ;
a l t e r table 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 table 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 table 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 table 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 ) ;
124
A.5 Arbre généalogique
La table PERSONNE, 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.
CREATE TABLE PERSONNE
( numpers number PRIMARY KEY,
nom varchar2 ( 3 0 ) NOT NULL,
prenom varchar2 ( 3 0 ) ,
p e r e REFERENCES PERSONNE( numpers ) ,
mere REFERENCES PERSONNE( numpers )
);
125
A.6 Comptes bancaires
DROP TABLE OPERATION;
DROP TABLE TYPEOPERATION;
DROP TABLE COMPTECLIENT;
DROP TABLE TYPECCL;
DROP TABLE PERSONNEL;
DROP TABLE CLIENT ;
126
CONSTRAINT p k o p e r a t i o n
PRIMARY KEY ( numcli , numccl , numoper ) ,
CONSTRAINT f k o p e r c c l
FOREIGN KEY ( numcli , numoper )
REFERENCES COMPTECLIENT ( numcli , numccl ) ,
CONSTRAINT f k o p e r c o d e o p e r
FOREIGN KEY ( numtypeoper )
REFERENCES t y p e o p e r a t i o n ( numtypeoper ) ,
CONSTRAINT m o n t a n t o p e r a t i o n
CHECK( montantoper <> 0 )
);
127
A.7 Comptes bancaires avec exceptions
DROP TABLE OPERATION;
DROP TABLE COMPTECLIENT;
DROP TABLE TYPECCL;
DROP TABLE TYPEOPERATION;
DROP TABLE PERSONNEL;
DROP TABLE CLIENT ;
128
CONSTRAINT p k o p e r a t i o n
PRIMARY KEY ( numcli , numccl , numoper ) ,
CONSTRAINT f k o p e r c c l
FOREIGN KEY ( numcli , numoper )
REFERENCES COMPTECLIENT ( numcli , numccl ) ,
CONSTRAINT f k o p e r c o d e o p e r
FOREIGN KEY ( numtypeoper )
REFERENCES t y p e o p e r a t i o n ( numtypeoper ) ,
CONSTRAINT m o n t a n t o p e r a t i o n
CHECK( montantoper <> 0 AND montantoper >= −1000 AND montantoper <= 1 0 0 0 )
);
129
A.8 Secrétariat pédagogique
DROP TABLE RESULTAT;
DROP TABLE EXAMEN;
DROP TABLE PREREQUIS ;
DROP TABLE INSCRIPTION ;
DROP TABLE MODULE;
DROP TABLE ETUDIANT;
130
ALTER TABLE ETUDIANT ADD
(CONSTRAINT c k c i v i l i t e
CHECK
(
c i v i l i t e IN ( ’Mr ’ , ’Mme ’ , ’ M l l e ’ )
),
CONSTRAINT c k c i v i l i t e n u m s e c u
CHECK
(
SUBSTR( numsecu , 1 , 1 ) = ’ 2 ’ OR patronyme I S NULL
),
CONSTRAINT c k l e n g t h n u m s e c u
CHECK
(
l e n g t h ( numsecu ) = 15
),
CONSTRAINT c k a n n e e n u m s e c u CHECK
(
t o c h a r ( d a t e n a i s s , ’ yy ’ ) = substr ( numsecu , 2 , 2 )
)
);
131
A.9 Mariages
CREATE TABLE PERSONNE
( numpers number PRIMARY KEY,
nom varchar2 ( 3 0 ) NOT NULL,
prenom varchar2 ( 3 0 ) ,
p e r e REFERENCES PERSONNE( numpers ) ,
mere REFERENCES PERSONNE( numpers )
);
132