Vous êtes sur la page 1sur 130

Table des mati`eres

1 Notes de cours 4
1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1.1 Quest-ce quun SGBD? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1.2 Organisation relationnelle des donnees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1.3 Survol de SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1.4 SQL+ et iSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2 Contraintes declaratives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.1 Valeurs par defaut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.2 Champs non renseignes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.3 Cle primaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.4 Cle etrang`ere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.5 Syntaxe alternative . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.3 Introduction aux requetes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3.1 Complements sur SELECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3.2 Instruction WHERE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3.3 Conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3.4 Suppression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.3.5 Mise `a jour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4 Jointures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4.2 Produit cartesien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.4.3 Jointure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.4.4 Jointures reexives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.5 Agregation de donnees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.5.1 Fonctions dagregation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.5.2 Groupage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.6 Vues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.6.1 Denition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.6.2 Syntaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.6.3 Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.6.4 Suppression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.7 Requetes imbriquees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
1.7.1 Sous requetes renvoyant une valeur scalaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
1.7.2 Sous requetes renvoyant une colonne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.7.3 Sous requetes non correlees renvoyant une table . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.7.4 Sous requetes correlees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
1.8 Complements sur les types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.8.1 Types numeriques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.8.2 Types chaine de caract`eres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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 Achage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.9.4 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1
1.9.5 Traitements conditionnels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.9.6 Traitements repetitifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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 Aectation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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 predenies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
1.12.3 Codes derreur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
1.12.4 Declarer et lancer ses propres exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
1.13 Sous-programmes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
1.13.1 Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
1.13.2 Fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
1.14 Curseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.14.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.14.2 Les curseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.15 Curseurs parametres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.15.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.15.2 Denition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.15.3 Declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.15.4 Ouverture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.15.5 Lecture dune ligne, fermeture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
1.15.6 Boucle pour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
1.15.7 Exemple recapitulatif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
1.16 Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
1.16.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
1.16.2 Classication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
1.16.3 Creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
1.16.4 Acc`es aux lignes en cours de modication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
1.16.5 Contourner le probl`eme des tables en mutation . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
1.17 Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
1.17.1 Principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
1.17.2 Specication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
1.17.3 Corps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
2 Exercices 55
2.1 Contraintes declaratives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
2.2 Introduction aux requetes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
2.3 Jointures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
2.4 Agregation de donnees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
2.5 Vues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
2.6 Requetes imbriquees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
2.7 Complements sur les types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
2.8 Revisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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 parametres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
2.16 Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
2.17 Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
2.18 Revisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
2
3 Corriges 76
3.1 Contraintes declaratives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
3.2 Introduction aux requetes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
3.3 Jointures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
3.4 Agregation de donnees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
3.5 Vues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
3.6 Requetes imbriquees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
3.7 Complements sur les types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
3.8 Revisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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 parametres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
3.16 Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
3.17 Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
3.18 Revisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
A Scripts de creation de bases 121
A.1 Livraisons Sans contraintes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
A.2 Modules et prerequis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
A.3 Geometrie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
A.4 Livraisons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
A.5 Arbre genealogique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
A.6 Comptes bancaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
A.7 Comptes bancaires avec exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
A.8 Secretariat pedagogique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
A.9 Mariages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
3
Chapitre 1
Notes de cours
1.1 Introduction
1.1.1 Quest-ce quun SGBD?
Denition : logiciel qui stocke des donnees de fa con organisee et coherente.
Access : version edulcoree. Mais mono-utilisateur, et faible capacite.
Les donnees sont stockees dans des chiers geres par le serveur de base de donnees. Cette operation est opaque.
On transmet depuis un client des instructions `a la base par lintermediaire du langage SQL.
Avantages :
permet de maintenir de facon able lintegrite des donnees
operations de bas niveau opaques
rapide
multi-utilisateurs
moins de trac sur le reseau
securite
Inconvenient :
Un peu plus long que bien programme en C, et encore...
Plusieurs facons dorganiser les donnees :
hierarchique
relationnel
deductif
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 donnees. Dun SGBD `a lautre, le SQL
change tr`es peu. Ce cours est surtout un cours de SQL.
1.1.2 Organisation relationnelle des donnees
Les donnes sont stockees dans des tables.
Table : tableau `a deux entrees.
Le MPD nous donne, pour chaque table, les colonnes (i.e. champs) que doit comporter la table.
nomtable ( col onne1 , col onne2 , . . . , col onnen )
Par exemple :
4
CLIENT( numero , prenom , nom, emai l )
nous donnera la table
numero nom prenom email
20505372 Alexandre Mesle alexandre.mesle@gmail.com
... ... ... ...
Supposons que lon veuille gerer des commandes emises par des clients. Nous souhaitons stocker les donnees sui-
vantes :
nom, prenom et adresse compl`ete des clients
produits proposes et co uts unitaires
pour chaque commande, le detail et le montant.
Apr`es maintes peripeties, nous en arrivons au MPD suivant :
CLIENT( numer o cl i ent , prenom , nom, adres se1 , adr es se2 , #CP)
CODE POSTAL(CP, v i l l e )
PRODUIT( numero produi t , de s c r i pt i on , pr i x uni t a i r e )
COMMANDE(#numer o cl i ent , numero commande )
LIGNECOMMANDE(#numer o cl i ent , #numero commande , #numero produi t , quant i t e )
Nous pouvons representer la base, avec quelques donnees inserees, par des tableaux
numero client prenom nom adresse1 adresse2 #CP
1 Alexandre Mesle Cite les framboises 28, rue du chemin vert 75013
2 Amedee Moregroin 29, rue de Choisy 95200
3 Medor dans sa niche 75013
4 Louis-Hubert Martin 112, rue de la Pompe 75016
CP ville
75013 Paris
75016 Paris
95200 Sarcelles
numero produit decription prix unitaire
1 Boite de cornichons 2.5
2 Goupillon 6.5
3 Cotons-tige 1.2
4 Ajax WC 1.2
5 Place concert des Stones 145
6 Roue de secours 75
7 Compas 4
8 Armoire Gl udehnblourf 146
9 Pate dietetique 12
10 Croquettes laxatives 8
#numero client numero commande
1 1
1 2
2 1
3 1
#numero client #numero commande #numero produit quantite
1 1 5 2
1 2 4 29
1 2 7 1
2 1 1 4
3 1 9 238
1.1.3 Survol de SQL
Le SQL de base se decline en quatre parties :
5
DDL : Data denition language
DML : Data manipulation language
DQL : Data query language
DCL : Data control language
A cela sajoute le PL/SQL. Celui-ci permet de gerer presque toutes les contraintes et de maintenir la coherence de
la base de donnees. Mais cest beaucoup plus complique...
Creer des tables
Les types pour commencer
numeriques : number
chanes de caract`eres : varchar2(taille)
syntaxe :
CREATE TABLE <nomdel atabl e>
(<de s c r i pt i on c ol onne 1 >, . . . , <de s c r i pt i on c ol onne n >)
Pour chaque colonne :
<nomcolonne> <type> [<opt i ons e ve nt ue l l e s >]
exemple :
create table c l i e n t
(
numcl i number,
nom varchar2 ( 256) ,
prenom varchar2( 256)
)
Acher le contenu dune table
syntaxe :
SELECT FROM<nomdel atabl e>
exemple :
sel ect from c l i e n t
Ajouter une ligne dans une table
syntaxe :
INSERT INTO <nomdel atabl e> (<nomcol onne 1 >, . . . , <nomcolonne n >)
VALUES (<val eur col onne 1 >, . . . , <val eur col onne n >)
exemple :
INSERT INTO CLIENT ( numcli , nom, prenom) VALUES ( 1 , Mesl e , Al exandre )
1.1.4 SQL+ et iSQL
Connection
login : scott
password : tiger
Liste des tables
SELECT tabl e name FROM us e r t a bl 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 declaratives
1.2.1 Valeurs par defaut
create table c l i e n t
(
numcl i number,
nom varchar2( 256) default Moi ,
prenom varchar2( 256)
)
fait de Moi le nom par defaut.
1.2.2 Champs non renseignes
create table c l i e n t
(
numcl i number,
nom varchar2( 256) NOT NULL,
prenom varchar2( 256) NOT NULL
)
force la saisie des champs nom et prenom.
1.2.3 Cle primaire
Une cle primaire est :
toujours renseignee
unique
On peut preciser PRIMARY KEY dans la creation de table
create table c l i e n t
(
numcl i number PRIMARY KEY,
nom varchar2 ( 256) ,
prenom varchar2( 256)
)
La colonne numcli est cle primaire, toute insertion ne respectant pas la contraine de cle primaire sera refusee par
Oracle.
1.2.4 Cle etrang`ere
Une cle etrang`ere reference une ligne dune table quelconque :
Syntaxe :
REFERENCES <nomtable> (<nomcolonne >)
create table c l i e n t
(
numcl i number PRIMARY KEY,
nom varchar2 ( 256) ,
prenom varchar2 ( 256) ,
numdept number REFERENCES DEPT ( nd)
)
Une ligne ne pourra etre inseree dans la table client que sil existe dans la table DEPT une ligne dont la valeur nd
est la meme que la valeur numdept en cours dinsertion.
On remarque quil devient impossible decraser la table DEPT si elle est referencee par une cle etrang`ere.
1.2.5 Syntaxe alternative
ALTER TABLE <nomtable>
ADD [CONSTRAINT <nomcontrai nte >] <de s c r i pt i onc ont r ai nt e >
8
descriptioncontrainte dune cle primaire :
PRIMARYKEY(<col onne 1 >, . . . , <col onne n >)
descriptioncontrainte dune cle etrang`ere :
FOREIGN KEY(<col onne 1 >, . . . , <col onne n >)
REFERENCES <t a bl e r e f e r e nc e e > (<col onne 1 >, . . . , <col onne n >)
Il est aussi possible de placer une descriptioncontrainte dans le CREATE TABLE. Par exemple,
create table c l i e n t
(
numcl i number,
nom varchar2 ( 256) ,
prenom varchar2 ( 256) ,
numdept number,
PRIMARYKEY (number) ,
FOREIGN KEY ( numdept ) REFERENCES DEPT ( nd)
)
On remarque quil est possible de nommer une contrainte. Cest utile si on souhaite la supprimer :
ALTER TABLE <nomtable> DROPCONSTRAINT <nomcontrai nte>
Pour lister les contraintes :
SELECT FROM USER CONSTRAINTS
9
1.3 Introduction aux requetes
1.3.1 Complements sur SELECT
Il est possible dutiliser SELECT pour nacher que certaines colonnes dune table. Syntaxe :
SELECT <col onne 1 >, <col onne 2 >, . . . , <col onne n>
FROM<table>
Cette instruction sappelle une requete, elle achera pour chaque ligne de la table les valeurs des colonnes colonne
1
`a colonne
n
. Il est possible de supprimer les lignes en double `a laide du mot-cle DISTINCT. Par exemple :
SELECT DISTINCT <col onne 1 >, <col onne 2 >, . . . , <col onne n>
FROM<table>
Pour trier les donnees, on utilise ORDER BY. Exemple :
SELECT <col onne 1 >, <col onne 2 >, . . . , <col onne n>
FROM<table>
ORDERBY <col onne 1bi s >, <col onne 2bi s >, . . . , <col onne nbi s >
Cette instruction trie les donnees par colonne
1bis
croissants. En cas degalite, le tri est fait par colonne
2bis
croissants,
etc. Pour trier par ordre decroissant, on ajoute DESC apr`es le nom de la colonne choisie comme crit`ere decroissant. Par
exemple :
SELECT <col onne 1 >, <col onne 2 >, . . . , <col onne n>
FROM<table>
ORDERBY <col onne 1bi s > DESC, <col onne 2bi s >, . . . , <col onne nbi s >
1.3.2 Instruction WHERE
Cette instruction permet de ne selectionner que certaines lignes de la table. Par exemple la requete
SELECT nom cl i ent , pr enom cl i ent
FROM c l i e n t
WHERE numer o cl i ent = 1
va acher les nom et prenom du client dont le numero est 1. La syntaxe generale est
SELECT <col onne 1 >, <col onne 2 >, . . . , <col onne n>
FROM<table>
WHERE <condi t i on>
condition sera evaluee pour chaque ligne de la table, et seules celles qui veeront cette condition feront partie du
resultat de la requete.
1.3.3 Conditions
Comparaison
Les conditions peuvent etre des relations degalite (=), de dierence (<>), dinegalite (<, >, >= ou <=) sur des
colonnes :
numer o cl i ent = 2
nom cl i ent = Chi rac
pr enom cl i ent <> Hubert
s al ar y < 230
t axes >= 23000
Negation
La negation dune condition sobtient `a laide de NOT. Par exemple, il est possible de re-ecrire les conditions ci-avant :
NOT ( numer o cl i ent <> 2)
NOT ( nom cl i ent <> Chi rac )
NOT ( pr enom cl i ent = Hubert )
NOT ( s al ar y >= 230)
NOT ( t axes < 23000)
10
Connecteurs logiques
De meme, vous avez `a votre disposition tous les connecteurs logiques binaires : AND, OR. Ainsi, les deux conditions
suivantes sont les memes :
NOT( ( nom = Bush ) AND ( prenom <> Medor ) )
(nom <> Bush ) OR ( prenom = Medor )
NULLite
Un champ non renseigne a la valeur NULL, dans une comparaison, NULL nest jamais egal `a quelque valeur quil
soit ! La condition suivante est toujours fausse :
NULL = NULL;
La requete suivante ne renvoie aucune ligne :
SELECT FROMEMP WHERECOMM=NULL;
Pour tester la nullite dun champ, on utilise IS NULL, par exemple :
SELECT FROMEMP WHERECOMM IS NULL;
La non-nullite se teste de deux facons :
WHERENOT (COMM IS NULL) ;
WHERECOMM IS NOT NULL
Encadrement
Une valeur numerique peut etre encadree `a laide de loperateur BETWEEN, par exemple les deux conditions suivantes
sont equivalentes :
SALAIRE BETWEEN 1000 AND 5000
(SALAIRE >= 1000) AND (SALAIRE <= 5000)
Inclusion
Loperateur IN permet de tester lappartenance `a une liste de valeurs. Les deux propositions suivantes sont
equivalentes
NAME IN ( Mesl e , Bush , Medor )
(NAME = Mesl e ) OR (NAME = Bush ) OR (NAME = Medor )
LIKE
LIKE sert `a comparer le contenu dune variable `a un litteral generique. Par exemple, la condition
NAME LIKE M%
sera veriee si NAME commence par un M. Ca fonctionne aussi sur les valeurs de type numerique, la condition
SALARY LIKE %000000000
sera veriee si SALARY se termine par 000000000. Le caract`ere % peut remplacer dans le litteral nimporte que suite,
vide ou non, de caract`eres ; il a le meme role que * en DOS et en SHELL. Le caract`ere remplace un et un seul
caract`ere dans le litteral. Par exemple, la condition
NAME LIKE B s%
ne sera veriee que si NAME commence par un B et contient un s en troisi`eme position.
1.3.4 Suppression
Lexpression
DELETEFROM<NOMTABLE> WHERE <CONDITION>
eace de la table NOMTABLE toutes les lignes veriant condition. Attention! La commande
DELETEFROM<NOMTABLE>
eace toutes les lignes de la table NOMTABLE !
11
1.3.5 Mise `a jour
Lexpression
UPDATE <NOMTABLE> SET
<col onne 1> = <val eur 1 >,
<col onne 2> = <val eur 2 >,
. . . ,
<col onne n> = <val eur n>
WHERE <CONDITION>
modie les lignes de la table NOMTABLE veriant condition. Elle aecte au champ colonne
i
la valeur valeur
i
. Par
exemple,
UPDATE CLIENT SET NAME = Medor WHERE LUNCH = Bones
aecte la valeur M edor aux champs noms de toutes les lignes dont la valeur LUNCH est egale `a Bones. Il est possible,
dans une modication, dutiliser les valeurs des autres champs de la ligne, voire meme lancienne valeur de ce champ.
Par exemple,
UPDATE CLIENT SET SALARY = SALARY + 5000
augmente tous les salaires de 5000 (choisissez lunite !).
12
1.4 Jointures
1.4.1 Principe
Etant donne le code ci-dessous,
CREATE TABLE MODULE
(numMod number primary key ,
nomMod varchar2( 30)
) ;
CREATE TABLE PREREQUIS
(
numMod number r e f e r e nc e s MODULE(numMod) ,
numModPrereq number r e f e r e nc e s MODULE(numMod) ,
noteMin number( 2) DEFAULT 10 NOT NULL ,
PRIMARYKEY(numMod, numModPrereq)
) ;
INSERT INTO MODULE VALUES ( 1 , ORacle ) ;
INSERT INTO MODULE VALUES ( 2 , C++ ) ;
INSERT INTO MODULE VALUES ( 3 , C ) ;
INSERT INTO MODULE VALUES ( 4 , Algo ) ;
INSERT INTO MODULE VALUES ( 5 , Meri se ) ;
INSERT INTO MODULE VALUES ( 6 , PL/SQL Oracl e ) ;
INSERT INTO MODULE VALUES ( 7 , mySQL ) ;
INSERT INTO MODULE VALUES ( 8 , Algo avancee ) ;
INSERT INTO PREREQUIS (numMod, numModPrereq) VALUES ( 1 , 5 ) ;
INSERT INTO PREREQUIS (numMod, numModPrereq) VALUES ( 2 , 3 ) ;
INSERT INTO PREREQUIS VALUES ( 6 , 1 , 12) ;
INSERT INTO PREREQUIS (numMod, numModPrereq) VALUES ( 6 , 5 ) ;
INSERT INTO PREREQUIS (numMod, numModPrereq) VALUES ( 8 , 5 ) ;
INSERT INTO PREREQUIS (numMod, numModPrereq) VALUES ( 7 , 5 ) ;
Si on souhaite connatre les numeros des modules prerequis pour sinscrire dans le module PL/SQL Oracle, il
nous faut tout dabord le numero de ce module :
SQL> SELECT numMod FROM module WHERE nomMod = PL/SQL Oracl e ;
NUMMOD

6
Ensuite, cherchons les numeros des modules prerequis pour sinscrire dans le module numero 6,
SQL> SELECT numModPrereq FROM pr e r e qui s WHERE numMod = 6;
NUMMODPREREQ

1
5
Et pour nir, allons recuperer les noms de ces modules,
SQL> SELECT nomMod FROM module WHERE numMod IN ( 1 , 5 ) ;
NOMMOD

Oracl e
Meri se
Vous etes probablement tous en train de vous demander sil nexiste pas une methode plus simple et plus rapide,
et surtout une facon dautomatiser ce que nous venons de faire. Il existe un moyen de selectionner des donnees dans
plusieurs tables simultanement. Pour traiter la question ci-dessus il susait de saisir :
13
SQL> SELECT m2. nomMod
2 FROM module m1, module m2, pr e r e qui s p
3 WHERE m1. numMod = p . numMod AND m2. numMod = p . numModprereq
4 AND m1. nomMod = PL/SQL Oracl e ;
NOMMOD

Oracl e
Meri se
Le but de ce chapitre est dexpliciter ce type de commande.
1.4.2 Produit cartesien
Linstruction SELECT ... FROM ... peut setendre de la facon suivante :
SELECT <l i s t e c o l o nne s >
FROM<l i s t e t a b l e s >
Lexemple ci-dessous vous montre le resultat dune telle commande.
SQL> SELECT FROM proposer , pr odui t ;
NUMFOU NUMPROD PRIX NUMPROD NOMPROD

1 1 200 1 Roue de s e c our s
1 1 200 2 Poupee Batman
1 1 200 3 Cotons t i g e s
1 1 200 4 Corni chons
1 2 15 1 Roue de s e c our s
1 2 15 2 Poupee Batman
1 2 15 3 Cotons t i g e s
1 2 15 4 Corni chons
2 2 1 1 Roue de s e c our s
2 2 1 2 Poupee Batman
2 2 1 3 Cotons t i g e s
NUMFOU NUMPROD PRIX NUMPROD NOMPROD

2 2 1 4 Corni chons
3 3 2 1 Roue de s e c our s
3 3 2 2 Poupee Batman
3 3 2 3 Cotons t i g e s
3 3 2 4 Corni chons
16 l i g ne ( s ) s e l e c t i o nne e ( s ) .
Placer une liste de tables dans le FROM revient `a former toutes les combinaisons de lignes possibles. Cependant, cela
a relativement peu de sens.
1.4.3 Jointure
Il serait plus interessant, dans le cas present, de ne voir sacher que des lignes dont les numeros de produits
concordent. Pour ce faire, il sut dutiliser WHERE. Par exemple,
SQL> SELECT FROM proposer , pr odui t
2 WHERE pr opos er . numprod = pr odui t . numprod ;
NUMFOU NUMPROD PRIX NUMPROD NOMPROD

1 1 200 1 Roue de s e c our s
2 2 1 2 Poupee Batman
1 2 15 2 Poupee Batman
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 cle etrang`ere dans proposer. Comme la colonne numprod apparait deux fois dans la requete,
il est necessaire de la prexer par le nom de la table de sorte que chaque colonne puisse etre designee de fa con non
ambigue. Si on veut mettre face `a face les noms des produits et les noms des fournisseurs, il sut de saisir la requete
SQL> SELECT nomfou , nomprod
2 FROM produi t , f our ni s s e ur , pr opos er
3 WHERE pr odui t . numProd = pr opos er . numProd
4 AND f o ur ni s s e ur . numFou = pr opos er . numFou;
NOMFOU NOMPROD

f 1 Roue de s e c our s
f 2 Poupee Batman
f 1 Poupee Batman
f 3 Cotons t i g e s
1.4.4 Jointures reexives
En utilisant la syntaxe suivante, il est possible de rennomer les tables,
FROM<t abl e 1 > <tabl e 1 renommee >, . . . , <t abl e n> <tabl e n renommee>
Reformulons la requete ci-dessus,
SQL> SELECT nomfou , nomprod
2 FROM pr odui t p , f o ur ni s s e ur f , pr opos er pr
3 WHERE p . numProd = pr . numProd
4 AND f . numFou = pr . numFou;
NOMFOU NOMPROD

f 1 Roue de s e c our s
f 2 Poupee Batman
f 1 Poupee Batman
f 3 Cotons t i g e s
Le renommage permet entre autres de faire des jointures reexives, cest `a dire entre une table et elle meme. 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 ne ( s ) s e l e c t i o nne e ( s ) .
La commande ci-dessous ache tous les couples dintervalles 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 . bor neI nf = j . bor neI nf OR i . borneSup = j . borneSup )
3 AND i . rowi d <> j . rowi d ;
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 l i g ne ( s ) s e l e c t i o nne e ( s ) .
Que ceux qui ont du courage reformulent la requete sans utiliser le rowid !
16
1.5 Agregation de donnees
1.5.1 Fonctions dagregation
Exemple introductif
Nous voulons connatre le nombre de lignes de table produit. Deux fa cons de proceder :
1. Solution moche
SQL> SELECT FROM PRODUIT;
NUMPROD NOMPROD

1 Roue de s e c our s
2 Poupee Batman
3 Cotons t i g e s
4 Corni chons
4 l i g ne ( s ) s e l e c t i o nne e ( s ) .
On a la reponse avec le nombre de lignes selectionnees.
2. Solution belle
SQL> SELECT count ( ) FROM PRODUIT;
COUNT( )

4
1 l i g ne s e l e c t i o nne e .
La reponse est le resultat de la requete.
Denition
Une fonction dagregation retourne une valeur calculee sur toutes les lignes de la requete (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 dutilisation
Lexemple suivant retourne le prix du produit propose au prix maximal.
SQL> SELECTMAX( pr i x )
2 FROM PROPOSER;
MAX(PRIX)

200
1 l i g ne s e l e c t i o nne e .
Il est possible de renommer la colonne MAX(prix), en utilisant le mot cle AS :
SQL> SELECTMAX( pr i x ) AS PRIX MAXIMAL
2 FROM PROPOSER;
PRIX MAXIMAL

200
17
1 l i g ne s e l e c t i o nne e .
Les requetes suivantes recup`erent le nom du fournisseur proposant larticle Poupee Batman au prix le moins eleve :
SQL> SELECT MIN( pr 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 l i g ne s e l e c t i o nne e .
SQL> SELECT nomfou
2 FROM FOURNISSEUR F, PROPOSER PR, PRODUIT P
3 WHERE F. numfou = PR. numfou
4 AND PR. numprod = P. numprod
5 AND nomprod = Poupee Batman
6 AND pr i x = 1;
NOMFOU

f 2
1 l i g ne s e l e c t i o nne e .
Il est possible de faire cela avec une seule requete en recuperant le prix minimum dans une requete imbriquee. Mais
cela sera pour un cours ulterieur.
Complements sur COUNT
On recup`ere le nombre de ligne retournees par une requete en utilisant COUNT(*). Par exemple, si on souhaite
connatre le nombre de produits proposes par le fournisseur f1 :
SQL> SELECT COUNT( ) AS NB PROD
2 FROM FOURNISSEUR F, PROPOSER P
3 WHERE F. numfou = P. numfou
4 AND nomfou = f 1 ;
NB PROD

2
1 l i g ne s e l e c t i o nne e .
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 l i g ne s e l e c t i o nne e .
Pour connatre le nombre de produits proposes, cest `a dire dont le numprod a une occurence dans la table PROPOSER,
on proc`ede de la facon suivante :
18
SQL> SELECT COUNT(DISTINCT numprod) AS NB PRODUITS PROPOSES
2 FROM PROPOSER;
NB PRODUITS PROPOSES

3
1 l i g ne s e l e c t i o nne e .
Le DISTINCT nous sert `a eviter quun meme produit propose par des fournisseurs dierents soit comptabilise
plusieurs fois.
1.5.2 Groupage
Linstruction GROUP BY
Les operation dagregation considerees jusqu`a maintenant portent sur la totalite des lignes retournees par les
requetes, linstruction GROUP BY permet de former des paquets `a linterieur desquels les donnees seront agregees. Cette
instruction sutilise de la mani`ere suivante
SELECT . . .
FROM . . .
WHERE. . .
GROUPBY <l i s t e c o l o nne s >
ORDERBY . . .
La liste des colonnes sert de crit`ere pour repartir les lignes dans des paquets de lignes. Si par exemple nous
souhaitons acher la liste des nombres de produits proposes 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 GROUPBY nomfou ;
NOMFOU NB PRODUITS PROPOSES

f 1 2
f 2 1
f 3 1
3 l i g ne ( s ) s e l e c t i o nne e ( s ) .
Linstruction HAVING
Supposons que de la requete precedente, nous ne souhaitions garder que les lignes pour lesquelles la valeur
NB PRODUITS PROPOSES est egale `a 1. Ajouter une condition dans WHERE serait inutile, le ltrage occasionne par WHERE
est eectue avant lagregation. Il nous faudrait une instruction pour ninclure que des groupes de donnees repondant
certains crit`eres. Linstruction utilisee pour ce faire est HAVING. Son utilisation est la suivante :
SELECT . . .
FROM . . .
WHERE . . .
GROUPBY. . .
HAVING <condi t i on>
ORDERBY . . .
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 GROUPBY nomfou
5 HAVINGCOUNT(DISTINCT numprod) = 1
19
6 ORDERBY nomfou DESC;
NOMFOU NB PRODUITS PROPOSES

f 3 1
f 2 1
2 l i g ne ( s ) s e l e c t i o nne e ( s ) .
Achons les noms des fournisseurs qui ont livre strictement plus dun produit dierent (toutes livraisons confon-
dues),
SQL> SELECT nomfou
2 FROM FOURNISSEUR F, DETAILLIVRAISON D
3 WHERE F. numfou = D. numfou
4 GROUPBY nomfou
5 HAVING count (DISTINCT D. numprod) > 1;
NOMFOU

f 1
1 l i g ne s e l e c t i o nne e .
20
1.6 Vues
1.6.1 Denition
Une vue est une table contenant des donnees calculees sur celle dune autre table. Les donnees dune vue sont tout
le temps `a jour. Si vous modiez les donnees dune des tables sur lesquelles est calculee la vue, alors les modications
sont automatiquement repercutees sur la vue.
1.6.2 Syntaxe
Appreciez la simplicite de la syntaxe :
CREATE VIEW <nom vue> AS <requete >
1.6.3 Application
Par exemple, la requete 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 GROUPBY nomprod
6 ORDERBYCOUNT( numfou ) ;
NOMPROD NB FOURNISSEURS

Corni chons 0
Cotons t i g e s 1
Roue de s e c our s 1
Poupee Batman 2
4 l i g ne ( s ) s e l e c t i o nne e ( s ) .
Ce type de requete sera explite dans un cours ulterieur. Pour le moment, notez juste que les outils dont vous
disposez pour le moment ne vous permettront pas de formuler une requete achant les noms des produits nayant
aucun fournisseur. Creons une vue pour ne pas avoir `a se farcir la requete 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 GROUPBY nomprod
7 ORDERBYCOUNT( numfou ) ;
Vue c r e e e .
Une fois creee, on peut interroger une vue de la meme fa con quon interroge une table :
SQL> SELECT
2 FROM NB FOURNISSEURS PAR PRODUIT;
NOMPROD NB FOURNISSEURS

Corni chons 0
Cotons t i g e s 1
Roue de s e c our s 1
Poupee Batman 2
4 l i g ne ( s ) s e l e c t i o nne e ( s ) .
21
Notez que toute modication dans la table PROPOSER ou PRODUIT sera immediatement repercutee sur la vue.
SQL> INSERT INTO PROPOSER VALUES ( 3 , 4 , 9 ) ;
1 l i g ne c r e e e .
SQL> SELECT
2 FROM NB FOURNISSEURS PAR PRODUIT;
NOMPROD NB FOURNISSEURS

Corni chons 1
Cotons t i g e s 1
Roue de s e c our s 1
Poupee Batman 2
4 l i g ne ( s ) s e l e c t i o nne e ( s ) .
Maintenant, nous souhaitons voir sacher, pour tout i, le nombre de produits proposes par exactement i fournis-
seurs.
SQL> SET head o f f
SQL> SELECT I l y a | | COUNT(NOMPROD) | | pr odui t ( s ) qui e s t / sont | |
2 propose ( s ) par | | NB FOURNISSEURS | | f o ur ni s s e ur ( s ) .
3 FROM NB FOURNISSEURS PAR PRODUIT
4 GROUPBY NB FOURNISSEURS
5 ORDERBY NB FOURNISSEURS;
I l y a 3 pr odui t ( s ) qui e s t / sont propose ( s ) par 1 f o ur ni s s e ur ( s ) .
I l y a 1 pr odui t ( s ) qui e s t / sont propose ( s ) par 2 f o ur ni s s e ur ( s ) .
2 l i g ne ( s ) s e l e c t i o nne e ( s ) .
SQL> SET head on
1.6.4 Suppression
On supprime une vue avec linstruction suivante :
DROPVIEW <nom vue >;
22
1.7 Requetes imbriquees
Oracle permet dimbriquer les requetes, cest-`a-dire de placer des requetes dans les requetes. Une requete imbriquee
peut renvoyer trois types de resultats :
une valeur scalaire
une colonne
une table
1.7.1 Sous requetes renvoyant une valeur scalaire
Le resultat dune requete est dit scalaire sil comporte une seule ligne et une seule colonne. Par exemple :
SQL> SELECT COUNT( ) FROM PERSONNE;
COUNT( )

21
On peut placer dans une requete une sous-requete calculant un resultat scalaire. Un tel type de sous-requete se place
soit comme une colonne supplementaire, soit comme une valeur servant `a evaluer des conditions (WHERE ou HAVING).
Colonne ctive
On peut ajouter une colonne dans une requete, et choisir comme valeurs pour cette colonne le resultat dune
requete. Ce type de requete est souvent une alternative `a GROUP BY. Par exemple, la requete 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 our s 1
Poupee Batman 2
Cotons t i g e s 1
Corni chons 0
Conditions complexes
On peut construire une condition en utilisant le resultat dune requete. Pour notre exemple, declarons dabord une
vue contenant le nombe darticles proposes 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 = (SELECTMAX(NB PROD)
5 FROM NB PROD PAR FOU) ;
NOMFOU
23

f 1
La requete SELECT MAX(NB PROD) FROM NB PROD PAR FOU est evaluee avant, et son resultat lui est substitue dans
lexpression de la requete. Comme on a
SQL> SELECTMAX(NB PROD) FROM NB PROD PAR FOU;
MAX(NB PROD)

2
Alors la requete precedente, dans ce contexte, est equivalente `a
SQL> SELECT nomfou
2 FROM FOURNISSEUR F, NB PROD PAR FOU N
3 WHERE F. numfou = N. numfou
4 AND NB PROD = 2;
NOMFOU

f 1
INSERT et UPDATE
On peut placer dans des instructions de mises `a jour ou dinsertions des requetes imbriquees. Par exemple,
SQL> INSERT INTO PERSONNE ( numpers , nom, prenom)
2 VALUES ( (SELECTMAX( numpers ) + 1 FROM PERSONNE) ,
3 Darth , Vador ) ;
1 l i g ne c r e e e .
SQL> UPDATE PERSONNE SET
2 pere = (SELECT numpers
3 FROM PERSONNE
4 WHERE nom = Socr at 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 ne mi se a j our .
1.7.2 Sous requetes renvoyant une colonne
On consid`ere une colonne comme une liste de valeurs, on peut tester lappartance dun element `a cette liste `a laide
de loperateur IN. On peut sen servir comme une alternative aux jointures, par exemple, reecrivons la requete de la
section precedente. La requete suivante nous renvoie le nombre de produits proposes par les fournisseurs proposant le
plus de produits :
SQL> SELECTMAX(NB PROD) FROM NB PROD PAR FOU;
MAX(NB PROD)

2
Maintenant, recherchons les numeros des fournisseurs proposant un tel nombre de produits :
24
SQL> SELECT N. numfou
2 FROM NB PROD PAR FOU N
3 WHERE NB PROD = (SELECTMAX(NB PROD)
4 FROM NB PROD PAR FOU) ;
NUMFOU

1
Notons que sil existe plusieurs fournisseurs proposant 2 produits, cette requete renverra plusieurs lignes. Cest
donc par hasard quelle ne retourne quune ligne. Le numero 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

f 1
Il sut donc dans la requete ci-dessous de remplacer le 1 par la requete qui a retourne 1. On a nalement :
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 = (SELECTMAX(NB PROD)
6 FROM NB PROD PAR FOU) ) ;
NOMFOU

f 1
1.7.3 Sous requetes non correlees renvoyant une table
On peut remplacer le nom dune table dans la clause FROM par une sous-requete. Par exemple, la requete suivante
renvoie une table.
SQL> SELECT
2 (SELECT COUNT( )
3 FROM PROPOSER PR
4 WHERE PR. numfou = F. numfou
5 ) AS NB PROD
6 FROM FOURNISSEUR F;
NB PROD

2
1
1
0
Cette table contient, pour chaque fournisseur, le nombre de produits proposes. Si lon souhaite connatre le plus
grand nombre de produits proposes, on se sert du resultat de la requete ci-dessus comme dune table :
SQL> SELECTMAX(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 requete est une alternative aux vues. Recuperons 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 (SELECTMAX(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

f 1
Vous constatez que la solution utilisant les vues est nettement plus simple.
1.7.4 Sous requetes correlees
Une sous-requete peut etre de deux types :
simple : Elle evaluee avant la requete principale
correlee : Elle est evaluee pour chaque ligne de la requete principale
Par exemple, la requete suivante renvoie le nombre de produits livres pour chaque fournisseur. Elle contient une
sous-requete correlee.
SQL> SELECT numfou ,
2 (SELECT SUM( qte )
3 FROM DETAILLIVRAISON D
4 WHERE D. numfou = F. numfou
5 ) NB PROD L
6 FROM FOURNISSEUR F;
NUMFOU NB PROD L

1 45
2
3 10
4
26
Cette meme requete, une fois evaluee, peut server de requete non correlee si on souhaite connatre les noms de ces
fournisseurs :
SQL> SELECT nomfou , NB PROD L
2 FROM FOURNISSEUR F,
3 (SELECT numfou ,
4 (SELECT SUM( qte )
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

f 1 45
f 2
f 3 10
f 4
Amusons-nous : quel sont, pour chaque fournisseur, les produits qui ont ete les plus livres ?
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( qte )
7 FROM DETAILLIVRAISON L
8 WHERE L. numfou = FF. numfou
9 AND L. numprod = PP. numprod
10 )
11 =
12 (SELECTMAX(NB PROD L)
13 FROM
14 (SELECT numfou , SUM( qte ) AS NB PROD L
15 FROM DETAILLIVRAISON L
16 GROUPBY numprod , numfou
17 ) Q
18 WHERE Q. numfou = FF. numfou
19 )
20 GROUPBY numfou , numprod
21 ) M
22 WHEREM. numprod = P. numprod
23 ANDM. numfou = F. numfou ;
NOMFOU NOMPROD

f 1 Roue de s e c our s
f 3 Cotons t i g e s
Dans la requete precedente, quelles sous-requetes sont correlees et lesquelles ne le sont pas ?
27
1.8 Complements sur les types
1.8.1 Types numeriques
NUMBER(p, s) denit un type numerique de au plus (p s) chires avant la virgule et au plus s chires apr`es la
virgule.
SQL> CREATE TABLE TOTO
2 ( tutu number( 4 , 2)
3 ) ;
Table c r e e e .
SQL> INSERT INTO TOTO VALUES( 1 0 . 2 ) ;
1 l i g ne c r e e e .
SQL> INSERT INTO TOTO VALUES( 1 0 ) ;
1 l i g ne c r e e e .
SQL> INSERT INTO TOTO VALUES( . 0 1 ) ;
1 l i g ne c r e e e .
SQL> INSERT INTO TOTO VALUES( 2 1 . 0 1 ) ;
1 l i g ne c r e e e .
SQL> INSERT INTO TOTO VALUES( 2 1 . 0 ) ;
1 l i g ne c r e e e .
SQL> INSERT INTO TOTO VALUES( 2 1 . 0 1 2 ) ;
1 l i g ne c r e e e .
SQL> INSERT INTO TOTO VALUES( 3 2 1 . 0 ) ;
INSERT INTO TOTO VALUES( 321. 0)

ERREUR a l a l i g ne 1 :
ORA01438: val eur i nc ohe r e nt e avec l a pr e c i s i o n i ndi quee pour c e t t e col onne
SQL> INSERT INTO TOTO VALUES( 321) ;
INSERT INTO TOTO VALUES( 321)

ERREUR a l a l i g ne 1 :
ORA01438: val eur i nc ohe r e nt e avec l a pr e c i s i o n i ndi quee pour c e t t e col onne
SQL> SELECT
2 FROMTOTO;
TUTU

10 , 2
10
, 01
21 , 01
28
21
21 , 01
6 l i g ne ( s ) s e l e c t i o nne e ( s ) .
1.8.2 Types chaine de caract`eres
Une petite liste de proprietes et de fonctions qui peuvent servir :
Pour concatener deux chanes de caract`eres, on utilise loperateur ||
Il est aussi possible de comparer deux chaines de caract`eres avec >, lordre considere est lordre dictionnaire
(ou lexicographique).
La longueur sobtient avec la fonction LENGTH.
On extrait une sous-chaine de caract`eres de longueur l `a partir de lindice i (les indices commencent `a 1) de la
chane s avec la fonction SUBSTR(S, i, l). Par exemple, SUBSTR(oracle, 3, 2) = ac
UPPER convertit en majuscules, LOWER convertit en minuscules.
1.8.3 Types date
Une date en SQL est considere comme un point dans le temps. On le convertit en chaine de carat`eres avec la
fonction to char(date, format), o` u format est une chane de caract`eres optionnelle. Par exemple,
SQL> SELECT t o char ( da t e l i ) AS DT
2 FROM LIVRAISON;
DT

30/10/06
30/10/06
SQL> SELECT t o c har ( dat e l i , yyyy ) AS ANNEE
2 FROM LIVRAISON;
ANNE

2006
2006
SQL> SELECT t o c har ( dat e l i , yyyy/mm/dd ) AS DT
2 FROM LIVRAISON;
DT

2006/10/30
2006/10/30
SQL> SELECT t o c har ( dat e l i , yyyymmdd ) AS DT
2 FROM LIVRAISON;
DT

20061030
20061030
On convertit une chaine de caract`eres en date avec la fonction to date(date, format). Par exemple :
SQL> UPDATE LIVRAISON
2 SET da t e l i = t o dat e ( 1934 | | t o c har ( dat e l i , mmdd ) , yyyymmdd ) ;
2 l i g ne ( s ) mi se ( s ) a j our .
SQL> SELECT
2 FROM LIVRAISON;
NUMFOU NUMLI DATELI
29

1 1 30/10/34
3 1 30/10/34
SQL> UPDATE LIVRAISON
2 SET da t e l i = t o dat e ( 2006 | | t o c har ( dat e l i , mmdd ) , yyyymmdd ) ;
2 l i g ne ( s ) mi se ( s ) a j our .
SQL> SELECT FROM LIVRAISON;
NUMFOU NUMLI DATELI

1 1 30/10/06
3 1 30/10/06
1.8.4 La fonction inclassable
nvl(valeur1, valeur2) renvoie valeur1 si valeur1 est non NULL, valeur2 sinon. Par exemple,
SQL> DELETEFROMTOTO;
6 l i g ne ( s ) suppri mee ( s ) .
SQL> SELECT SUM( tutu )
2 FROMTOTO;
SUM(TUTU)

SQL> SELECT nvl (SUM( tutu ) , 0)


2 FROMTOTO;
NVL(SUM(TUTU) , 0)

0
1.8.5 Contraintes CHECK
La contrainte declarative de type permet de tester une condition portant les lignes de la table prises une par une.
La syntaxe est :
ALTER TABLE nomtable ADDCONSTRAINT nomcontrai nte CHECK( c ondi t i on ) ;
Par exemple,
SQL> ALTER TABLE EMP ADDCONSTRAINT c k s al ar y CHECK(SAL > 0 ) ;
Table modi f i ee .
SQL> INSERT INTO EMP (EMPNO, SAL) VALUES ( 15 , 1);
INSERT INTO EMP (EMPNO, SAL) VALUES ( 15 , 1)

ERREUR a l a l i g ne 1 :
ORA02290: v i o l a t i o n de c ont r ai nt e s (SCOTT. CK SALARY) de v e r i f i c a t i o n
Une contrainte de type CHECK ne peut pas contenir de requetes ni de valeurs non constantes (sysdate par exemple).
30
1.9 Introduction au PL/SQL
1.9.1 PL/SQL
Le PL de PL/SQL signie Procedural Language. Il sagit dune extension procedurale du SQL permettant deectuer
des traitements complexes sur une base de donnees. Les possibilites oertes sont les memes quavec des langages
imperatifs (instructions en sequence) classiques.
Ecrivez-le dans un editeur dont vous copierez le contenu dans SQL+. Un script ecrit en PL/SQL se termine obliga-
toirement par un /, sinon SQL+ ne linterpr`ete pas. Sil contient des erreurs de compilation, il est possible dacher les
messages derreur avec la commande SQL+ : SHOW ERRORS.
1.9.2 Blocs
Tout code ecrit dans un langage procedural est forme de blocs. Chaque bloc comprend une section de declaration
de variables, et un ensemble dinstructions dans lequel les variables declarees sont visibles.
La syntaxe est
DECLARE
/ de c l ar at i on de v a r i a b l e s /
BEGIN
/ i ns t r uc t i o ns a execut er /
END;
1.9.3 Achage
Pour acher le contenu dune variable, les procedures DBMS OUTPUT.PUT() et DBMS OUTPUT.PUT LINE() prennent
en argument une valeur `a acher ou une variable dont la valeur est `a acher. Par defaut, les fonctions dachage
sont desactivees. Il convient, `a moins que vous ne vouliez rien voir sacher, de les activer avec la commande SQL+
SET SERVEROUTPUT ON.
1.9.4 Variables
Une variable se declare de la sorte :
nom type [ : = i n i t i a l i s a t i o n ] ;
Linitisation est optionnelle. Nous utiliserons les memes types primitifs que dans les tables. Par exemple :
SET SERVEROUTPUT ON
DECLARE
c varchar2( 15) := Hel l o World ! ;
BEGIN
DBMS OUTPUT. PUT LINE( c ) ;
END;
/
Les aectations se font avec la syntaxe variable := valeur ;
1.9.5 Traitements conditionnels
Le IF et le CASE fonctionnent de la meme fa con que dans les autres langages imperatifs :
IF / condi t i on 1 / THEN
/ i ns t r uc t i o ns 1 /
ELSE
/ i ns t r uc t i o ns 2 /
END IF ;
voire
IF / condi t i on 1 / THEN
/ i ns t r uc t i o ns 1 /
ELSIF / condi t i on 2 /
/ i ns t r uc t i o ns 2 /
31
ELSE
/ i ns t r uc t i o ns 3 /
END IF ;
Les conditions sont les memes quen SQL. Le switch du langage C simplemente en PL/SQL de la fa con suivante :
CASE / v a r i a b l e /
WHEN / val eur 1 / THEN
/ i ns t r uc t i o ns 1 /
WHEN / val eur 2 / THEN
/ i ns t r uc t i o ns 2 /
. . .
WHEN / val eur n / THEN
/ i ns t r uc t i o ns n /
ELSE
/ i ns t r uc t i o ns par def aut /
END CASE;
1.9.6 Traitements repetitifs
LOOP ... END LOOP ; permet dimplementer les boucles
LOOP
/ i ns t r uc t i o ns /
END LOOP;
Linstruction EXIT WHEN permet de quitter une boucle.
LOOP
/ i ns t r uc t i o ns /
EXIT WHEN / condi t i on / ;
END LOOP;
La boucle FOR existe aussi en PL/SQL :
FOR / v a r i a b l e / IN / i nf / . . / sup / LOOP
/ i ns t r uc t i o ns /
END LOOP;
Ainsi que la boucle WHILE :
WHILE / condi t i on / LOOP
/ i ns t r uc t i o ns /
END LOOP;
Est-il possible, en bidouillant, dimplementer une boucle DO ... WHILE ?
32
1.10 Tableaux et structures
1.10.1 Tableaux
Creation dun type tableau
Les types tableau doivent etre denis explicitement par une declaration de la forme
TYPE / t ype / IS VARRAY ( / t a i l l e / ) OF / t ypeEl ement s / ;
type est le nom du type tableau cree par cette instruction
taille est le nombre maximal delements quil est possible de placer dans le tableau.
typeElements est le type des elements qui vont etre stockes dans le tableau, il peut sagir de nimporte quel
type.
Par exemple, creons un type tableau de nombres indice de 1 `a 10, que nous appelerons numberTab
TYPE numberTab IS VARRAY ( 10) OF NUMBER;
Declaration dun tableau
Dorenavant, le type dun tableau peut etre utilise au meme titre que NUMBER ou VARCHAR2. Par exemple, declarons
un tableau appele t de type numberTab,
DECLARE
TYPE numberTab IS VARRAY ( 10) OF NUMBER;
t numberTab ;
BEGIN
/ i ns t r uc t i o ns /
END;
/
Allocation dun tableau
La creation dun type tableau met `a disposition un constructeur du meme nom que le type cree. Cette fonction
reserve de lespace memoire pour ce tableau et retourne ladresse memoire de la zone reservee, il sagit dune sorte de
malloc. Si, par exemple, un type tableau numtab a ete cree, la fonction numtab() retourne une tableau vide.
DECLARE
TYPE numberTab IS VARRAY ( 10) OF NUMBER;
t numberTab ;
BEGIN
t := numberTab ( ) ;
/ u t i l i s a t i o n du t ab l e au /
END;
/
Une fois cette allocation faite, il devient presque possible dutiliser le tableau...
Dimensionnement dun tableau
Le tableau retourne par le constructeur est vide. Il convient ensuite de reserver de lespace pour stocker les elements
quil va contenir. On utilise pour cela la methode EXTEND(). EXTEND sinvoque en utilisant la notation pointee. Par
exemple,
DECLARE
TYPE numberTab IS VARRAY ( 10) OF NUMBER;
t numberTab ;
BEGIN
t := numberTab ( ) ;
t .EXTEND( 4 ) ;
/ u t i l i s a t i o n du t ab l e au /
END;
/
33
Dans cet exemple, t.EXTEND(4) ; permet par la suite dutiliser les elements du tableau t(1), t(2), t(3) et t(4).
Il nest pas possible detendre un tableau `a une taille superieure `a celle speciee lors de la creation du type tableau
associe.
Utilisation dun tableau
On acc`ede, en lecture et en ecriture, au i-`eme element dune variable tabulaire nomme T avec linstruction T(i).
Les elements sont indices `a partir de 1.
Eectuons, par exemple, une permutation circulaire vers la droite des elements du tableau t.
DECLARE
TYPE numberTab IS VARRAY ( 10) OF NUMBER;
t numberTab ;
i number;
k number;
BEGIN
t := numberTab ( ) ;
t .EXTEND( 1 0 ) ;
FOR i IN 1 . . 1 0 LOOP
t ( i ) := i ;
END LOOP;
k := t ( 1 0 ) ;
FOR i in REVERSE 2 . . 1 0 LOOP
t ( i ) := t ( i 1 ) ;
END LOOP;
t ( 1) := k ;
FOR i IN 1 . . 1 0 LOOP
DBMS OUTPUT. PUT LINE( t ( i ) ) ;
END LOOP;
END;
/
1.10.2 Structures
Un structure est un type regroupant plusieurs types. Une variable de type structure contient plusieurs variables,
ces variables sappellent aussi des champs.
Creation dun type structure
On denit un type structure de la sorte :
TYPE / nomType / IS RECORD
(
/ l i s t e des champs /
) ;
nomType est le nom du type structure construit avec la syntaxe precedente. La liste suit la meme syntaxe que la
liste des colonnes dune table dans un CREATE TABLE. Par exemple, construisons le type point (dans IR
2
),
TYPE poi nt IS RECORD
(
a bs c i s s e NUMBER,
ordonnee NUMBER
) ;
Notez bien que les types servant `a denir un type structure peuvent etre quelconques : variables scalaires, tableaux,
structures, etc.
Declaration dune variable de type structure
point est maintenant un type, il devient donc possible de creer des variables de type point, la r`egle est toujours la
meme pour declarer des variables en PL/SQL, par exemple
34
p poi nt ;
permet de declarer une variable p de type point.
Utilisation dune variable de type structure
Pour acceder `a un champ dune variable de type structure, en lecture ou en ecriture, on utilise la notation pointee :
v.c est le champ appele c de la variable structure appelee v. Par exemple,
DECLARE
TYPE poi nt IS RECORD
(
a bs c i s s e NUMBER,
ordonnee NUMBER
) ;
p poi nt ;
BEGIN
p . a bs c i s s e := 1;
p . ordonnee := 3;
DBMS OUTPUT. PUT LINE( p . a bs c i s s e = | | p . a bs c i s s e | |
and p . ordonnee = | | p . ordonnee ) ;
END;
/
Le script ci-dessous cree le type point, puis cree une variable t de type point, et enn aecte aux champs abscisse
et ordonnee du point p les valeurs 1 et 3.
35
1.11 Utilisation du PL/SQL
Ce cours est une introduction aux interactions possibles entre la base de donnees et les scripts PL/SQL.
1.11.1 Aectation
On place dans une variable le resultat dune requete en utilisant le mot-cle INTO. Les instructions
SELECT champ 1 , . . . , champ n INTO v 1 , . . . , v n
FROM . . .
aecte aux variables v 1, ..., v n les valeurs retournees par la requete. Par exemple
DECLARE
num NUMBER;
nom VARCHAR2( 30) := Poupee Batman ;
BEGIN
SELECT numprod INTO num
FROM PRODUIT
WHERE nomprod = nom;
DBMS OUTPUT. PUT LINE( L a r t i c l e | |
nom | | a pour numero | | num) ;
END;
/
Pretez attention au fait que la requete doit retourner une et une une seule ligne, sinon, une erreur se produit `a
lexecution.
1.11.2 Tables et structures
Si vous ne tenez pas `a vous prendre la tete pour choisir le type de chaque variable, demandez-vous ce que vous
allez mettre dedans ! Si vous tenez `a y mettre une valeur qui se trouve dans une colonne dune table, il est possible de
vous referer directement au type de cette colonne avec le type nomTable.nomColonne%type. Par exemple,
DECLARE
num PRODUIT. numprod%type ;
nom PRODUIT. nomprod%type := Poupee Batman ;
BEGIN
SELECT numprod INTO num
FROM PRODUIT
WHERE nomprod = nom;
DBMS OUTPUT. PUT LINE( L a r t i c l e | |
nom | | a pour numero | | num) ;
END;
/
Pour aller plus loin, il est meme possible de declarer une structure pour representer une ligne dune table, le type
porte alors le nom suivant : nomTable%rowtype.
DECLARE
nom PRODUIT. nomprod%type := Poupee Batman ;
l i g ne PRODUIT%rowtype ;
BEGIN
SELECT INTO l i g ne
FROM PRODUIT
WHERE nomprod = nom;
DBMS OUTPUT. PUT LINE( L a r t i c l e | |
l i g ne . nomprod | | a pour numero | | l i g ne . numprod ) ;
END;
/
36
1.11.3 Transactions
Un des mecanismes les plus puissants des SGBD recents reside dans le syst`eme des transactions. Une transaction
est un ensemble doperations atomiques, cest-`a-dire indivisible. Nous considererons quun ensemble doperations est
indivisible si une execution partielle de ces instructions poserait des probl`emes dintegrite dans la base de donnees.
Par exemple, dans le cas dune base de donnees de gestion de comptes en banque, un virement dun compte `a un autre
se fait en deux temps : crediter un compte dune somme s, et debiter un autre de la meme somme s. Si une erreur
survient pendant la deuxi`eme operation, et que la transaction est interrompue, le virement est incomplet et le patron
va vous assassiner.
Il convient donc de disposer dun mecanisme permettant de se proteger de ce genre de desagrement. Plutot que
se casser la tete `a tester les erreurs `a chaque etape et `a balancer des instructions permettant de revenir en arri`ere,
nous allons utiliser les instructions COMMIT et ROLLBACK.
Voici le squelette dun exemple :
/ i ns t r uc t i o ns /
IF / erreur / THEN
ROLLBACK;
ELSE
COMMIT;
END;
Le ROLLBACK annule toutes les modications faites depuis le debut de la transaction (donc depuis le precedent
COMMIT), COMMIT les enregistre denitivement dans la base de donnees.
La variable denvironnement AUTOCOMMIT, qui peut etre positionnee `a ON ou `a OFF permet dactiver la gestion des
transactions. Si elle est positionnee `a ON, chaque instruction a des repercussions immediates dans la base, sinon, les
modications ne sont eectives quune fois quun COMMIT a ete execute.
37
1.12 Exceptions
Le mecanisme des exceptions est implemente dans la plupart des langages recent, notament orientes objet. Cette
facon de programmer a quelques avantages immediats :
obliger les programmeurs `a traiter les erreurs : combien de fois votre prof de C a hurle en vous suppliant
de verier les valeurs retournees par un malloc, ou un fopen ? La plupart des compilateurs des langages `a
exceptions (notamment java) ne compilent que si pour chaque erreur potentielle, vous avez prepare un bloc de
code (eventuellement vide...) pour la traiter. Le but est de vous assurer que vous navez pas oublie derreur.
Rattraper les erreurs en cours dexecution : Si vous programmez un syst`eme de securite de centrale
nucleaire ou un pilote automatique pour laviation civile, une erreur de memoire qui vous acherait lecran
bleu de windows, ou le message Envoyer le rapport derreur ?, ou plus simplement le fameux Segmentation
fault produirait un eet des plus mauvais. Certaines erreurs dexecution sont rattrapables, autrement dit, il est
possible de resoudre le probl`eme sans interrompre le programme.
Ecrire le traitement des erreurs `a part : Pour des raisons abilite, de lisibilite, il a ete considere que
melanger le code normal et le traitement des erreurs etait un style de programmation perfectible... Dans les
langages `a exception, les erreurs sont traitees `a part.
1.12.1 Rattraper une exception
Je vous ai menti dans le premier cours, un bloc en PL/SQL a la forme suivante :
DECLARE
/ de c l ar at i ons /
BEGIN
/ i ns t r uc t i o ns /
EXCEPTION
/ t r ai t ement des er r eur s /
END;
Une exception est une erreur type, elle porte un nom, au meme titre quune variable a une identicateur, par
exemple GLUBARF. Lorsque dans les instructions, lerreur GLUBARF se produit, le code du BEGIN sinterrompt et le
code de la section EXCEPTION est lance. On dit aussi que quand une exception est levee (raised) (on dit aussi jetee
(thrown)), on la rattrape (catch) dans le bloc EXCEPTION. La section EXCEPTION a la forme suivante :
EXCEPTION
WHEN E1 THEN
/ t r ai t ement /
WHEN E2 THEN
/ t r ai t ement /
WHEN E3 THEN
/ t r ai t ement /
WHENOTHERS THEN
/ t r ai t ement /
END;
On enum`ere les erreurs les plus pertinentes en utilisant leur nom et en consacrant `a chacune delle un traitement
particulier pour rattraper (ou propager) lerreur. Quand un bloc est traite, les WHEN suivants ne sont pas evalues.
OTHERS est lexception par defaut, OTHERS est toujours verie, sauf si un cas precedent a ete verie. Dans lexemple
suivant :
DECLARE
/ de c l ar at i ons /
BEGIN
/ i ns t r uc t i o ns /
COMMIT;
EXCEPTION
WHENGLUBARF THEN
ROLLBACK;
DBMS OUTPUT. PUT LINE( GLUBARF except i on r ai s e d ! ) ;
WHENOTHERS THEN
DBMS OUTPUT. PUT LINE( SQLCODE = | | SQLCODE) ;
DBMS OUTPUT. PUT LINE( SQLERRM = | | SQLERRM) ;
END;
38
Les deux variables globales SQLCODE et SQLERRM contiennent respectivement le code derreur Oracle et un message
derreur correspondant `a la derni`ere exception levee. Chaque exception a donc, en plus dun nom, un code et un
message.
1.12.2 Exceptions predenies
Bon nombre dexceptions sont predenies par Oracle, par exemple
NO DATA FOUND est levee quand la requete dune instruction de la forme SELECT ... INTO ... ne retourne
aucune ligne
TOO MANY ROWS est levee quand la requete dune instruction de la forme SELECT ... INTO ... retourne plusieurs
lignes
DUP VAL ON INDEX est levee si une insertion (ou une modication) est refusee `a cause dune contrainte dunicite.
On peut enrichir notre exemple de la sorte :
DECLARE
num NUMBER;
nom VARCHAR2( 30) := Poupee Batman ;
BEGIN
SELECT numprod INTO num
FROM PRODUIT
WHERE nomprod = nom;
DBMS OUTPUT. PUT LINE( L a r t i c l e | |
nom | | a pour numero | | num) ;
EXCEPTION
WHENNODATAFOUND THEN
DBMS OUTPUT. PUT LINE( Aucun a r t i c l e ne por t e l e nom
| | nom) ;
WHENTOOMANYROWS THEN
DBMS OUTPUT. PUT LINE( Pl us i e ur s a r t i c l e s por t ent l e nom
| | nom) ;
WHENOTHERS THEN
DBMS OUTPUT. PUT LINE( I l y a un gr os probl`eme . . . ) ;
END;
/
SELECT numprod INTO num... l`eve une exception si la requete renvoie un nombre de lignes dierent de 1.
1.12.3 Codes derreur
Je vous encore menti, certaines exceptions nont pas de nom. Elle ont seulement un code derreur, il est conseille
de se reporter `a la documentation pour les obtenir. On les traite de la facon suivante
EXCEPTION
WHENOTHERS THEN
IF SQLCODE = CODE1 THEN
/ t r ai t ement /
ELSIF SQLCODE = CODE2 THEN
/ t r ai t ement /
ELSE
DBMS OUTPUT. PUT LINE( J voi s pas c que ca
peut e t r e . . . ) ;
END;
Cest souvent le cas lors de violation de contraintes.
1.12.4 Declarer et lancer ses propres exceptions
Exception est un type, on declare donc les exceptions dans une section DECLARE. Une exception se lance avec
linstruction RAISE. Par exemple,
DECLARE
GLUBARF EXCEPTION;
39
BEGIN
RAISE GLUBARF;
EXCEPTION
WHENGLUBARF THEN
DBMS OUTPUT. PUT LINE( gl ubar f r ai s e d . ) ;
END;
/
40
1.13 Sous-programmes
1.13.1 Procedures
Syntaxe
On denit une procedure de la sorte
CREATE OR REPLACE PROCEDURE / nom / ( / paramet res / ) IS
/ de c l ar at i on des v a r i a b l e s l o c a l e s /
BEGIN
/ i ns t r uc t i o ns /
END;
les param`etres sont une simple liste de couples nom type. Par exemple, la procedure suivante ache un compte `a
rebours.
CREATE OR REPLACE PROCEDURE compteARebours ( n NUMBER) IS
BEGIN
IF n >= 0 THEN
DBMS OUTPUT. PUT LINE( n ) ;
compteARebours ( n 1 ) ;
END IF ;
END;
Invocation
En PL/SQL, une procedure sinvoque tout simplement avec son nom. Mais sous SQL+, on doit utiliser le mot-cle
CALL. Par exemple, on invoque le compte `a rebours sous SQL+ avec la commande CALL compteARebours(20).
Passage de param`etres
Oracle permet le passage de param`etres par reference. Il existe trois types de passage de param`etres :
IN : passage par valeur
OUT : aucune valeur passee, sert de valeur de retour
IN OUT : passage de param`etre par reference
Par defaut, le passage de param`etre se fait de type IN.
CREATE OR REPLACE PROCEDURE i nc r ( val IN OUT NUMBER) IS
BEGIN
val := val + 1;
END;
1.13.2 Fonctions
Syntaxe
On cree une nouvelle fonction de la facon suivante :
CREATE OR REPLACE FUNCTION / nom / ( / paramet res / ) RETURN / t ype
/ IS
/ de c l ar at i on des v a r i a b l e s l o c a l e s /
BEGIN
/ i ns t r uc t i o ns /
END;
Linstruction RETURN sert `a retourner une valeur. Par exemple,
CREATE OR REPLACE FUNCTION module ( a NUMBER, b NUMBER) RETURN NUMBER IS
BEGIN
IF a < b THEN
RETURN a ;
ELSE
RETURN module ( a b , b ) ;
41
END IF ;
END;
Invocation
Tout comme les procedures, linvocation des fonctions ne pose aucun probl`eme en PL/SQL, par contre, sous SQL+,
cest quelque peu particulier. On passe par une pseudo-table nommee DUAL de la fa con suivante :
SELECT module ( 21 , 12) FROM DUAL;
Passage de param`etres
Les param`etres sont toujours passes 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 requetes
retourant une et une seule valeur. Ne serait-il pas interessant de pouvoir placer dans des variables le resultat dune
requete retournant plusieurs lignes ? A mediter...
1.14.2 Les curseurs
Un curseur est un objet contenant le resultat dune requete (0, 1 ou plusieurs lignes).
declaration
Un curseur se declare dans une section DECLARE :
CURSOR / nomcurseur / IS / r equet e / ;
Par exemple, si on tient `a recuperer tous les employes de la table EMP, on declare le curseur suivant.
CURSOR emp cur IS
SELECT FROMEMP;
Ouverture
Lors de louverture dun curseur, la requete du curseur est evaluee, et le curseur contient toutes les donnees
retournees par la requete. On ouvre un curseur dans une section BEGIN :
OPEN / nomcurseur / ;
Par exemmple,
DECLARE
CURSOR emp cur IS
SELECT FROMEMP;
BEGIN
OPEN emp cur ;
/ Ut i l i s a t i o n du curseur /
END;
Lecture dune ligne
Une fois ouvert, le curseur contient toutes les lignes du resultat de la requete On les recup`ere une par une en
utilisant le mot-cle FETCH :
FETCH / nom curseur / INTO / l i s t e v a r i a b l e s / ;
La liste de variables peut etre remplacee par une structure de type nom curseur%ROWTYPE. Si la lecture de la ligne
echoue, parce quil ny a plus de ligne `a lire, lattribut %NOTFOUND prend la valeur vrai.
DECLARE
CURSOR emp cur IS
SELECT FROMEMP;
l i g ne emp cur%rowtype
BEGIN
OPEN emp cur ;
LOOP
FETCH emp cur INTO l i g ne ;
EXIT WHEN emp cur%NOTFOUND;
DBMS OUTPUT. PUT LINE( l i g ne . ename ) ;
END LOOP;
/ . . . /
END;
43
Fermeture
Apr`es utilisation, il convient de fermer le curseur.
CLOSE / nomcurseur / ;
Completons notre exemple,
DECLARE
CURSOR emp cur IS
SELECT FROMEMP;
l i g ne emp cur%rowtype ;
BEGIN
OPEN emp cur ;
LOOP
FETCH emp cur INTO l i g ne ;
EXIT WHEN emp cur%NOTFOUND;
DBMS OUTPUT. PUT LINE( l i g ne . ename ) ;
END LOOP;
CLOSE emp cur ;
END;
/
Le programme ci-dessus peut aussi secrire
DECLARE
CURSOR emp cur IS
SELECT FROMEMP;
l i g ne emp cur%rowtype ;
BEGIN
OPEN emp cur ;
FETCH emp cur INTO l i g ne ;
WHILE emp cur%FOUND LOOP
DBMS OUTPUT. PUT LINE( l i g ne . ename ) ;
FETCH emp cur INTO l i g ne ;
END LOOP;
CLOSE emp cur ;
END;
Boucle FOR
Il existe une boucle FOR se chargeant de louverture, de la lecture des lignes du curseur et de sa fermeture,
FOR l i g ne IN emp cur LOOP
/ Trai tement /
END LOOP;
Par exemple,
DECLARE
CURSOR emp cur IS
SELECT FROMEMP;
l i g ne emp cur%rowtype ;
BEGIN
FOR l i g ne IN emp cur LOOP
DBMS OUTPUT. PUT LINE( l i g ne . ename ) ;
END LOOP;
END;
/
44
1.15 Curseurs parametres
1.15.1 Introduction
A votre avis, le code suivant est-il valide ?
DECLARE
NUMBER n := 14;
BEGIN
DECLARE
CURSOR C IS
SELECT
FROM PERSONNE
WHERE numpers >= n ;
ROW C%rowType ;
BEGIN
FOR ROW IN C LOOP
DBMS OUTPUT. PUT LINE(ROW. numpers ) ;
END LOOP;
END;
END;
/
Reponse : non. La requete dun curseur ne peut pas contenir de variables dont les valeurs ne sont pas xees.
Pourquoi ? Parce que les valeurs des ces sont susceptibles de changer entre la declaration du curseur et son ouverture.
Le rem`ede est un curseur parametre.
1.15.2 Denition
Un curseur parametre est un curseur dont la requete contient des variables dont les valeurs ne seront xees qu`a
louverture.
1.15.3 Declaration
On precise la liste des noms et des type des param`etres entre parenth`eses apr`es le nom du curseur :
CURSOR / nom / ( / l i s t e des param`et res / ) IS
/ r equet e /
Par exemple, creeons une requete qui, pour une personne donnee, nous donne la liste des noms et prenoms de ses
enfants :
CURSOR enf ant s ( numparent NUMBER) IS
SELECT
FROM PERSONNE
WHERE pere = numparent
OR mere = numparent ;
1.15.4 Ouverture
On ouvre un curseur parametre en passant en param`etre les valeurs des variables :
OPEN / nom / ( / l i s t e des param`et res / )
Par exemple,
OPEN enf ant s ( 1 ) ;
1.15.5 Lecture dune ligne, fermeture
la lecture dune ligne suit les memes r`egles quavec un curseur non parametre.
45
1.15.6 Boucle pour
La boucle pour se charge de louverture, il convient donc de placer les param`etre dans lentete de la boucle,
FOR / v a r i a b l e / IN / nom / ( / l i s t e param`et res / ) LOOP
/ i ns t r uc t i o ns /
END LOOP;
Par exemple,
FOR e IN enf ant s ( 1) LOOP
DBMS OUTPUT. PUT LINE( e . nompers | | | | e . prenompers ) ;
END LOOP;
1.15.7 Exemple recapitulatif
DECLARE
CURSOR parent IS
SELECT
FROM PERSONNE;
p parent%rowtype ;
CURSOR enf ant s ( numparent NUMBER) IS
SELECT
FROM PERSONNE
WHERE pere = numparent
OR mere = numparent ;
e enf ant s%rowtype ;
BEGIN
FOR p IN parent LOOP
DBMS OUTPUT. PUT LINE( Les enf ant s de | | p . prenom | |
| | p . nom | | sont : ) ;
FOR e IN enf ant 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 procedure stockee qui se lance automatiquement lorsquun evenement se produit. Par evenement,
on entend dans ce cours toute modication des donnees se trouvant dans les tables. On sen sert pour controler ou
appliquer des contraintes quil est impossible de formuler de facon declarative.
1.16.2 Classication
Type devenement
Lors de la creation dun trigger, il convient de preciser quel est le type devenement qui le declenche. Nous realiserons
dans ce cours des triggers pour les evenements suivants :
INSERT
DELETE
UPDATE
Moment de lexecution
On precise aussi si le trigger doit etre execute avant (BEFORE) ou apr`es (AFTER) levenement.
Evenements non atomiques
Lors que lon fait un DELETE ..., il y a une seule instruction, mais plusieurs lignes sont aectees. Le trigger doit-il
etre execute pour chaque ligne aectee (FOR EACH ROW), ou seulement une fois pour toute linstruction (STATEMENT) ?
un FOR EACH ROW TRIGGER est execute `a chaque fois quune ligne est aectee.
un STATEMENT TRIGGER est executee `a chaque fois quune instruction est lancee.
1.16.3 Creation
Syntaxe
On declare un trigger avec linstruction suivante :
CREATE OR REPLACE TRIGGER nomtri gger
[BEFORE | AFTER] [INSERT | DELETE | UPDATE] ON nomtable
[FOR EACH ROW | ]
DECLARE
/ de c l ar at i ons /
BEGIN
/ i ns t r uc t i o ns /
END;
Par exemple,
SQL> CREATE OR REPLACE TRIGGER pasDeDel eteDansCl i ent
2 BEFORE DELETE ON CLIENT
3 BEGIN
4 RAISE APPLICATION ERROR( 20555 , Va t e f a i r e . . . ) ;
5 END;
6 /
Decl encheur c ree .
SQL> SELECT COUNT( )
2 FROM CLIENT;
COUNT( )

21
SQL> DELETEFROM CLIENT;
47
DELETEFROM CLIENT

ERREUR `a l a l i g ne 1 :
ORA20555: Va t e f a i r e . . .
ORA06512: `a SCOTT. PASDEDELETEDANSCLIENT , l i g ne 2
ORA04088: e r r e ur l o r s d execut i on du decl encheur SCOTT. PASDEDELETEDANSCLIENT
SQL> SELECT COUNT( )
2 FROM CLIENT;
COUNT( )

21
Linstruction RAISE APPLICATION ERROR(code, message) l`eve une exception sans nom portant un code code et
un message derreur message. Vous remarquez que comme lerreur a ete levee avant la suppression, les donnees sont
toujours presentes dans la table CLIENT. Le trigger a controle une r`egle, et comme elle netait pas respectee, il a lance
une erreur.
Combinaisons devenements
Il est possible, en separant les types devenement par le mot-cle OR, de denir un trigger declenche par plusieurs
evenements. Les variables booleennes INSERTING, UPDATING et DELETING permettent didentier levenement qui a
declenche le trigger.
CREATE OR REPLACE TRIGGER af f i cheEvenement
BEFORE INSERT ORUPDATE OR DELETE ON CLIENT
FOR EACH ROW
BEGIN
IF INSERTING THEN
DBMS OUTPUT. PUT LINE( I ns e r t i o n dans CLIENT ) ;
ELSIF UPDATING THEN
DBMS OUTPUT. PUT LINE( Mise a j our dans CLIENT ) ;
ELSE
DBMS OUTPUT. PUT LINE( Suppr es s i on dans CLIENT ) ;
END IF ;
END;
1.16.4 Acc`es aux lignes en cours de modication
Dans les FOR EACH ROW triggers, il est possible avant la modication de chaque ligne, de lire lancienne ligne et la
nouvelle ligne par lintermediaire des deux variables structurees :old et :new. Par exemple le trigger suivant empeche
de diminuer un salaire :
CREATE OR REPLACE TRIGGER pasDeBai ss eDeSal ai re
BEFORE UPDATEON EMP
FOR EACH ROW
BEGIN
IF ( : ol d . s a l > : new. s a l ) THEN
RAISE APPLICATION ERROR( 20567 ,
Pas de bai s s e de s a l a i r e ! ) ;
END IF ;
END;
Tables en mutation
Il est impossible, dans un trigger de type FOR EACH ROW de faire un SELECT sur la table en cours de modication.
SQL> CREATE OR REPLACE TRIGGER bef oreStatement
2 BEFORE UPDATEON CLIENT
48
3 DECLARE
4 NB NUMBER;
5 BEGIN
6 SELECT COUNT( ) INTO NB
7 FROM CLIENT;
8 END;
9 /
Decl encheur c ree .
SQL>
SQL> CREATE OR REPLACE TRIGGER af t er St at ement
2 AFTER UPDATEON CLIENT
3 DECLARE
4 NB NUMBER;
5 BEGIN
6 SELECT COUNT( ) INTO NB
7 FROM CLIENT;
8 END;
9 /
Decl encheur c ree .
SQL>
SQL> UPDATE CLIENT SET nomcl i = nomcl i ;
21 l i g ne ( s ) mi se ( s ) `a j our .
SQL>
SQL> CREATE OR REPLACE TRIGGER beforeForEachRow
2 BEFORE UPDATEON CLIENT
3 FOR EACH ROW
4 DECLARE
5 NB NUMBER;
6 BEGIN
7 SELECT COUNT( ) INTO NB
8 FROM CLIENT;
9 END;
10 /
Decl encheur c ree .
SQL>
SQL> UPDATE CLIENT SET nomcl i = nomcl i ;
UPDATE CLIENT SET nomcl i = nomcl i

ERREUR `a l a l i g ne 1 :
ORA04091: l a table SCOTT. CLIENT e s t en mutati on ; l e decl encheur ou l a
f onc t i on ne peut l a voi r
ORA06512: `a SCOTT.BEFOREFOREACHROW , l i g ne 4
ORA04088: e r r e ur l o r s d execut i on du decl encheur SCOTT.BEFOREFOREACHROW
SQL> DROP TRIGGER beforeForEachRow ;
Decl encheur suppri me .
SQL>
SQL>
49
SQL> CREATE OR REPLACE TRIGGER afterForEachRow
2 AFTER UPDATEON CLIENT
3 FOR EACH ROW
4 DECLARE
5 NB NUMBER;
6 BEGIN
7 SELECT COUNT( ) INTO NB
8 FROM CLIENT;
9 END;
10 /
Decl encheur c ree .
SQL>
SQL> UPDATE CLIENT SET nomcl i = nomcl i ;
UPDATE CLIENT SET nomcl i = nomcl i

ERREUR `a l a l i g ne 1 :
ORA04091: l a table SCOTT. CLIENT e s t en mutati on ; l e decl encheur ou l a
f onc t i on ne peut l a voi r
ORA06512: `a SCOTT.AFTERFOREACHROW , l i g ne 4
ORA04088: e r r e ur l o r s d execut i on du decl encheur SCOTT.AFTERFOREACHROW
1.16.5 Contourner le probl`eme des tables en mutation
Il existe plusieurs facons de contourner ce probl`eme :
Utiliser un STATEMENT trigger. Comme on ne sait pas quelles lignes ont ete modiees, on est oblige de toutes
les traiter. Cette approche presente donc un inconvenient majeur : elle nous am`ene `a eectuer de nombreux
traitements inutiles.
En ayant des donnees redondantes. Il sut que les donnees servant `a la verication se trouvent dans une autre
table que celle en mutation. Cette methode a pour inconvenient la memoire occupee et la quantite de code `a ecrire
pour maintenir la coherence des donnees. Dans la plupart des cas, cette solution est malgre tout la meilleure.
Colonnes supplementaires
Par exemple, si lon souhaite empecher un client davoir plus de 10 comptes en banque, une solution est de placer
dans la table client une colonne contenant le nombre de comptes.
ALTER TABLE CLIENT ADD nbComptes number;
UPDATE CLIENT SET nbComptes = 0;
Une fois cette table cree, il convient de sassurer que les donnees de la colonne nbComptes contient toujours les
bonnes valeurs. On le fait avec plusieurs sous-programmes :
CREATE OR REPLACE TRIGGER metAJourNbComptes
AFTER INSERT ORUPDATE OR DELETE ON COMPTECLIENT
BEGIN
UPDATE CLIENT SET nbComptes =
(
SELECT COUNT( )
FROM COMPTECLIENT CC
WHERE CC. numCli = numCli
) ;
END;
/
CREATE OR REPLACE TRIGGER veri f i eNbComptes
BEFORE INSERT ON COMPTECLIENT
FOR EACH ROW
DECLARE
nbComptes NUMBER;
50
BEGIN
SELECT nbComptes INTO nbComptes
FROM CLIENT
WHERE numCli = : new. numcl i ;
IF ( nbComptes >= 10) THEN
RAISE APPLICATION ERROR( 20556 ,
Ce c l i e n t a dej a trop de comptes ) ;
END IF ;
END;
/
On peut aner en remplacant metAJourNbComptes par plusieurs sous-programmes :
CREATE OR REPLACE TRIGGER i ni t i al i s eNbCompt es
BEFORE INSERT ON CLIENT
FOR EACH ROW
BEGIN
: new. nbComptes := 0;
END;
/
CREATE OR REPLACE TRIGGER metAJourNbComptes
AFTER INSERT ORUPDATE OR DELETE ON COMPTECLIENT
FOR EACH ROW
BEGIN
IF DELETING OR UPDATING THEN
UPDATE CLIENT SET nbComptes = nbComptes 1
WHERE numcl i = : ol d . numcl i ;
END IF ;
IF INSERTING OR UPDATING THEN
UPDATE CLIENT SET nbComptes = nbComptes + 1
WHERE numcl i = : new. numcl i ;
END IF ;
END;
/
Tables supplementaires
Si lon souhaite par exemple empecher les circuits dans la table PERSONNE, il est necessaire de faire un parcours
de graphe. Ce qui necessite des SELECT dans la table en cours de mutation. La seule solution est dans ce cas davoir
une table miroir qui contient les colonnes cles primaire et etrang`eres de cette table, et de sen servir pour detecter les
circuits.
CREATE TABLE MIRRORPERSONNE
(
numpers NUMBERPRIMARY KEY,
pere NUMBER,
mere NUMBER
) ;
Nous allons ensuite proceder de meme, en repercutant chaque operation de PERSONNE sur MIRRORPERSONNE.
CREATE OR REPLACE TRIGGER mi seAJourMi rrorPersonne
BEFORE UPDATE OR INSERT OR DELETE ON PERSONNE
FOR EACH ROW
BEGIN
IF DELETING OR UPDATING THEN
DELETEFROM MIRRORPERSONNE
WHERE numpers = : ol 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 sut de rechercher si une personne inseree est une descendante delle meme dans MIRRORPERSONNE.
CREATE OR REPLACE FUNCTION t r ouve Ci r c ui t ( cur r ent NUMBER, toFi nd NUMBER)
RETURN BOOLEAN IS
numPere NUMBER;
numMere NUMBER;
BEGIN
IF ( cur r ent IS NULL) THEN
RETURN FALSE;
END IF ;
SELECT pere , mere INTO numPere , numMere
FROM MIRRORPERSONNE
WHERE numPers = cur r ent ;
RETURN ( numPere = toFi nd OR numMere = toFi nd OR
t r ouve Ci r c ui t ( numPere , toFi nd ) OR
t r ouve Ci r c ui t (numMere , toFi nd ) ) ;
END;
/
CREATE OR REPLACE TRIGGER v e r i f i e Ci r c u i t
AFTER UPDATE OR INSERT ON PERSONNE
FOR EACH ROW
BEGIN
IF ( t r ouve Ci r c ui t ( : new. numPers , : new. numPers ) ) THEN
RAISE APPLICATION ERROR( 20557 ,
Ci r c ui t dans l ar br e geneal ogi que . ) ;
END IF ;
END;
/
52
1.17 Packages
1.17.1 Principe
Un package est un ensemble de sous-programmes et de variables forme par
Une specication : declaration de variables et de sous-programmes
Un corps : implementation des sous-programmes
Tout ce qui se trouve dans la specication doit se trouver dans le corps, mais la reciproque est fausse. Un package
satisfait les points suivants :
encapsulation : certains traitements sont masques, seule la specication du package est visible. Cela a pour
avantage de simplier la tache de celui qui va utiliser le package.
modularite : il est possible de developper separement les diverses parties de lapplication. le developpement
devient ainsi un assemblage de package.
Ces deux aspects fournissent une souplesse certaine au niveau du developpement : il est possible de modier le
corps dun package sans changer sa specication, donc sans modier le fonctionnement de lapplication.
1.17.2 Specication
La syntaxe permettant de creer lentete est la suivante :
CREATE OR REPLACE PACKAGE nompackage IS
/
de c l ar at i ons
/
END nomPackage ;
/
Par exemple,
CREATE OR REPLACE PACKAGE compteur IS
procedure r e s e t ;
f unc t i on nextVal ue r et ur n number;
END compteur ;
/
1.17.3 Corps
La syntaxe permettant de creer le corps est la suivante :
CREATE OR REPLACE PACKAGE BODY nompackage IS
/
i mpl ement at i on
/
END nomPackage ;
/
Par exemple,
CREATE OR REPLACE PACKAGE BODY compteur IS
cpt NUMBER := 0;
PROCEDURE r e s e t IS
BEGIN
cpt := 0;
END;
FUNCTION nextVal ue RETURN NUMBER IS
BEGIN
cpt := cpt + 1;
RETURN cpt 1;
END;
END compteur ;
/
53
On peut utiliser un package depuis nimporte quel script PL/SQL :
DECLARE
nb NUMBER;
BEGIN
FOR nb IN 4 . . 2 0 LOOP
DBMS OUTPUT. PUT LINE(COMPTEUR. nextVal ue ( ) ) ;
END LOOP;
COMPTEUR. RESET( ) ;
FOR nb IN REVERSE 0 . . 1 0 LOOP
DBMS OUTPUT. PUT LINE(COMPTEUR. nextVal ue ( ) ) ;
END LOOP;
END;
/
54
Chapitre 2
Exercices
2.1 Contraintes declaratives
Nous nous proposons de modier le script de creation de table de lannexe A.1.
Exercice 1
Modiez le script de facon `a ce que les saisies des valeurs suivantes soit obligatoire :
Le prix des articles proposes
La quantite des produits livres
Exercice 2
Reperez les colonnes, couples de colonnes, voire triplets de colonnes, `a choisir comme cles primaires. Modiez le
script de fa con `a ce que cela se fasse.
Exercice 3
Faites de meme pour les cles etrang`eres, sans oublier quil ne peut gurer dans une livraison que des produits
proposes par le fournisseur qui eectue cette livraison.
Exercice 4
Inserez quelques lignes dans chaque table.
Exercice 5
Reperez toutes les contraintes des questions precedentes dans user constraints, supprimez-les.
Exercice 6
Redenissez toutes ces contraintes avec la syntaxe ALTER TABLE
55
2.2 Introduction aux requetes
Nous souhaitons gerer un secretatiat pedagogique avec la base de A.2.
Les sorties generees par les deux premi`eres questions sont donnees. Apr`es, ca sera `a vous de verier si les resultats
de vos requetes est coherent ou non.
Exercice 1
Acher la liste des noms des modules.
Oracle
C++
C
Algo
Merise
PL/SQL Oracle
mySQL
Algo avance
8 ligne(s) selectionnee(s).
Exercice 2
Acher la liste des numeros des modules prerequis pour dautres modules.
1
3
5
3 ligne(s) selectionnee(s).
Exercice 3
En utilisant le resultat de la requete precedente, et loperateur IN, achez les noms de ces trois modules.
Exercice 4
Augmentez les notesMin necessaires pour sinscrire en Algo avance de deux points. Celles necessaires pour aller
en PL/SQL Oracle dun point.
Exercice 5
Achez, par ordre de noteMin croissantes, les numeros des modules necessaires pour acceder au module PL/SQL
Oracle.
Exercice 6
Achez les numeros des modules dans lequels je ne peux pas minscrire avec 10 en merise.
Exercice 7
Achez les noms de tous les modules dont le libelle 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 species par les coordonnees de deux sommets diametralement opposes,
leurs aretes sont parall`eles aux axes. Certains rectangles ont des coordonnees erronnees, cest-`a dire que soit ils sont des
segments, soit les coordonnees de certains points ne sont pas dans le bon ordre. Supprimez, avec une seule instruction,
tous les rectangles-segments.
Exercice 10
Achez tous les intervalles contenant la valeur 10.
Exercice 11
Acher 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` u les valeurs des coordonnees font que lon na pas un
point en haut `a gauche et un en bas `a droite. Acher `a ces rectangles.
Exercice 13
Certains rectangles mal denis peuvent etre repares 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 coordonnees (x, y) = (2, 2), acher les coordonnees des rectangles qui contiennent ce point.
Exercice 15
Acher 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 donees de A.4.
Exercice 1
Acher tous les noms des produits dont le numero a une occurence dans la table PROPOSER.
NOMPROD
------------------------------
Cotons tiges
Poupee Batman
Roue de secours
Exercice 2
Acher tous les noms des fournisseurs dont le numero a une occurence dans la table PROPOSER.
NOMFOU
------------------------------
f1
f2
f3
Exercice 3
Acher les noms des fournisseurs avec pour chaque fournisseur la liste des produits proposes.
NOMFOU NOMPROD
------------------------------ ------------------------------
f1 Roue de secours
f1 Poupee Batman
f2 Poupee Batman
f3 Cotons tiges
Exercice 4
Acher les nom des fournisseurs proposant des Poupees Batman par ordre de prix croissant.
Exercice 5
Acher les dates des livraisons eectuees par le fournisseur f1 ;
Exercice 6
Acher les noms de tous les produits dej`a livres par le fournisseur f3 ;
Exercice 7
Acher toutes les lignes de la table LIVRAISON correspondant `a des livraisons dans lesquelles gure le produit
Poupee Batman.
Exercice 8
Pour les exercices suivants, nous travaillerons sur les donnees de A.5. Dans les questions o` u il vous est demande de
formuler des requetes retournant plusieurs personnes, il faut quil y ait une ligne par personne. Acher les noms et
prenoms des enfants de Soa Kobalevskaa.
NOM PRENOM
------------------------------ ------------------------------
Leibniz Gottfried Wilhem
Bach Johann Sebastien
58
Exercice 9
Acher les noms et prenoms des parents de Edvard Dijkstra.
NOM PRENOM
------------------------------ ------------------------------
Jacqou Le Croquant
Granger Hermione
Exercice 10
Acher les noms et prenoms des enfants de jean-Sebastien Bach et Mireille Mathieu.
Exercice 11
Acher les noms et prenoms du fr`ere de Jacqouille la Fripouille.
Exercice 12
Acher les noms et prenoms du cousin germain de Dijkstra du cote de son p`ere.
Exercice 13
Acher les noms et prenoms du demi-fr`ere (du cote de sa m`ere) du p`ere de Lara Fabian.
Exercice 14
Acher les noms et prenoms des p`eres des enfants de Kate Bush.
Exercice 15
Acher les noms et prenoms du neveu de Jacqou le Croquant.
Exercice 16
Acher les noms et prenoms de la m`ere du ls du ls dAndre Rieu.
Exercice 17
Acher les noms et prenoms 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) selectionnee(s).
Noubliez pas : une ligne par personne.
59
2.4 Agregation de donnees
Nous utiliserons les donnees de A.4. Il est demande dans chaque exercice de formuler une requete.
Exercice 1
Donner le nombre de fournisseurs.
Exercice 2
Donner le nombre de fournisseurs ayant dej`a eectue une livraison.
Exercice 3
Quel est le prix du produit propose au prix le plus eleve par f1 ?
Exercice 4
Combien de produits sont proposes pour chaque fournisseur proposant au moins un produit ?
Exercice 5
Acher le nombre de produits qui ne sont proposes par aucun fournisseur.
Exercice 6
Acher, pour chaque produit (dont on achera le nom), le nombre de fournisseurs layant dej`a livre.
Exercice 7
Donner pour chaque livraison le nom du fournisseur, le numero de livraison et le nombre de produits livres.
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 proposes que par un seul fournisseur.
Exercice 10
Donner les noms des fournisseurs qui ont livre au moins une fois chaque produit quils proposent.
60
2.5 Vues
Nous utiliserons les donnees de A.4. Nhesitez pas, pour tester vos requetes et `a inserer dautres donnees dans la
base.
Exercice 1
Creez une vue achant pour chaque produit ayant dej`a ete livre le numero du produit et la somme des quantites
livrees (toutes livraisons confondues).
Exercice 2
Achez la quantite totale livree du produit dont la quantite totale livree est la plus elevee.
Exercice 3
Creez une vue achant pour chaque livraison, le montant de la facture.
Exercice 4
Creez une vue achant pour chaque fournisseur, le total des factures sur toutes les livraisons.
Exercice 5
Achez le total des factures du fournisseurs dont le total des factures est le moins eleve.
Exercice 6
Achez le nombre de produits distincts livres par le fournisseur ayant livre le plus de produits distincts. Par nombre
de produits distincts, on entend sans tenir compte de la quantite.
61
2.6 Requetes imbriquees
Nous utiliserons les donnees de A.4. Presque tous les stratag`emes sont autorises, vous pouvez utiliser des fonctions
dagregation, des vues, et des requetes imbriquees. Bon courage, laspirine nest pas fournie.
Exercice 1
Donner, pour chaque fournisseur (acher son nom), le nombre de produits proposes, meme si ce fournisseur nen
propose aucun. Il est interdit dutiliser OUTER JOIN !
Exercice 2
Acher les noms des fournisseurs qui proposent le produit numero 2, il est interdit de faire des jointures !
Exercice 3
Acher les noms des fournisseurs qui proposent des poupees Batman.
Exercice 4
Acher les noms des fournisseurs qui ont dej` a livre des poupees Batman.
Exercice 5
Quels sont les noms des fournisseurs qui ont dej`a livre tous leurs produits au moins une fois ?
Exercice 6
Donner, pour chaque fournisseur (acher son nom), le produit propose au prix le plus eleve.
Exercice 7
Pour chaque produit p, quel sont les noms des fournisseurs qui, sur toutes ses livraisons, ont livre la plus grande
quantite cumulee de produits p.
Exercice 8
Acher le nombre de produits proposes par les fournisseurs proposant le moins de produits. Normalement, un 0
devrait sacher... Pas un 1.
Exercice 9
Acher le(s) nom(s) du(des) fournisseur(s) proposant le moins de produits.
Exercice 10
Acher, pour chaque produit, le(s) nom(s) du(des) fournisseur(s) qui la(ont) le plus livre (en quantite cumulee).
62
2.7 Complements sur les types
Vous modierez pour faire ces exercices le script de creation de tables de A.4.
Exercice 1
Rendez, `a laide de contraintes de type CHECK les saisies des champs qte, prix et dateli oligatoires.
Exercice 2
Empechez la saisie de prix negatifs ou nuls et de quantites negatives ou nulles.
Exercice 3
On sait que la base a ete creee vers le mois dOctobre 2006, empechez lajout de livraisons anterieures `a ce mois.
Exercice 4
Implementez une contrainte declarative empechant les livraisons les premiers mai de chaque annee.
Exercice 5
Implementez une contrainte declarative obligeant les noms des produits `a commencer par une majuscule et `a ne
comporter ensuite sur des minuscules. Si lajout dune des contraintes est refusee, demandez vous pourquoi et faites le
necessaire (une commande UPDATE sera la bienvenue...) pour y remedier.
63
2.8 Revisions
Nous utiliserons les donnees de A.4.
Exercice 1
Donner le nombre de fournisseurs ayant eectue un nombre de livraisons superieur au egal `a deux.
Exercice 2
Quelles sont les annees pendant lesquelles le plus de livraisons ont ete eectuees ?
Exercice 3
Parmi les fournisseurs qui ont livre au moins une fois chaque produit quils proposent, quels sont les derniers `a
avoir eectue une livraison.
64
2.9 Introduction au PL/SQL
Exercice 1
Ecrivez un programme aectant les valeurs 1 et 2 `a deux variables a et b, puis permutant les valeurs de ces deux
variables.
Exercice 2
Ecrivez un programme placant la valeur 10 dans une variable a, puis achant la factorielle de a.
Exercice 3
Ecrivez un programme placant les valeurs 48 et 84 dans deux variables a et b puis achant le pgcd de a et b.
65
2.10 Tableaux et Structures
Exercice 1
1. Creez un type tableau pouvant contenir jusqu`a 50 entiers.
2. Creez une variable de ce type , faites une allocation dynamique et dimensionnez ce tableau `a 20 emplacements.
3. Placez dans ce tableau la liste des 20 premiers carres parfaits : 1, 4, 9, 16, 25, . . .
4. Inversez lordre des elements du tableau
5. Achez le tableau.
Exercice 2
Triez le tableau precedent avec la methode du tri `a bulle.
Exercice 3
Recherchez, par dichotomie, si lelement 225 se trouve dans le tableau.
Exercice 4
On implemente des listes chanees avec des tableaux de la sorte,
SET SERVEROUTPUT ON
DECLARE
-- Maillon dune liste cha^nee
TYPE CELL IS RECORD
(
-- Donnee de chaque maillon
data INTEGER,
-- Indice du maillon precedent de la liste,
-- -1 sil ny en a pas
previous INTEGER,
-- Indice du maillon suivant de la liste,
-- -1 sil ny en a pas
next INTEGER
);
-- Type tableau contenant les maillons de la liste
TYPE TREE IS VARRAY (19) OF CELL;
-- Tableau contenant les maillons de la liste
t TREE;
-- indice du premier element de la liste
first integer;
-- indice du dernier element 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 lordre des elements de la liste, sans changer les indices des maillons (seulement en modiant le chanage).
Exercice 5
Utilisez le tri `a bulle pour remettre les elements dans lordre. Les indications sont les memes : ne deplacez pas les
maillons, vous navez le droit de toucher quau chanage. Bon courage, laspirine nest pas fournie.
67
2.11 Utilisation PL/SQL
Nous travaillerons sur les donnees A.6 et A.5.
Vous noublierez pas de placer des commit en des lieux bien choisis.
Exercice 1
Vous remarquerez que les valeurs des numpers de la table PERSONNE forment une sequence de nombres de 1 `a 21.
Utilisez une boucle dans laquelle vous placerez une requete pour recopier les couples nom/prenom de la table personne
dans la table CLIENT.
Exercice 2
Ecrivez un script recuperant le client de cle primaire la plus elevee, et injectant ce client dans la table PERSONNEL.
Exercice 3
Ouvrez un compte courant pour chaque personne, eectuez un depot en esp`ece egal `a numpers 100 euros.
Exercice 4
Ouvrez un livret pour chaque personne ayant un numpers pair, faites un virement de leur compte courant vers ce
livret de sorte quil ne reste plus que 500 sur leur compte.
68
2.12 Exceptions
Nous utiliserons les donnees de A.7 et A.5
Vous etes invites `a modier le code de la seance precedente. Chaque fois quun SELECT ... INTO ... sera eectue,
vous rattraperez les exceptions NO DATA FOUND et TOO MANY ROWS. A chaque insertion, vous ratrapperez lexception
DUP VAL ON INDEX.
Exercice 1
Faites de sorte que les scripts important les donnees des tables CLIENT ne puissent etre executes quune seule fois.
Exercice 2
Les scripts remplissant la table Operation ne fonctionneront pas aujourdhui... Meme sil fonctionnaient la derni`ere
fois. Trouvez les codes derreurs des exceptions levees par ces scripts, rattrapez-les de la facon la plus appropriee qui
soit.
69
2.13 Sous-programmes
Exercice 1
Ecrire une fonction recursive retournant b
n
, avec n entier positif ou nul.
Exercice 2
Ameliorer la fonction precedente en utilisant le fait que
b
n
= (b
2
)
n
2
si n est pair.
Pour les questions suivantes, utilisez les donnees de A.5.
Exercice 3
Ecrire une fonction demi-freres prenant deux numeros de personnes en param`etre et retournant vrai si et seulement
si ces deux personnes ont un parent en commun.
Exercice 4
Ecrire une fonction cousins germains prenant deux numeros de personnes en param`etre et retournant vrai si et
seulement si ces deux deux individus sont cousins germains.
Exercice 5
Ecrire une procedure recursive achant le nom de la personne dont le numero est passe en param`etre et se rappellant
recursivement sur le p`ere de cette personne. Faites de sorte `a ne pas utiliser dexceptions.
Exercice 6
Ecrire une procedure recursive achant les noms des ascendants de sexe masculin de la personne dont le numero
est passe en param`etre.
Exercice 7
Ecrire une fonction recursive prenant deux numeros de personne A et B et retournant vrai si A est un ascendant
de B.
Exercice 8
Ecrire une fonction prenant en param`etre deux numeros de personne A et B et retournant, si lun est un ascendant
de lautre, le nombre de generations les separant, 1 si lun nest pas un ascendant de lautre.
Exercice 9
Preparez un verre daspirine et ecrivez une requete retournant le(s) couples(s) personnes separees par le plus de
generations.
Exercice 10
Reprendre le code du tp precedent, le decouper en sous-programmes de la fa con 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 achant toute la descendance dune personne.
71
2.15 Curseurs parametres
Linteret de ces exercices etant de vous familiariser avec les curseurs parametres, vous ferez en sorte de ne pas
contourner leur usage. Nous utiliserons les donnees de A.6
Exercice 1
Ecrire une procedure qui ache tous les clients, et pour chaque client, la liste des comptes.
Exercice 2
Ecrire une procedure qui ache tous les clients, et pour chaque client, la liste des comptes, et pour chacun de ces
comptes, lhistorique des operations.
72
2.16 Triggers
Implementez les contraintes suivantes dans les donnees de les donnees de A.8. Vous ferez des sous-programmes
tenant sur une page, et ne contenant pas plus de trois niveaux dimbrication. Vous repertorierez les numeros derreurs
que vous aecterez `a chaque levee dexception.
1. Il ne doit pas etre possible de modier la note min dans la table prerequis.
2. Dans un module, il ne doit pas y avoir plus de effecMax el`eves inscrits.
3. On ne peut creer un examen pour un module que sil y a des el`eves inscrits dans ce module.
4. Un el`eve ne peut passer un examen que si sa date dinscription est anterieure `a la date de lexamen.
5. Il ne doit pas y avoir de circuit dans la table prerequis (il existe une facon de la verier en PL/SQL, mais
comme vous ne la connaissez pas, faites un parcours en profondeur du graphe des pre-requis)
6. Un el`eve sinscrivant `a un module doit avoir eu au moins la note min `a tous les modules pre-requis.
7. Ajouter dans etudiant un champ moyenne, celui-ci contiendra la moyenne de chaque etudiant sil a passe les
examens de tous les modules dans lesquels il est inscrit.
8. Revenez sur la premi`ere contrainte : il ne doit etre possible de modier une note min dans la table prerequis que
sil nexiste pas del`eve dont une inscription serait invalidee.
9. Il ne doit etre possible de modier effecMax que si des etudiants ne se retrouvent pas avec une inscription
invalidee.
Libre `a vous par la suite de trouver dautres contraintes et de les implementer.
73
2.17 Packages
Exercice 1
Lancez deux sessions simultanement sur le meme serveur et invoquez les sous-programmes du package compteur
depuis chacune des sessions. Que remarquez-vous ?
Exercice 2
Implementer le corps du package suivant (utilisez les donnees de A.5).
CREATE OR REPLACE PACKAGE ge s t i on ar br e IS
c i r c u i t exception ;
cur s or f e u i l l e s r et ur n personne%rowtype ;
procedure aj outePersonne (nom personne . nom%type ,
prenom personne . prenom%type , pere personne . pere%type ,
mere personne . mere%type ) ;
procedure modi f i ePar ent s ( per s personne . numpers%type ,
numPere personne . pere%type , numMere personne . mere%type ) ;
END ge s t i on ar br e ;
/
74
2.18 Revisions
Implementez les contraintes suivantes dans les donnees de A.9.
1. Les parents dune meme personne sont des personnes dierentes.
2. Larbre genealogique ne contient pas de circuit.
3. Les dates de divorce sont ulterieures aux dates de mariage.
4. Une meme personne ne peut pas etre mariee `a plusieurs personnes simultanement.
5. Personne ne peut etre p`ere dune personne et m`ere dune autre.
6. Un mari ne peut pas etre m`ere et une femme ne peut pas etre p`ere.
7. Deux personnes ayant du sang en commun ne peuvent se marier.
75
Chapitre 3
Corriges
3.1 Contraintes declaratives
quest i ons 1 , 2 et 3
DROP TABLE DETAILLIVRAISON;
DROP TABLE LIVRAISON;
DROP TABLE PROPOSER;
DROP TABLE PRODUIT;
DROP TABLE FOURNISSEUR;
CREATE TABLE PRODUIT
( numprod number PRIMARY KEY,
nomprod varchar2 ( 3 0 ) ) ;
CREATE TABLE FOURNISSEUR
( numfou number PRIMARY KEY,
nomfou varchar2 ( 3 0 ) ) ;
CREATE TABLE PROPOSER
( numfou number,
numprod number,
pr i x number NOT NULL,
PRIMARYKEY ( numfou , numprod) ,
FOREIGN KEY ( numfou) REFERENCES f o ur ni s s e ur ( numfou ) ,
FOREIGN KEY ( numprod) REFERENCES pr odui t ( numprod ) ) ;
CREATE TABLE LIVRAISON
( numfou number,
numli number,
da t e l i date default sysdate ,
PRIMARYKEY ( numfou , numli ) ,
FOREIGN KEY ( numfou) REFERENCES f o ur ni s s e ur ( numfou ) ) ;
CREATE TABLE DETAILLIVRAISON
( numfou number,
numli number,
numprod number,
qte number NOT NULL,
PRIMARYKEY ( numfou , numli , numprod) ,
FOREIGN KEY ( numfou , numli ) REFERENCES l i v r a i s o n ( numfou , numli ) ,
FOREIGN KEY ( numfou , numprod) REFERENCES pr oposer ( numfou , numprod ) ) ;
quest i on 4
INSERT INTO PRODUIT values ( 1 , Roue de s ecour s ) ;
INSERT INTO PRODUIT values ( 2 , Poupee Batman ) ;
INSERT INTO PRODUIT values ( 3 , Cotons t i g e s ) ;
INSERT INTO PRODUIT values ( 4 , Corni chons ) ;
INSERT INTO FOURNISSEUR values ( 1 , f 1 ) ;
INSERT INTO FOURNISSEUR values ( 2 , f 2 ) ;
INSERT INTO FOURNISSEUR values ( 3 , f 3 ) ;
INSERT INTO FOURNISSEUR values ( 4 , f 4 ) ;
INSERT INTO PROPOSER values ( 1 , 1 , 200) ;
INSERT INTO PROPOSER values ( 1 , 2 , 15) ;
INSERT INTO PROPOSER values ( 2 , 2 , 1 ) ;
INSERT INTO PROPOSER values ( 3 , 3 , 2 ) ;
INSERT INTO LIVRAISON ( numfou , numli ) values ( 1 , 1 ) ;
INSERT INTO LIVRAISON ( numfou , numli ) values ( 1 , 2 ) ;
INSERT INTO LIVRAISON ( numfou , numli ) values ( 3 , 1 ) ;
INSERT INTO DETAILLIVRAISON values ( 3 , 1 , 3 , 10) ;
INSERT INTO DETAILLIVRAISON values ( 1 , 1 , 1 , 25) ;
76
INSERT INTO DETAILLIVRAISON values ( 1 , 1 , 2 , 20) ;
INSERT INTO DETAILLIVRAISON values ( 1 , 2 , 1 , 15) ;
INSERT INTO DETAILLIVRAISON values ( 1 , 2 , 2 , 17) ;
quest i on 5
Le s c r i pt ci dessous va vous af f i c he r l a s ol ut i on .
Vous pouvez proceder de deux f acons :
copi erc o l l e r c e t t e s ol ut i on af f i c he e
par c e t t e se r i e de commandes
set und o f f
set headi ng o f f
set f eed o f f
sel ect a l t e r t abl e | | tabl e name | | drop c ons t r ai nt | |
const r ai nt name | | ; from us e r c o ns t r a i nt s
where tabl e name in
( PRODUIT , FOURNISSEUR , PROPOSER ,
LIVRAISON , DETAILLIVRAISON )
AND c ons t r ai nt t ype IN ( R , P )
ORDER BY c ons t r ai nt t ype DESC ;
set und on
set headi ng on
set f eed on
pl acer ceci dans l e f i c h i e r dp . s q l
et l execut er en s ai s i s s ant @<cheminabsol u>/dp . s q l
set tri mout o f f ;
Set f eed o f f ;
set echo o f f ;
set headi ng o f f ;
set termout o f f ;
set v e r i f y o f f ;
set space 0 ;
SET NEWPAGE 0 ;
SET PAGESIZE 0 ;
s pool dr op c ons t r ai nt s . l s t
sel ect a l t e r t abl e | | tabl e name | | drop c ons t r ai nt | |
const r ai nt name | | ; from us e r c o ns t r a i nt s
where tabl e name in
( PRODUIT , FOURNISSEUR ,
PROPOSER , LIVRAISON , DETAILLIVRAISON )
AND c ons t r ai nt t ype IN ( R , P )
ORDER BY c ons t r ai nt t ype DESC ;
s pool o f f
@dr op cons t r ai nt s . l s t
set tri mout on ;
Set f eed on ;
set echo on ;
set headi ng on ;
set termout on ;
set v e r i f y on;
quest i on 6
al ter table pr odui t add
constraint pk pr odui t
PRIMARYKEY ( numprod ) ;
al ter table f o ur ni s s e ur add
constraint pk f our ni s s e ur
PRIMARYKEY ( numfou ) ;
al ter table pr oposer add
constraint pk pr oposer
PRIMARYKEY ( numfou , numprod ) ;
al ter table l i v r a i s o n add
constraint pk l i vr a i s o n
PRIMARYKEY ( numfou , numli ) ;
al ter table 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
PRIMARYKEY ( numfou , numli , numprod ) ;
al ter table pr oposer add
constraint f k pr o po s e r f o ur ni s s e ur
FOREIGN KEY ( numfou)
REFERENCES f o ur ni s s e ur ( numfou ) ;
al ter table pr oposer add constraint f k pr opos e r pr odui t
FOREIGN KEY ( numprod)
REFERENCES pr odui t ( numprod ) ;
al ter table l i v r a i s o n add constraint f k l i v r a i s o n
FOREIGN KEY ( numfou)
REFERENCES f o ur ni s s e ur ( numfou ) ;
al ter table d e t a i l l i v r a i s o n add constraint 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 ) ;
al ter table d e t a i l l i v r a i s o n add constraint 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 pr oposer ( numfou , numprod ) ;
77
3.2 Introduction aux requetes
Exerci ce 1
SELECT nomMod
FROM MODULE;
Exerci ce 2
SELECT DISTINCT numModPrereq
FROM PREREQUIS
Exerci ce 3
SELECT nomMod
FROM MODULE
WHERE numMod IN ( 1 , 3 , 5 ) ;
Exerci ce 4
SQL> SELECT FROM MODULE WHERE nomMod = Algo avancee ;
NUMMOD NOMMOD

8 Algo avancee
1 l i g ne s e l e c t i o nne e .
SQL> UPDATE pr e r e qui s SET noteMin = 12 WHERE numMod = 8;
SQL> SELECT FROM module WHERE nomMod = PL/SQL Oracl e ;
NUMMOD NOMMOD

6 PL/SQL Oracl e
1 l i g ne s e l e c t i o nne e .
SQL> UPDATE pr e r e qui s SET noteMin = 11 WHERE numMod = 6;
Exerci ce 5
SELECT numModPrereq , noteMin
FROM PREREQUIS
WHERE numMod = 6
ORDER BY noteMin ;
Exerci ce 6
SELECT numMod
FROM pr e r e qui s
WHERE numModPrereq = 5
AND noteMin > 10;
Exerci ce 7
SELECT nomMod
FROM module
WHERE nomMod LIKE %Algo%
OR nomMod LIKE %SQL% ;
Exerci ce 8
DELETE FROM i n t e r v a l l e
WHERE borneSup < bor neI nf ;
Exerci ce 9
DELETE FROM r e c t angl e
WHERE xHautGauche = xBasDroi t
OR yHautGauche = yBasDroi t ;
Exerci ce 10
SELECT
FROM i n t e r v a l l e
WHERE 10 BETWEEN bor neI nf AND borneSup ;
Exerci ce 11
SELECT
FROM i n t e r v a l l e
WHERE bor neI nf <= 5 AND borneSup >= 7;
SELECT
FROM i n t e r v a l l e
WHERE bor neI nf >= 5 AND borneSup <= 35;
SELECT
78
FROM i n t e r v a l l e
WHERE (15 BETWEEN bor neI nf AND borneSup )
OR (20 BETWEEN bor neI nf AND borneSup )
OR ( bor neI nf BETWEEN 15 AND 20) ;
Exerci ce 12
SELECT
FROM r e c t angl e
WHERE ( xHautGauche > xBasDroi t )
OR ( yHautGauche < yBasDroi t ) ;
Exerci ce 13
UPDATE r e c t angl e SET
xHautGauche = xBasDroi t ,
xBasDroi t = xHautGauche
WHERE xHautGauche > xBasDroi t ;
UPDATE r e c t angl e SET
yHautGauche = yBasDroi t ,
yBasDroi t = yHautGauche
WHERE yHautGauche < yBasDroi t ;
Exerci ce 14
SELECT
FROM r e c t angl e
WHERE (2 BETWEEN xHautGauche AND xBasDroi t )
AND (2 BETWEEN yBasDroi t AND yHautGauche ) ;
79
3.3 Jointures
Exerci ce 1
SELECT di sti nct nomprod
FROM produi t , pr oposer
WHERE pr odui t . numprod = pr oposer . numprod ;
Exerci ce 2
SELECT di sti nct nomfou
FROM f o ur ni s s e ur f , pr oposer p
WHERE f . numfou = p . numfou ;
Exerci ce 3
SELECT nomfou , nomprod
FROM f o ur ni s s e ur f , pr odui t p , pr oposer pr
WHERE f . numfou = pr . numfou
AND pr . numprod = p . numprod ;
Exerci ce 4
SELECT nomfou , pr i x
FROM f o ur ni s s e ur f , pr odui t p , pr oposer pr
WHERE f . numfou = pr . numfou
AND pr . numprod = p . numprod
AND nomProd = Poupee Batman
ORDER BY pr i x ;
Exerci ce 5
SELECT da t e l i
FROM l i v r a i s o n l , f o ur ni s s e ur f
WHERE l . numfou = f . numfou
AND f . nomFou = f 1 ;
Exerci ce 6
SELECT nomprod
FROM f o ur ni s s e ur f , pr odui t p , d e t a i l l i v r a i s o n d , l i v r a i s o n 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 da t e l i < s ys dat e ;
Exerci ce 7
SELECT l . numfou , l . numli , da t e l i
FROM pr odui t p , l i v r a i s o n l , d e t a i l l i v r a i s o n d
WHERE p . numprod = d . numprod
AND l . numfou = d . numfou
AND l . numli = d . numli
AND p . nomprod = Poupee Batman ;
Exerci ce 8
SELECT enf . nom, enf . prenom
FROM personne s f , personne enf
WHERE enf . mere = s f . numpers
AND s f . prenom = Sof i a ;
Exerci ce 9
SELECT par . nom, par . prenom
FROM personne ed , personne par
WHERE ( ed . pere = par . numpers OR ed . mere = par . numpers )
AND ed . nom = Di j ks t r a ;
Exerci ce 10
SELECT e . nom, e . prenom
FROM personne e , personne p , personne m
WHERE e . pere = p . numpers
AND e . mere = m. numpers
AND p . nom = Bach
AND m. nom = Mathieu ;
Exerci ce 11
SELECT f . nom, f . prenom
FROM personne f , personne j
WHERE f . pere = j . pere
AND f . mere = j . mere
AND j . nom = La Fr i po ui l l e
AND j . nom <> f . nom;
80
Exerci ce 12
SELECT c . nom, c . prenom
FROM personne c , personne o , personne p , personne d
WHERE d . nom = Di j ks t r a
AND d . pere = p . numpers
AND p . pere = o . pere
AND p . mere = o . mere
AND p . numpers <> o . numpers
AND c . pere = o . numpers ;
Exerci ce 13
SELECT dm. nom, dm. prenom
FROM personne dm, personne l f , personne p
WHERE l f . nom = Fabian
AND p . numpers = l f . pere
AND p . mere = dm. mere
AND p . numpers <> dm. numpers ;
Exerci ce 14
SELECT p . nom, p . prenom
FROM personne p , personne kb , personne enf
WHERE kb . nom = Bush
AND enf . mere = kb . numpers
AND enf . pere = p . numpers ;
Exerci ce 15
SELECT nev . nom, nev . prenom
FROM personne nev , personne j l c , personne f r
WHERE j l c . prenom = Jacqou
AND f r . pere = j l c . pere
AND f r . mere = j l c . mere
AND f r . numpers <> j l c . numpers
ANd ( nev . pere = f r . numpers OR nev . mere = f r . numpers ) ;
Exerci ce 16
SELECT m. nom, m. prenom
FROM personne ar , personne f , personne m
WHERE f . pere = ar . numpers
AND ar . nom = Rieu
AND f . mere = m. numpers ;
Exerci ce 17
SELECT DISTINCT gp . nom, gp . prenom
FROM personne sh , personne p , personne gp
WHERE sh . nom = Stone
AND (
( sh . pere = gp . numpers )
OR ( sh . mere = gp . numpers )
OR (
( sh . mere = p . numpers OR sh . pere = p . numpers )
AND ( p . mere = gp . numpers OR p . pere = gp . numpers )
)
) ;
81
3.4 Agregation de donnees
Exerci ce 1
SELECT COUNT( )
FROM FOURNISSEUR;
Exerci ce 2
SELECT COUNT(DISTINCT NUMFOU)
FROM LIVRAISON;
Exerci ce 3
SELECT MAX( pr i x ) AS PRIX MAX
FROM PROPOSER PR, FOURNISSEUR F
WHERE F. numfou = PR. numfou
AND nomfou = f 1 ;
Exerci ce 4
SELECT nomfou , count (DISTINCT numprod) AS NB PROD PROPOSES
FROM FOURNISSEUR F, PROPOSER P
WHERE F. numfou = P. numfou
GROUP BY nomfou ;
Exerci ce 5
SELECT COUNT(DISTINCT P. numprod) count (DISTINCT PR. numprod)
FROM PRODUIT P, PROPOSER PR;
Exerci ce 6
SELECT nomprod , COUNT(DISTINCT D. numfou)
FROM PRODUIT P, DETAILLIVRAISON D
WHERE P. numprod = D. numprod
GROUP BY nomprod ;
Exerci ce 7
SELECT nomfou , L. numli , dat e l i , COUNT( numprod) AS NB PRODUITS
FROM FOURNISSEUR F, LIVRAISON L, DETAILLIVRAISON D
WHERE F. numfou = L. numfou
AND D. numfou = L. numfou
AND D. numli = L. numli
GROUP BY nomfou , L. numli , da t e l i ;
Exerci ce 8
SELECT nomfou , L. numli , dat e l i , SUM( qte pr i x ) AS TOTAL
FROM FOURNISSEUR F, LIVRAISON L, DETAILLIVRAISON D, PROPOSER P
WHERE F. numfou = L. numfou
AND D. numfou = L. numfou
AND D. numli = L. numli
AND P. numfou = F. numfou
AND D. numprod = P. numprod
GROUP BY nomfou , L. numli , da t e l i ;
Exerci ce 9
SELECT nomprod
FROM PRODUIT P, PROPOSER PR
WHERE P. numprod = PR. numprod
GROUP BY nomprod
HAVINGCOUNT(D. numfou) = 1;
Exerci ce 10
SELECT nomfou
FROM FOURNISSEUR F, PROPOSER P, DETAILLIVRAISON L
WHERE F. numfou = P. numfou
AND L. numfou = F. numfou
GROUP BY nomfou
HAVINGCOUNT(DISTINCT P. numprod) = COUNT(DISTINCT L. numprod ) ;
82
3.5 Vues
Exerci ce 1
CREATE VIEW QUANTITE LIVREE PAR PRODUIT AS
SELECT numprod , SUM( qte ) AS QUANTITE LIVREE
FROM DETAILLIVRAISON
GROUP BY numprod ;
Exerci ce 2
SELECT MAX(QUANTITE LIVREE)
FROM QUANTITE LIVREE PAR PRODUIT;
Exerci ce 3
CREATE VIEW FACTURE PAR LIVRAISON AS
SELECT D. numfou , D. numli , SUM( qte pr i x ) AS MONTANTFACTURE
FROM PROPOSER PR, DETAILLIVRAiSON D
wHERE PR. numfou = D. numfou
AND D. numprod = PR. numprod
GROUP BY D. numfou , D. numli ;
Exerci ce 4
CREATE VIEW FACTURE PAR FOURNISSEUR AS
SELECT numfou , SUM(MONTANTFACTURE) AS TOTAL FACTURE
FROM FACTURE PAR LIVRAISON
GROUP BY numfou ;
Exerci ce 5
SELECT MIN(TOTAL FACTURE)
FROM FACTURE PAR FOURNISSEUR;
Exerci ce 6
CREATE VIEW NB PROD DIST LIVRES PAR FOU AS
SELECT DISTINCT numfou ,
COUNT(DISTINCT numprod) AS NB PRODUITS DISTINCTS LIVRES
FROM DETAILLIVRAISON
GROUP BY numfou ;
SELECT MAX(NB PRODUITS DISTINCTS LIVRES)
FROM NB PROD DIST LIVRES PAR FOU;
83
3.6 Requetes imbriquees
Exerci ce 1
SELECT nomfou ,
(SELECT COUNT( numprod)
FROM PROPOSER P
WHERE P. numfou = F. numfou
) AS NB PROD PROPOSES
FROM FOURNISSEUR F;
Exerci ce 2
SELECT nomfou
FROM FOURNISSEUR
WHERE numfou IN
(SELECT numfou
FROM PROPOSER
WHERE numprod = 2 ) ;
Exerci ce 3
SELECT nomfou
FROM FOURNISSEUR
WHERE numfou IN
(SELECT numfou
FROM PROPOSER
WHERE numprod =
(SELECT numprod
FROM PRODUIT
WHERE nomprod = Poupee Batman
)
) ;
Exerci ce 4
SELECT nomfou
FROM FOURNISSEUR
WHERE numfou IN
(SELECT numfou
FROM DETAILLIVRAISON
WHERE numprod IN
(SELECT numprod
FROM PRODUIT
WHERE nomprod = Poupee Batman
)
) ;
Exerci ce 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
) ;
Exerci ce 6
SELECT nomfou ,
(SELECT nomprod
FROM PRODUIT P
WHERE P. numprod IN
(SELECT numprod
FROM PROPOSER PR1
WHERE PR1. numfou = F. numfou
AND pr i x =
(SELECT MAX( pr i x )
FROM PROPOSER PR2
WHERE PR2. numfou = F. numfou
)
)
)
FROM FOURNISSEUR F;
Exerci ce 7
84
CREATE VIEW NB PROD LIVRES PAR FOU AS
SELECT numfou , numprod , SUM( qte ) AS QTE
FROM DETAILLIVRAISON
GROUP BY numfou , numprod ;
SELECT nomprod , nomfou
FROM FOURNISSEUR F, PRODUIT P
WHERE
(SELECT QTE
FROM NB PROD LIVRES PAR FOU D
WHERE D. numprod = P. numprod
AND D. numfou = F. numfou
)
=
(SELECT MAX(QTE)
FROM NB PROD LIVRES PAR FOU D
WHERE D. numprod = P. numprod
) ;
Exerci ce 8
SELECT MIN(NB PROD)
FROM
(SELECT
(SELECT COUNT( )
FROM PROPOSER PR
WHERE PR. numfou = F. numfou
) AS NB PROD
FROM FOURNISSEUR F
) ;
Exerci ce 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
)
)
) ;
Exerci ce 10
SELECT nomprod , nomfou
FROM PRODUIT P, FOURNISSEUR F,
(SELECT F1 . numfou , P1 . numprod
FROM FOURNISSEUR F1 , PRODUIT P1
WHERE
(SELECT SUM(QTE)
FROM DETAILLIVRAiSON D
WHERE D. numfou = F1 . numfou
AND D. numprod = P1 . numprod
)
=
(SELECT MAX(NB LIV)
FROM
(SELECT numprod , SUM(QTE) AS NB LIV
FROM DETAILLIVRAiSON D
GROUP BY numprod , numfou
) Q
WHERE Q. numprod = P1 . numprod
)
) M
WHERE P. numprod = M. numprod
AND F. numfou = M. numfou ;
85
3.7 Complements sur les types
Exerci ce 1
ALTER TABLE LIVRAISON ADDCONSTRAINT ck date mandatory
CHECK ( da t e l i IS NOT NULL) ;
ALTER TABLE PROPOSER ADDCONSTRAINT ck pr i ce mandat or y
CHECK ( pr i x IS NOT NULL) ;
ALTER TABLE DETAILLIVRAISON ADDCONSTRAINT ck qte mandatory
CHECK ( qte IS NOT NULL) ;
Exerci ce 2
ALTER TABLE PROPOSER ADDCONSTRAINT c k p r i c e p o s i t i v e
CHECK ( pr i x > 0 ) ;
ALTER TABLE DETAILLIVRAISON ADDCONSTRAINT c k q t e po s i t i v e
CHECK ( qte > 0 ) ;
Exerci ce 3
ALTER TABLE LIVRAISON ADDCONSTRAINT ck oct obr e 2006
CHECK ( t o char ( dat e l i , yyyymm ) >= 200610 ) ;
Exerci ce 4
ALTER TABLE LIVRAISON ADDCONSTRAINT c k f e t e d u t r a v a i l
CHECK ( t o char ( dat e l i , mmdd ) <> 0501 ) ;
Exerci ce 5
UPDATE PRODUIT SET
nomprod = upper( substr ( nomprod , 1 , 1 ) ) | |
substr ( nomprod , 2 , LENGTH( nomprod) 1 ) ;
ALTER TABLE PRODUIT ADD
CONSTRAINT ck maj us cul e pr odui t
CHECK ( upper( substr ( nomprod , 1 , 1) ) = substr ( nomprod , 1 , 1 ) ) ;
UPDATE FOURNISSEUR SET
nomfou = upper( substr ( nomfou , 1 , 1 ) ) | |
substr ( nomfou , 2 , LENGTH( nomfou) 1 ) ;
ALTER TABLE FOURNISSEUR ADD
CONSTRAINT c k maj us c ul e f our ni s s e ur
CHECK ( upper( substr ( nomfou , 1 , 1) ) = substr ( nomfou , 1 , 1 ) ) ;
86
3.8 Revisions
Exerci ce 1
SELECT nomfou
FROM FOURNISSEUR F
WHERE
(
SELECT COUNT( )
FROM LIVRAISON L
WHERE L. numfou = F. numfou
)
>= 2;
Exerci ce 2
CREATE VIEW LIVRAISONS PAR ANNEE AS
SELECT ANNEE, COUNT( ) AS NB LIVRAISONS
FROM
(
SELECT t o char ( dat e l i , yyyy ) AS ANNEE, numfou , numli
FROM LIVRAISON
)
GROUP BY ANNEE;
SELECT ANNEE
FROM LIVRAISONS PAR ANNEE
WHERE NB LIVRAISONS =
(
SELECT MAX(NB LIVRAISONS)
FROM LIVRAISONS PAR ANNEE
) ;
Exerci ce 3
CREATE VIEW FOU KI ONT TOU LIVRE AS
SELECT numfou
FROM FOURNISSEUR F
WHERE
(SELECT COUNT( )
FROM PROPOSER PR
WHERE PR. numfou = F. numfou)
=
(SELECT COUNT(DISTINCT numprod)
FROM DETAILLIVRAISON D
WHERE D. numfou = F. numfou
) ;
CREATE VIEW DERNIERE LI PAR FOU AS
SELECT numfou , MAX( da t e l i ) AS DATEMAX
FROM LIVRAISON
GROUP BY numfou ;
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 DATEMAX =
(
SELECT MAX(DATEMAX)
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;
Exerci ce 1 et 3
CREATE TABLE ETUDIANT
(numEtud number,
nom varchar2 ( 40) ,
prenom varchar2 ( 40) ,
dat e nai s s date ,
c i v i l i t e varchar2 ( 4) ,
patronyme varchar2 ( 40) ,
numsecu varchar2 ( 15) NOT NULL) ;
CREATE TABLE MODULE
( codMod number,
nomMod varchar2 ( 15) ,
ef f ecMax number DEFAULT 30) ;
CREATE TABLE EXAMEN
( codMod number,
codExam number,
dateExam date ) ;
CREATE TABLE INSCRIPTION
(numEtud number,
codMod number,
dat eI ns c date default s ys dat e ) ;
CREATE TABLE PREREQUIS
( codMod number,
codModPrereq number,
noteMin number( 4 , 2) NOT NULL) ;
CREATE TABLE RESULTAT
( codMod number,
codExam number,
numEtud number,
note number( 4 , 2 ) ) ;
Exerci ce 2
ALTER TABLE ETUDIANT ADD
CONSTRAINT pk et udi ant
PRIMARYKEY (numEtud ) ;
ALTER TABLE MODULE ADD
CONSTRAINT pk module
PRIMARYKEY ( codMod ) ;
ALTER TABLE EXAMEN ADD
CONSTRAINT pk examen
PRIMARYKEY ( codMod , codExam) ;
ALTER TABLE PREREQUIS ADD
CONSTRAINT pk pr e r e qui s
PRIMARYKEY ( codMod , codModPrereq ) ;
ALTER TABLE INSCRIPTION ADD
CONSTRAINT pk i ns c r i pt i o n
PRIMARYKEY ( codMod , numEtud ) ;
ALTER TABLE RESULTAT ADD
CONSTRAINT pk r e s ul t a t
PRIMARYKEY ( codMod , numEtud , codExam) ;
ALTER TABLE INSCRIPTION ADD
(CONSTRAINT f k i ns c r i pt i o n e t udi a nt
FOREIGN KEY (numEtud)
REFERENCES ETUDIANT(numEtud) ,
CONSTRAINT f k i ns c r i pt i on modul e
FOREIGN KEY ( codMod)
REFERENCES MODULE( codMod ) ) ;
ALTER TABLE PREREQUIS ADD
(CONSTRAINT f k pr er equi s codmod
FOREIGN KEY ( codMod)
REFERENCES MODULE( codMod) ,
CONSTRAINT f k pr er equi s codmodpr er eq
FOREIGN KEY ( codModPrereq )
REFERENCES MODULE( codMod ) ) ;
ALTER TABLE EXAMEN ADD
CONSTRAINT fk examen
FOREIGN KEY ( codMod)
REFERENCES MODULE( codMod ) ;
ALTER TABLE RESULTAT ADD
(CONSTRAINT f k r e s ul t at e xame n
FOREIGN KEY ( codMod , codExam)
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 ) ) ;
Exerci ce 3
I c i se t rouve l e s cons t r ai nt es de t ype CHECK qui n ont pas ete pl acees
au niveau de l a t ab l e pour des rai sons de l i s i b i l i t e .
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 , Ml l e )
) ,
CONSTRAINT c k c i vi l i t e nums e c u
CHECK
(
SUBSTR( numsecu , 1 , 1) = 2 OR patronyme IS NULL
) ,
CONSTRAINT ck l ength numsecu
CHECK
(
l engt h ( numsecu) = 15
) ,
CONSTRAINT ck annee numsecu CHECK
(
t o char ( dat enai s s , yy ) = substr ( numsecu , 2 , 2)
)
) ;
I l i mpossi bl e de l i mi t e r de facon de c l ar at i ve l e nombre d et udi ant s
i ns c r i t s `a un module .
Exerci ce 4
INSERT INTO ETUDIANT VALUES
( (SELECT nvl (MAX(numEtud) , 0) + 1 FROM ETUDIANT) ,
Four i er ,
Joseph ,
t o dat e ( 21031768 , ddmmyyyy ) ,
Mr ,
NULL,
168031234567890
) ;
INSERT INTO MODULE ( codMod , nomMod) VALUES
(
(SELECT nvl (MAX( codMod) , 0) + 1 FROM MODULE) ,
Maths
) ;
INSERT INTO INSCRIPTION ( codMod , numEtud) VALUES
( (SELECT numEtud FROM ETUDIANT WHERE nom = Four i er ) ,
(SELECT codMod FROM MODULE WHERE nomMod = Maths ) ) ;
INSERT INTO EXAMEN VALUES
(
(SELECT codMod FROM MODULE WHERE nomMod = Maths ) ,
1 ,
t o dat e ( 02012007 , ddmmyyyy )
) ;
INSERT INTO RESULTAT VALUES
(
(SELECT codMod FROM MODULE WHERE nomMod = Maths ) ,
1 ,
(SELECT numEtud FROM ETUDIANT WHERE nom = Four i er ) ,
19
) ;
UPDATE RESULTAT SET note = 20
wHERE
numEtud = (SELECT numEtud FROM ETUDIANT WHERE nom = Four i er )
AND codMod = (SELECT codMod FROM MODULE WHERE nomMod = Maths )
AND codExam = 1;
Exerci ce 5
requet e 1
SELECT nom
FROM ETUDIANT;
requet e 2
89
SELECT nom
FROM ETUDIANT
WHERE numEtud IN
(
SELECT numEtud
FROM INSCRIPTION
WHERE codMod IN
(
SELECT codMod
FROM MODULE
WHERE nomMod = Maths
)
) ;
requet e 3
SELECT nom, prenom ,
(
SELECT MAX(NOTE)
FROM RESULTAT R
WHERE R. numEtud = E. numEtud
AND codMod =
(
SELECT codMod
FROM MODULE
WHERE nomMod = Maths
)
) AS NOTE DEFINITIVE
FROM ETUDIANT E;
requet e 4
SELECT nom, prenom
FROM ETUDIANT E
WHERE
0 <=
(
SELECT count ( )
FROM RESULTAT R
WHERE R. numEtud = E. numEtud
AND note >= 10
AND codMod =
(
SELECT codMod
FROM MODULE
WHERE nomMod = Maths
)
) ;
requet e 5
SELECT nom, prenom
FROM ETUDIANT E
WHERE
(
SELECT count ( )
FROM RESULTAT R
WHERE R. numEtud = E. numEtud
AND codMod =
(
SELECT codMod
FROM MODULE
WHERE nomMod = Maths
)
) = 0 ;
requet e 6
CREATE VIEW NOTE MATHS PAR ETU AS
SELECT numEtud ,
(
SELECT MAX(NOTE)
FROM RESULTAT R
WHERE R. numEtud = E. numEtud
AND codMod =
(
SELECT codMod
FROM MODULE
WHERE nomMod = Maths
)
) AS NOTEMATHS
FROM ETUDIANT E;
SELECT nom, prenom
FROM ETUDIANT
WHERE numEtud IN
(
90
SELECT numEtud
FROM NOTE MATHS PAR ETU
WHERE NOTEMATHS
=
(
SELECT MAX(NOTEMATHS)
FROM NOTE MATHS PAR ETU
)
) ;
requet e 7
CREATE VIEW NOTE MIN MATHS PAR ETU AS
SELECT numEtud ,
(
SELECT MIN(NOTE)
FROM RESULTAT R
WHERE R. numEtud = E. numEtud
AND codMod =
(
SELECT codMod
FROM MODULE
WHERE nomMod = Maths
)
) AS NOTEMATHS
FROM ETUDIANT E;
SELECT nom, prenom
FROM ETUDIANT
WHERE numEtud IN
(
SELECT numEtud
FROM NOTE MATHS PAR ETU
WHERE NOTEMATHS
=
(
SELECT MAX(NOTEMATHS)
FROM NOTE MIN MATHS PAR ETU
)
) ;
requet e 8
CREATE VIEW NOTE PAR ETU MOD AS
SELECT numEtud , codMod ,
(
SELECT MAX( note )
FROM RESULTAT R
WHERE R. numEtud = I . numEtud
AND R. codMod = I . codMod
) AS NOTE DEF
FROM INSCRIPTION I ;
SELECT nomMod
FROM MODULE M
WHERE
(
SELECT COUNT( )
FROM PREREQUIS P
WHEREM. 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 = Four i er
)
)
) = 0
ANDM. codMod NOT IN
(
SELECT codMod
FROM INSCRIPTION
WHERE numEtud IN
(
SELECT numEtud
FROM ETUDIANT
WHERE nom = Four i er
)
) ;
91
3.10 Introduction au PL/SQL
Exerci ce 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 ul t i s : ) ;
t := a ;
a := b ;
b := t ;
DBMS OUTPUT. PUT LINE( a = | | a ) ;
DBMS OUTPUT. PUT LINE( b = | | b ) ;
END;
/
Exerci ce 2
DECLARE
a NUMBER;
r e s NUMBER;
counter NUMBER;
BEGIN
a := 10;
r e s := 1;
counter := a ;
WHILE counter > 0 LOOP
r e s := r e s counter ;
counter := counter 1;
END LOOP;
DBMS OUTPUT. PUT LINE( a | | != | | r e s ) ;
END;
/
Exerci ce 3
DECLARE
a NUMBER := 48;
b NUMBER := 84;
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
Tabl eaux
DECLARE
TYPE montab IS VARRAY ( 50) OF INTEGER;
t montab ;
BEGIN
t := montab ( ) ;
t . extend ( 2 0 ) ;
I ni t i a l i s a t i o n
FOR i IN 1 . . 2 0 LOOP
t ( i ) := i i ;
END LOOP;
Inversi on de l ordre des elements
DECLARE
temp integer ;
BEGIN
FOR i IN 1 . . 1 0 LOOP
temp := t ( i ) ;
t ( i ) := t (20i +1);
t (20i +1) := temp ;
END LOOP;
END;
Af f i chage
FOR i IN 1 . . 2 0 LOOP
DBMS OUTPUT. PUT LINE( t ( | |
i | | ) = | | t ( i ) ) ;
END LOOP;
Tri `a b ul l e
DECLARE
temp integer ;
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;
Af f i chage
FOR i IN 1 . . 2 0 LOOP
DBMS OUTPUT. PUT LINE( t ( | |
i | | ) = | | t ( i ) ) ;
END LOOP;
Recherche par di chotomi e de l element 225
DECLARE
i nf INTEGER := 1;
sup INTEGER := 20;
m INTEGER;
X INTEGER := 400;
BEGIN
LOOP
DBMS OUTPUT. PUT LINE( i nf = | | i nf | |
; sup = | | sup ) ;
m := ( i nf + sup ) /2;
EXIT WHEN
t (m) = X OR i nf = sup ;
IF t (m) > X THEN
sup := m1;
ELSE
i nf := m+1;
END IF ;
END LOOP;
IF t (m) = X THEN
DBMS OUTPUT. PUT LINE(X | |
e s t dans l e t abl eau ) ;
ELSE
DBMS OUTPUT. PUT LINE(X | |
n e s t pas dans l e t abl eau ) ;
END IF ;
END;
END;
/
93
St ruct ures
DECLARE
Mai l l on d une l i s t e cha nee
TYPE CELL IS RECORD
(
Donnee de chaque mai l l on
data INTEGER,
Indi ce du mai l l on precedent de l a l i s t e ,
1 s i l n y en a pas
pr evi ous INTEGER,
Indi ce du mai l l on sui vant de l a l i s t e ,
1 s i l n y en a pas
next INTEGER
) ;
Type t abl eau contenant l e s mai l l ons de l a l i s t e
TYPE TREE IS VARRAY ( 19) OF CELL;
Tableau contenant l e s mai l l ons de l a l i s t e
t TREE;
i ndi ce du premier element de l a l i s t e
f i r s t integer ;
i ndi ce du derni er element de l a l i s t e
l ast integer ;
BEGIN
t := TREE( ) ;
t . extend ( 1 9 ) ;
I ni t i a l i s a t i o n
FOR i IN 1 . . 1 9 LOOP
t ( i ) . data := power ( i , 5) mod 19 ;
t ( i ) . pr evi ous := i 1;
t ( i ) . next := i +1;
END LOOP;
f i r s t := 1;
l ast := 19;
t ( f i r s t ) . pr evi ous := 1;
t ( l ast ) . next := 1;
Af f i chage
DECLARE
p integer := f i r s t ;
BEGIN
WHILE p <> 1 LOOP
DBMS OUTPUT. PUT LINE( ( | | p | | , | |
t ( p ) . data | | , | |
t ( p ) . pr evi ous | | , | |
t ( p ) . next | | ) ) ;
p := t ( p ) . next ;
END LOOP;
END;
Inversi on de l ordre des elements
DECLARE
temp INTEGER;
BEGIN
FOR i IN 1 . . 1 9 LOOP
temp := t ( i ) . pr evi ous ;
t ( i ) . pr evi ous := t ( i ) . next ;
t ( i ) . next := temp ;
END LOOP;
f i r s t := 19;
l ast := 1;
END;
Af f i chage
DECLARE
p integer := f i r s t ;
BEGIN
WHILE p <> 1 LOOP
DBMS OUTPUT. PUT LINE( ( | |
p | | , | |
t ( p ) . data | | , | |
t ( p ) . pr evi ous | | , | |
t ( p ) . next | | ) ) ;
p := t ( p ) . next ;
END LOOP;
END;
Tri `a b ul l e
DECLARE
i integer := l ast ;
j integer ;
BEGIN
WHILE t ( t ( i ) . pr evi ous ) . pr evi ous <> 1 LOOP
j := f i r s t ;
WHILE i <>j LOOP
IF( t ( j ) . data > t ( t ( j ) . next ) . data ) THEN
94
Echange de j et t ( j ) . next
par modi f i cat i on du cha nage
DECLARE
af t e r J INTEGER := t ( j ) . next ;
bef or eJ INTEGER := t ( j ) . pr evi ous ;
BEGIN
t ( j ) . next := t ( a f t e r J ) . next ;
t ( af t e r J ) . next := j ;
t ( af t e r J ) . pr evi ous := bef or eJ ;
t ( j ) . pr evi ous := a f t e r J ;
IF t ( j ) . next <> 1 THEN
t ( t ( j ) . next ) . pr evi ous := j ;
ELSE
l ast := j ;
END IF ;
IF t ( af t e r J ) . pr evi ous <> 1 THEN
t ( t ( af t e r J ) . pr evi ous ) . next := af t e r J ;
ELSE
f i r s t := af 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 ) . pr evi ous ;
END LOOP;
END;
Af f i chage
DECLARE
p integer := f i r s t ;
BEGIN
WHILE p <> 1 LOOP
DBMS OUTPUT. PUT LINE( ( | | p | | , | |
t ( p ) . data | | , | |
t ( p ) . pr evi ous | | , | |
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
Exerci ce 1
DECLARE
unCl i ent PERSONNE%ROWTYPE;
numClient PERSONNE. numpers%type ;
Y A EU UNE MERDE EXCEPTION;
BEGIN
FOR numClient IN 1 . . 2 1 LOOP
BEGIN
SELECT INTO unCl i ent
FROM PERSONNE
WHERE numpers = numClient ;
INSERT INTO CLIENT ( numcli , nomcl i , prenomcl i )
VALUES
( unCl i ent . numpers ,
unCl i ent . nom,
unCl i ent . prenom ) ;
EXCEPTION
WHEN NO DATA FOUND THEN
DBMS OUTPUT. PUT LINE(
Personne na l i d e n t i f i a n t | |
numClient ) ;
WHENTOOMANYROWS THEN
DBMS OUTPUT. PUT LINE(
Cette message ne de vr ai t j amai s appar a t r e ! ) ;
WHEN DUP VAL ON INDEX THEN
DBMS OUTPUT. PUT LINE(
Contrai nte de c l e v i o l e e ! Message SQL : | |
SQLERRM) ;
WHEN OTHERS THEN
RAISE Y A EU UNE MERDE;
END;
END LOOP;
COMMIT;
EXCEPTION
WHEN Y A EU UNE MERDE THEN
DBMS OUTPUT. PUT LINE( SQLCODE = | | SQLCODE) ;
DBMS OUTPUT. PUT LINE( I l y a eu une Merde ! ) ;
ROLLBACK;
END;
/
Exerci ce 2
DECLARE
unCl i ent CLIENT%rowtype ;
BEGIN
SELECT INTO unCl i ent
FROM CLIENT WHERE numCli =
(
SELECT MAX( numcl i )
FROM CLIENT
) ;
INSERT INTO PERSONNEL VALUES
(
1 ,
unCl i ent . nomcl i ,
unCl i ent . prenomcl i ,
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 gr os probl`eme . . . Jcomprends pas c qui s passe ) ;
END;
/
Exerci ce 3
DECLARE
numClient CLIENT. numcl i%TYPE;
tCCL TYPECCL. numtypeccl%TYPE;
nto TYPEOPERATION. numtypeoper%TYPE;
Y A UN GRO BLEME EXCEPTION;
BEGIN
SELECT numtypeoper INTO nto
96
FROM TYPEOPERATION
WHERE nomtypeoper = depot es p`eces ;
SELECT numtypeccl INTO tCCL
FROM TYPECCL
WHERE nomtypeCCL = Compte courant ;
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 100 ,
i naugur at i on du compte
) ;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
Adaptez l e numero du code ,
chez moi ca donne 2290
IF SQLCODE = 2290 THEN
DECLARE
t o t a l OPERATION. montantoper%TYPE := numClient 100;
t o I ns e r t OPERATION. montantoper%TYPE;
cpt NUMBER := 1;
BEGIN
WHILE t o t a l > 0 LOOP
IF t o t a l > 1000 THEN
t o I ns e r t := 1000;
ELSE
t o I ns e r t := t o t a l ;
END IF ;
INSERT INTO OPERATION VALUES
(
numClient ,
1 ,
(SELECT nvl (MAX( numoper ) , 0) + 1
FROM OPERATION
WHERE numcl i = numClient
AND numccl = 1
) ,
nto ,
SYSDATE,
t oI ns e r t ,
I naugur at i on du compte | | cpt
) ;
t o t a l := t o t a l t o I ns e r t ;
cpt := cpt + 1;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
DBMS OUTPUT. PUT LINE( MOD( t ot al , 1000) = | | MOD( t ot al , 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 donnees ! ) ;
WHENTOOMANYROWS THEN
DBMS OUTPUT. PUT LINE( Trop de donnees ! ) ;
WHEN Y A UN GRO BLEME THEN
DBMS OUTPUT. PUT LINE( I l y a un gr os probl`eme ! ) ;
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;
/
Exerci ce 4
97
DECLARE
numClient CLIENT. numcl i%TYPE := 2;
numCompteLivret TYPECCL. numtypeCCL%TYPE;
nto TYPEOPERATION. numtypeoper%TYPE;
montant OPERATION. montantoper%TYPE;
Y A UN GRO BLEME EXCEPTION;
BEGIN
SELECT numtypeoper INTO nto
FROM TYPEOPERATION
WHERE nomtypeoper = vi rement ;
SELECT numtypeccl INTO numCompteLivret
FROM TYPECCL
WHERE nomtypeCcl = l i v r e t ;
WHILE numClient <= 21 LOOP
BEGIN
montant := 100 numClient 500;
INSERT INTO COMPTECLIENT VALUES
(
numClient ,
2 ,
numCompteLivret ,
SYSDATE,
1
) ;
INSERT INTO OPERATION VALUES
(
numClient ,
1 ,
(SELECT nvl (MAX( numoper ) , 0) + 1
FROM OPERATION
WHERE numcl i = numClient
AND numccl = 1) ,
nto ,
SYSDATE,
montant ,
versement l i v r e t
) ;
INSERT INTO OPERATION VALUES
(
numClient ,
2 ,
(SELECT nvl (MAX( numoper ) , 0) + 1
FROM OPERATION
WHERE numcl 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;
cpt NUMBER := 1;
BEGIN
WHILE t o t a l > 1000 LOOP
IF t o t a l > 1000 THEN
toMove := 1000;
ELSE
tomove := t o t a l ;
END IF ;
INSERT INTO OPERATION VALUES
(
numClient ,
1 ,
(SELECT nvl (MAX( numoper ) , 0) + 1
FROM OPERATION
WHERE numcl i = numClient
AND numccl = 1) ,
nto ,
SYSDATE,
toMove ,
versement l i v r e t | | cpt
) ;
INSERT INTO OPERATION VALUES
(
numClient ,
2 ,
(SELECT nvl (MAX( numoper ) , 0) + 1
FROM OPERATION
WHERE numcl 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 ;
cpt := cpt + 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 donnees ! ) ;
WHENTOOMANYROWS THEN
DBMS OUTPUT. PUT LINE( Trop de donnees ! ) ;
WHEN Y A UN GRO BLEME THEN
DBMS OUTPUT. PUT LINE( I l y a un gr os probl`eme ! ) ;
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
Exerci ce 1
CREATE OR REPLACE FUNCTION
bad pui s s ance ( b NUMBER, n NUMBER)
RETURN NUMBER IS
BEGIN
IF ( n = 0) THEN
RETURN 1;
ELSE
RETURN b bad pui s s ance ( b , n 1 ) ;
END IF ;
END;
/
Exerci ce 2
CREATE OR REPLACE FUNCTION
good pui s s ance ( b NUMBER, n NUMBER)
RETURN NUMBER IS
BEGIN
IF ( n = 0) THEN
RETURN 1;
END IF ;
IF ( MOD( n , 2) = 0 ) THEN
RETURN good pui s s ance ( b b , n / 2 ) ;
END IF ;
RETURN b good pui s s ance ( b , n 1 ) ;
END;
/
Exerci ce 3
CREATE OR REPLACE FUNCTION
demi Freres (A PERSONNE. numpers%type , B PERSONNE. numpers%type )
RETURN BOOLEAN IS
rowA PERSONNE%rowtype ;
rowB PERSONNE%rowtype ;
BEGIN
SELECT INTO rowA FROM PERSONNE WHERE numpers = A;
SELECT INTO rowB FROM PERSONNE WHERE numpers = B;
RETURN rowA. pere = rowB. pere OR rowA. mere = rowB. mere ;
END;
/
Exerci ce 4
CREATE OR REPLACE FUNCTION
f r e r e s (A PERSONNE. numpers%type , B PERSONNE. numpers%type )
RETURN BOOLEAN IS
rowA PERSONNE%rowtype ;
rowB PERSONNE%rowtype ;
BEGIN
SELECT INTO rowA FROM PERSONNE WHERE numpers = A;
SELECT INTO rowB FROM PERSONNE WHERE numpers = B;
RETURN rowA. pere = rowB. pere AND rowA. mere = rowB. mere ;
END;
/
CREATE OR REPLACE FUNCTION
cousi nsGermai ns (A PERSONNE. numpers%type , B PERSONNE. numpers%type )
RETURN BOOLEAN IS
rowA PERSONNE%rowtype ;
rowB PERSONNE%rowtype ;
BEGIN
SELECT INTO rowA FROM PERSONNE WHERE numpers = A;
SELECT INTO rowB FROM PERSONNE WHERE numpers = B;
RETURN
f r e r e s (rowA. pere , rowB. pere )
OR
f r e r e s (rowA. pere , rowB. mere )
OR
f r e r e s (rowA. mere , rowB. pere )
OR
f r e r e s (rowA. mere , rowB. mere ) ;
END;
/
Exerci ce 5
CREATE OR REPLACE PROCEDURE
a i e ul (P PERSONNE. numpers%type ) IS
row PERSONNE%rowtype ;
nb NUMBER;
BEGIN
SELECT count ( ) INTO NB
FROM PERSONNE
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 ul ( row . pere ) ;
END IF ;
END;
/
Exerci ce 6
CREATE OR REPLACE PROCEDURE
mecs (P PERSONNE. numpers%type ) IS
row PERSONNE%rowtype ;
nb NUMBER;
BEGIN
SELECT count ( ) INTO NB
FROM PERSONNE
WHERE numpers = P;
IF (NB = 1) THEN
SELECT INTO row
FROM PERSONNE
WHERE numpers = P;
SELECT count ( ) INTO NB
FROM PERSONNE
WHERE pere = P;
IF (NB > 0) THEN
DBMS OUTPUT. PUT LINE( row . nom) ;
END IF ;
mecs ( row . pere ) ;
mecs ( row . mere ) ;
END IF ;
END;
/
Exerci ce 7
CREATE OR REPLACE FUNCTION
ascendant (A PERSONNE. numpers%type , B PERSONNE. numpers%type )
RETURN BOOLEAN IS
row PERSONNE%rowtype ;
BEGIN
SELECT INTO row FROM PERSONNE WHERE numpers = B;
IF ( row . pere = A OR row . mere = A) THEN
RETURN TRUE;
END IF ;
RETURN ( row . pere IS NOT NULL AND ascendant (A, row . pere ) )
OR
( row . mere IS NOT NULL AND ascendant (A, row . mere ) ) ;
END;
/
BEGIN
IF ( ascendant ( 1 , 8) ) THEN
DBMS OUTPUT. PUT LINE( OK ) ;
ELSE
DBMS OUTPUT. PUT LINE( pas OK ) ;
END IF ;
END;
/
Exerci ce 8
CREATE OR REPLACE FUNCTION
fmax (A NUMBER, B NUMBER)
RETURN NUMBER IS
BEGIN
IF (A > B) THEN
RETURN A;
ELSE
RETURN B;
END IF ;
END;
/
CREATE OR REPLACE FUNCTION
ecartAscendant (A PERSONNE. numpers%type , B PERSONNE. numpers%type )
RETURN NUMBER IS
row PERSONNE%rowtype ;
NB NUMBER;
BEGIN
SELECT INTO row FROM PERSONNE WHERE numpers = B;
IF ( row . pere = A OR row . mere = A) THEN
RETURN 1;
END IF ;
IF ( row . pere IS NULL) THEN
101
NB := 1;
ELSE
NB := ecartAscendant (A, row . pere ) ;
END IF ;
IF ( row . mere IS NULL) THEN
NB := fmax( 1, NB) ;
ELSE
NB := fmax( ecartAscendant (A, row . pere ) , NB) ;
END IF ;
IF (NB <> 1) THEN
NB := NB + 1;
END IF ;
RETURN NB;
END;
/
CREATE OR REPLACE FUNCTION
e c ar t (A PERSONNE. numpers%type , B PERSONNE. numpers%type )
RETURN NUMBER IS
row PERSONNE%rowtype ;
NB NUMBER;
BEGIN
RETURN fmax( ecartAscendant (A, B) , ecartAscendant (B, A) ) ;
END;
/
Exerci ce 9
SELECT A. nom, A. prenom , B. nom, B. prenom
FROM PERSONNE A, PERSONNE B
WHERE ecartAscendant (A. numpers , B. numpers ) =
(
SELECT MAX( ec )
FROM
(
SELECT e c ar t (A. numpers , B. numpers ) AS ec
FROM PERSONNE A, PERSONNE B
)
) ;
Exerci ce 10
102
3.14 Curseurs
CREATE OR REPLACE PROCEDURE copyFromPersonneToCl i ent IS
CURSOR C IS
SELECT
FROM PERSONNE;
ROW C%rowtype ;
BEGIN
FOR ROW IN C LOOP
INSERT INTO CLIENT
( numcli , nomcl i , prenomcl 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 onl y once . ) ;
END;
/
CALL copyFromPersonneToCl i ent ( ) ;
CREATE OR REPLACE PROCEDURE t akeCl i ent ToPer sonnel IS
Row c l i e n t%rowtype ;
BEGIN
SELECT INTO Row
FROM CLIENT
WHERE numcl i =
(
SELECT MAX( numcl i )
FROM CLIENT) ;
INSERT INTO PERSONNEL
( numpers , nompers , prenompers )
VALUES
(Row. numcli , Row. nomcl i , Row. prenomcl i ) ;
COMMIT;
EXCEPTION
WHEN DUP VAL ON INDEX THEN
DBMS OUTPUT. PUT LINE( Thi s row has al r eady been i mported . ) ;
ROLLBACK;
WHEN NO DATA FOUND THEN
DBMS OUTPUT. PUT LINE( Table CLIENT i s empty . ) ;
ROLLBACK;
END;
/
CALL t akeCl i ent ToPer sonnel ( ) ;
CREATE OR REPLACE PROCEDURE
cr edi t Account ( numcl i ent CLIENT. numcl i%type , value NUMBER) IS
BEGIN
IF ( value > 100) THEN
cr edi t Account ( numcl i ent , 100) ;
cr edi t Account ( numcl i ent , value 100) ;
ELSE
INSERT INTO OPERATION VALUES
( numcl i ent ,
1 ,
(SELECT nvl (MAX( numoper ) , 0) + 1
FROM OPERATION
WHERE numcl i = numcl i ent
AND numccl = 1
) ,
(SELECT numtypeoper
FROM TYPEOPERATION
WHERE nomtypeoper = vi rement
) ,
sysdate ,
value ,
cadeau !
) ;
END IF ;
EXCEPTION
WHEN OTHERS THEN
IF (SQLCODE = 22900) THEN
DBMS OUTPUT. PUT LINE( Too much money at once . ) ;
END IF ;
END;
/
CREATE OR REPLACE PROCEDURE
createVi rement ( numcl i ent CLIENT. numcl i%type , value NUMBER) IS
BEGIN
INSERT INTO OPERATION VALUES
( numcl i ent ,
1 ,
(SELECT nvl (MAX( numoper ) , 0) + 1
103
FROM OPERATION
WHERE numcl i = numcl i ent
AND numccl = 1
) ,
(SELECT numtypeoper
FROM TYPEOPERATION
WHERE nomtypeoper = vi rement
) ,
sysdate ,
value ,
cadeau !
) ;
INSERT INTO OPERATION VALUES
( numcl i ent ,
2 ,
(SELECT nvl (MAX( numoper ) , 0) + 1
FROM OPERATION
WHERE numcl i = numcl i ent
AND numccl = 1
) ,
(SELECT numtypeoper
FROM TYPEOPERATION
WHERE nomtypeoper = vi rement
) ,
sysdate ,
value ,
cadeau !
) ;
EXCEPTION
WHEN OTHERS THEN
IF (SQLCODE = 22900) THEN
DBMS OUTPUT. PUT LINE( Too much money at once . ) ;
END IF ;
END;
/
CREATE OR REPLACE PROCEDURE
moveToLivret ( numcl i ent CLIENT. numcl i%type , value NUMBER) IS
BEGIN
IF ( value >= 0) THEN
IF ( value > 100) THEN
moveToLivret ( numcl i ent , 100) ;
moveToLivret ( numcl i ent , value 100) ;
ELSE
createVi rement ( numcl i ent , value ) ;
END IF ;
END IF ;
EXCEPTION
WHEN OTHERS THEN
IF (SQLCODE = 22900) THEN
DBMS OUTPUT. PUT LINE( Too much money at once . ) ;
END IF ;
END;
/
CREATE OR REPLACE PROCEDURE
openAccount ( numcl i ent CLIENT. numcl i%type ) IS
BEGIN
INSERT INTO COMPTECLIENT VALUES
( numcl i ent ,
1 ,
(SELECT numtypeccl
FROM TYPECCL
WHERE nomtypeccl = Compte courant
) ,
sysdate ,
(SELECT numpers
FROM PERSONNEL
WHERE numpers =
(
SELECT MAX( numcl i )
FROM CLIENT
)
)
) ;
INSERT INTO COMPTECLIENT VALUES
( numcl i ent ,
2 ,
(SELECT numtypeccl
FROM TYPECCL
WHERE nomtypeccl = vi rement
) ,
sysdate ,
(SELECT numpers
FROM PERSONNEL
WHERE numpers =
(
SELECT MAX( numcl i )
FROM CLIENT
104
)
)
) ;
cr edi t Account ( numcl i ent , numcl i ent 100) ;
moveToLivret ( numcl i ent , numcl i ent 100 500) ;
EXCEPTION
WHEN DUP VAL ON INDEX THEN
DBMS OUTPUT. PUT LINE( Thi s account has al r eady been opened . ) ;
END;
/
CREATE OR REPLACE PROCEDURE openAccounts IS
CURSOR C IS
SELECT numcl i FROM CLIENT;
ROW C%rowtype ;
BEGIN
FOR ROW IN C LOOP
openAccount (ROW. numcl i ) ;
END LOOP;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS OUTPUT. PUT LINE( An e r r or has occur r ed . ) ;
ROLLBACK;
END;
/
CALL openAccounts ( ) ;
CREATE OR REPLACE PROCEDURE
af f i cheDes cendance ( numpersonne NUMBER) IS
CURSOR C IS
SELECT
FROM PERSONNE
WHERE pere = numpersonne
OR mere = numpersonne ;
ROW C%rowType ;
BEGIN
FOR ROW IN C LOOP
DBMS OUTPUT. PUT LINE( row . nom| | | | row . prenom ) ;
af f i cheDes cendance (ROW. numpers ) ;
END LOOP;
END;
/
105
3.15 Curseurs parametres
Exerci ce 1
CREATE OR REPLACE PROCEDURE a f f i c he Cl i e nt ( unCl i ent CLIENT%rowtype ) IS
BEGIN
DBMS OUTPUT. PUT LINE( Cl i ent | | unCl i ent . prenomcl i | | | | unCl i ent . nomCli ) ;
END;
/
CREATE OR REPLACE PROCEDURE af f i cheCompte ( unCompte COMPTECLIENT%rowtype ) IS
BEGIN
DBMS OUTPUT. PUT LINE( Compte | | unCompte . numCli | | | | unCompte . numccl ) ;
END;
/
CREATE OR REPLACE PROCEDURE af f i cheCompt es Cl i ent s IS
CURSOR c l i e n t s IS
SELECT
FROM CLIENT;
unCl i ent c l i e n t s%rowtype ;
CURSOR comptes ( numcl i ent CLIENT. numcl i%type ) IS
SELECT
FROM COMPTECLIENT
WHERE numcl i = numcl i ent ;
unCompte c l i e n t s%rowtype ;
BEGIN
FOR unCl i ent IN c l i e n t s LOOP
a f f i c he Cl i e nt ( unCl i ent ) ;
FOR unCompte IN comptes ( unCl i ent . numcl i ) LOOP
af f i cheCompte ( unCompte ) ;
END LOOP;
END LOOP;
END;
/
SET SERVEROUTPUT ON SIZE 1000000
c a l l af f i cheCompt es Cl i ent s ( ) ;
Exerci ce 2
CREATE OR REPLACE PROCEDURE af f i c he Ope r at i on ( uneOperati on OPERATION%rowtype ) IS
BEGIN
DBMS OUTPUT. PUT LINE( Operati on | | uneOperati on . numOper | | , montant : | | uneOperati on . montantOper ) ;
END;
/
CREATE OR REPLACE PROCEDURE af f i cheOper Compt esCl i ent s IS
CURSOR c l i e n t s IS
SELECT
FROM CLIENT;
unCl i ent c l i e n t s%rowtype ;
CURSOR comptes ( numcl i ent CLIENT. numcl i%type ) IS
SELECT
FROM COMPTECLIENT
WHERE numcl i = numcl i ent ;
unCompte c l i e n t s%rowtype ;
CURSOR ope r at i ons
( numcl i ent CLIENT. numcl i%type ,
numcompte COMPTECLIENT. numccl%type ) IS
SELECT
FROM OPERATION
WHERE numcl i = numcl i ent
AND numccl = numcompte ;
uneOperati on ope r at i ons%rowtype ;
BEGIN
FOR unCl i ent IN c l i e n t s LOOP
a f f i c he Cl i e nt ( unCl i ent ) ;
FOR unCompte IN comptes ( unCl i ent . numcl i ) LOOP
af f i cheCompte ( unCompte ) ;
FOR uneOperati on IN ope r at i ons ( unCl i ent . numcli , unCompte . numccl ) LOOP
af f i c he Ope r at i on ( uneOperati on ) ;
END LOOP;
END LOOP;
END LOOP;
END;
/
c a l l af f i cheOper Compt esCl i ent s ( ) ;
106
3.16 Triggers
I l convi ent d abord de modi f i er quel que peu l organi sat i on des
donnees , on aj out e par exemple dans l a t ab l e MODULE l e nombre
d et udi ant s i ns c r i t s
DROP TABLE RESULTAT;
DROP TABLE EXAMEN;
DROP TABLE PREREQUIS;
DROP TABLE INSCRIPTION;
DROP TABLE MODULE;
DROP TABLE ETUDIANT;
CREATE TABLE ETUDIANT
(numEtud number,
nom varchar2 ( 40) ,
prenom varchar2 ( 40) ,
dat e nai s s date ,
c i v i l i t e varchar2 ( 4) ,
patronyme varchar2 ( 40) ,
numsecu varchar2 ( 15) NOT NULL,
moyenne NUMBERDEFAULT NULL) ;
CREATE TABLE MODULE
( codMod number,
nomMod varchar2 ( 15) ,
ef f ecMax number DEFAULT 30 ,
e f f e c number default 0 ) ;
CREATE TABLE EXAMEN
( codMod number,
codExam number,
dateExam date ) ;
CREATE TABLE INSCRIPTION
(numEtud number,
codMod number,
dat eI ns c date default s ys dat e ) ;
CREATE TABLE PREREQUIS
( codMod number,
codModPrereq number,
noteMin number( 4 , 2) NOT NULL) ;
CREATE TABLE RESULTAT
( codMod number,
codExam number,
numEtud number,
note number( 4 , 2 ) ) ;
ALTER TABLE ETUDIANT ADD
CONSTRAINT pk et udi ant
PRIMARYKEY (numEtud ) ;
ALTER TABLE MODULE ADD
CONSTRAINT pk module
PRIMARYKEY ( codMod ) ;
ALTER TABLE EXAMEN ADD
CONSTRAINT pk examen
PRIMARYKEY ( codMod , codExam) ;
ALTER TABLE PREREQUIS ADD
CONSTRAINT pk pr e r e qui s
PRIMARYKEY ( codMod , codModPrereq ) ;
ALTER TABLE INSCRIPTION ADD
CONSTRAINT pk i ns c r i pt i o n
PRIMARYKEY ( codMod , numEtud ) ;
ALTER TABLE RESULTAT ADD
CONSTRAINT pk r e s ul t a t
PRIMARYKEY ( codMod , numEtud , codExam) ;
ALTER TABLE INSCRIPTION ADD
(CONSTRAINT f k i ns c r i pt i o n e t udi a nt
FOREIGN KEY (numEtud)
REFERENCES ETUDIANT(numEtud) ,
CONSTRAINT f k i ns c r i pt i on modul e
FOREIGN KEY ( codMod)
REFERENCES MODULE( codMod ) ) ;
ALTER TABLE PREREQUIS ADD
(CONSTRAINT f k pr er equi s codmod
FOREIGN KEY ( codMod)
REFERENCES MODULE( codMod) ,
CONSTRAINT f k pr er equi s codmodpr er eq
FOREIGN KEY ( codModPrereq )
REFERENCES MODULE( codMod ) ) ;
ALTER TABLE EXAMEN ADD
CONSTRAINT fk examen
FOREIGN KEY ( codMod)
REFERENCES MODULE( codMod ) ;
ALTER TABLE RESULTAT ADD
107
(CONSTRAINT f k r e s ul t at e xame 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 ) ) ;
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 , Ml l e )
) ,
CONSTRAINT c k c i vi l i t e nums e c u
CHECK
(
SUBSTR( numsecu , 1 , 1) = 2 OR patronyme IS NULL
) ,
CONSTRAINT ck l ength numsecu
CHECK
(
l engt h ( numsecu) = 15
) ,
CONSTRAINT ck annee numsecu CHECK
(
t o char ( dat enai s s , yy ) = substr ( numsecu , 2 , 2)
)
) ;

Contrai nte 1

CREATE OR REPLACE TRIGGER bef oreUpdateFERPrerequi s


BEFORE UPDATE ON PREREQUIS
FOR EACH ROW
BEGIN
IF ( : new. noteMin < : ol d . noteMin ) THEN
: new. noteMin := : ol d . noteMin ;
END IF ;
END;
/

Contrai nte 2

CREATE OR REPLACE PROCEDURE i nc r Ef f e c ( module NUMBER) IS


BEGIN
UPDATE MODULE SET e f f e c = e f f e c + 1 WHERE codmod = module ;
END;
/

CREATE OR REPLACE PROCEDURE de c r Ef f e c ( module NUMBER) IS


BEGIN
UPDATE MODULE SET e f f e c = e f f e c 1 WHERE codmod = module ;
END;
/

CREATE OR REPLACE TRIGGER BeforeInsertFERModul e


BEFORE INSERT ON MODULE
FOR EACH ROW
BEGIN
: new. e f f e c := 0;
END;
/

CREATE OR REPLACE TRIGGER af t er I ns er t FERI ns c


AFTER INSERT ON INSCRIPTION
FOR EACH ROW
BEGIN
i nc r Ef f e c ( : new. codmod ) ;
END;
/

108

CREATE OR REPLACE TRIGGER af terDel eteFERI nsc


AFTER DELETE ON INSCRIPTION
FOR EACH ROW
BEGIN
de c r Ef f e c ( : ol d . codmod ) ;
END;
/

CREATE OR REPLACE TRIGGER afterUpdateFERInsc


AFTER UPDATE ON INSCRIPTION
FOR EACH ROW
BEGIN
de c r Ef f e c ( : ol d . codmod ) ;
i nc r Ef f e c ( : new. codmod ) ;
END;
/

DROP VIEW modul esDi sponi bl es ;


CREATE VIEW modul esDi sponi bl es AS
SELECT codmod
FROM MODULE
WHERE e f f e c < ef f ecMax ;

CREATE OR REPLACE TRIGGER bef oreInsertUpdateFERInsc


BEFORE INSERT OR UPDATE ON INSCRIPTION
FOR EACH ROW
DECLARE
nbLi gnes NUMBER;
BEGIN
SELECT count ( ) INTO nbLi gnes
FROM modul esDi sponi bl es
WHERE codmod = : new. codmod ;
IF ( nbLi gnes = 0) THEN
RAISE APPLICATION ERROR( 20001 , Pl us de pl ac e s di poni bl e s . ) ;
END IF ;
END;
/

Contrai nte 3

DROP VIEW examensPossi bl es ;


CREATE VIEW examensPossi bl es AS
SELECT codMod
FROM MODULE M
WHERE
(
SELECT COUNT( )
FROM INSCRIPTION I
WHERE I . codmod = M. codmod
) > 0 ;

CREATE OR REPLACE TRIGGER beforeInsertUpdateFERExam


BEFORE INSERT OR UPDATE ON EXAMEN
FOR EACH ROW
DECLARE
nbLi gnes NUMBER;
BEGIN
SELECT count ( ) INTO nbLi gnes
FROM examensPossi bl es
WHERE codMod = : new. codmod ;
IF ( nbLi gnes = 0) THEN
RAISE APPLICATION ERROR( 20002 , Pas d e l `e ve dans ce module . ) ;
END IF ;
END;
/
109

Contrai nte 4

DROP VIEW etudi antsExamens ;


CREATE VIEW etudi antsExamens AS
SELECT I . numetud , E. codmod , E. codexam
FROM INSCRIPTION I , EXAMEN E
WHERE I . codmod = E. codmod
AND I . dat eI ns c < E. dateExam;

CREATE OR REPLACE TRIGGER bef oreInsertUpdateFERResul t


BEFORE INSERT OR UPDATE ON RESULTAT
FOR EACH ROW
DECLARE
nbLi gnes NUMBER;
BEGIN
SELECT count ( ) INTO nbLi gnes
FROM etudi antsExamens
WHERE numetud = : new. numetud
AND codmod = : new. codmod
AND codexam = : new. codexam ;
IF ( nbLi gnes = 0) THEN
RAISE APPLICATION ERROR( 20002 , Examen ant e r i e ur `a l i ns c r i pt i o n dans l e module . ) ;
END IF ;
END;
/

Contrai nte 5

On cree une t ab l e temporaire contenant l e s memes val eurs que prerequi s ,


On l a met `a j our AVANT l a t ab l e prerequi s pour v e r i f i e r que l i ns er t i on
ne cons t r ui t pas de c i r c ui t .
DROP TABLE MIRRORPREREQ;
CREATE TABLE MIRRORPREREQ
( codmod NUMBER,
codmodprereq NUMBER,
noteMin NUMBER) ;

CREATE OR REPLACE FUNCTION


f i ndModul e ( r oot number, moduleToFind number)
RETURN BOOLEAN
IS
CURSOR C IS
SELECT codmod
FROM MIRRORPREREQ
WHERE codmodprereq = r oot ;
SON C%rowtype ;
BEGIN
FOR SON IN C LOOP
IF
( son . codmod = moduleToFind OR
f i ndModul e ( son . codmod , moduleToFind ) )
THEN
RETURN TRUE;
END IF ;
END LOOP;
RETURN FALSE;
END;
/

CREATE OR REPLACE PROCEDURE


i ns e r t Mi r r or Pr e r e q ( codmodValue NUMBER, codmodprereqVal ue NUMBER, note NUMBER) IS
BEGIN
INSERT INTO MIRRORPREREQ
( codmod , codmodprereq , noteMin )
VALUES
( codmodValue , codmodprereqValue , note ) ;
END;
/
110

CREATE OR REPLACE PROCEDURE


del et eMi r r or Pr er eq ( codmodValue NUMBER, codmodprereqVal ue NUMBER) IS
BEGIN
DELETE FROM MIRRORPREREQ
WHERE codmod = codmodValue
AND codmodprereq = codmodprereqVal ue ;
END;
/

CREATE OR REPLACE PROCEDURE


updateMi rrorPrereq
( codmodValue NUMBER,
codmodNewValue NUMBER,
codmodprereqVal ue NUMBER,
codmodprereqNewValue NUMBER,
newNote NUMBER) IS
BEGIN
UPDATE MIRRORPREREQ SET
codmod = codmodNewValue ,
codmodprereq = codmodprereqNewValue ,
noteMin = newNote
WHERE codmod = codmodValue
AND codmodprereq = codmodprereqVal ue ;
END;
/

CREATE OR REPLACE TRIGGER af terDel eteFERPrereq


AFTER DELETE ON PREREQUIS
FOR EACH ROW
BEGIN
del et eMi r r or Pr er eq ( : ol d . codmod , : ol d . codmodprereq ) ;
END;
/

CREATE OR REPLACE TRIGGER bef oreInsertUpdateFERPrereq


BEFORE INSERT OR UPDATE ON PREREQUIS
FOR EACH ROW
BEGIN
IF INSERTING THEN
i ns e r t Mi r r or Pr e r e q ( : new. codmod , : new. codmodprereq , : new. noteMin ) ;
END IF ;
IF UPDATING THEN
updateMi rrorPrereq ( : ol d . codmod , : new. codmod ,
: ol d . codmodprereq , : new. codmodprereq , : new. noteMin ) ;
END IF ;
IF ( f i ndModul e ( : new. codmod , : new. codmod ) ) THEN
IF INSERTING THEN
del et eMi r r or Pr er eq ( : new. codmod , : new. codmodprereq ) ;
END IF ;
IF UPDATING THEN
updateMi rrorPrereq ( : new. codmod , : ol d . codmod ,
: new. codmodprereq , : ol d . codmodprereq , : ol d . noteMin ) ;
END IF ;
RAISE APPLICATION ERROR( 20003 , Ci r c ui t dans pr e r e qui s . ) ;
END IF ;
END;
/

Contrai nte 6

CREATE OR REPLACE FUNCTION


c he c kI ns c r i pt i on ( etud NUMBER, mod NUMBER)
RETURN BOOLEAN
IS
CURSOR pr er eq IS
SELECT noteMin , codmodprereq
FROM MIRRORPREREQ
WHERE codmod = mod;
p pr er eq%rowtype ;
nbLi gnes NUMBER;
BEGIN
111
FOR p IN pr er eq LOOP
SELECT count ( ) INTO nbLi gnes
FROM RESULTAT
WHERE codmod = p . codmodprereq
AND numetud = etud
AND note < p . noteMin ;
IF ( nbLi gnes = 0) THEN
RETURN FALSE;
END IF ;
END LOOP;
RETURN TRUE;
END;
/

CREATE OR REPLACE TRIGGER bef oreInsertUpdateFERInsc


BEFORE INSERT OR UPDATE ON INSCRIPTION
FOR EACH ROW
DECLARE
nbLi gnes NUMBER;
BEGIN
SELECT count ( ) INTO nbLi gnes
FROM modul esDi sponi bl es
WHERE codmod = : new. codmod ;
IF ( nbLi gnes = 0) THEN
RAISE APPLICATION ERROR( 20001 , Pl us de pl ac e s di poni bl e s . ) ;
END IF ;
IF (NOT( c he c kI ns c r i pt i on ( : new. numetud , : new. codmod ) ) ) THEN
RAISE APPLICATION ERROR( 20004 , Prer equi s non s a t i s f a i t . ) ;
END IF ;
END;
/

Contrai nte 7

La aussi un probl eme se pose , on ne peut pas f ai r e de requet e sur


l a t ab l e r es ul t at , comme de pl us , on t i e nt `a prendre pour chaque et udi ant
l e mei l l eure note dans chaque module , on cree une t ab l e temporaire contenant
l e s not es obetnues par l e s el eves .
DROP TABLE MIRRORRESULT;
CREATE TABLE MIRRORRESULT
( numetud NUMBER,
codmod NUMBER,
codexam NUMBER,
note NUMBER,
PRIMARYKEY( numetud , codmod , codexam)
) ;

DROP VIEW MEILLEURENOTE;


CREATE VIEW MEILLEURENOTE AS
SELECT numetud , codmod , MAX( note ) AS noteMax
FROM MIRRORRESULT
GROUP BY numetud , codmod ;

DROP VIEW NOMBREINSCRIPTIONs;


CREATE VIEW NOMBREINSCRIPTIONS AS
SELECT numetud ,
(
SELECT COUNT( )
FROM INSCRIPTION I
WHERE I . numetud = E. numetud
) AS nbI ns c r i pt i ons
FROM ETUDIANT E;

DROP VIEW NOMBRENOTES;


CREATE VIEW NOMBRENOTES AS
SELECT numetud ,
112
(SELECT COUNT( ) AS nbNotes
FROM MEILLEURENOTE M
WHEREM. numetud = E. numetud
) AS nbNotes
FROM ETUDIANT E;

CREATE OR REPLACE PROCEDURE


updateMoyenne ( etud NUMBER)
IS
nbNotes NUMBER;
nbI ns c r i pt i ons NUMBER;
BEGIN
SELECT nbNotes INTO nbNotes
FROM NOMBRENOTES
WHERE numetud = etud ;
SELECT nbI ns c r i pt i ons INTO nbI Ns cr i pt i ons
FROM NOMBREINSCRIPTIONS
WHERE numetud = etud ;
IF ( nbNotes = nbI ns c r i pt i ons ) THEN
UPDATE ETUDIANT SET moyenne =
(SELECT AVG( noteMax)
FROM MEILLEURENOTE
WHERE numetud = etud
)
WHERE numetud = etud ;
ELSE
UPDATE ETUDIANT SET
moyenne = NULL
WHERE numetud = etud ;
END IF ;
END;
/

CREATE OR REPLACE TRIGGER af t er I ns er t FERRes ul t


AFTER INSERT ON RESULTAT
FOR EACH ROW
BEGIN
INSERT INTO MIRRORRESULT VALUES
( : new. numetud , : new. codmod , : new. codexam , : new. note ) ;
updateMoyenne ( : new. numetud ) ;
END;
/

CREATE OR REPLACE TRIGGER afterUpdateFERResul t


AFTER UPDATE ON RESULTAT
FOR EACH ROW
BEGIN
UPDATE MIRRORRESULT SET
numetud = : new. numetud ,
codmod = : new. codmod ,
codexam = : new. codexam ,
note = : new. note
WHERE numetud = : ol d . numetud
AND codmod = : ol d . codmod
AND codexam = : ol d . codexam ;
updateMoyenne ( : new. numetud ) ;
END;
/

CREATE OR REPLACE TRIGGER af terDel eteFERResul t


AFTER DELETE ON RESULTAT
FOR EACH ROW
BEGIN
DELETE FROM MIRRORRESULT
WHERE numetud = : new. numetud
AND codmod = : new. codmod
AND codexam = : new. codexam ;
updateMoyenne ( : new. numetud ) ;
END;
/

Contrai nte 9
113

CREATE OR REPLACE FUNCTION


checkAl l St udent s
RETURN BOOLEAN
IS
CURSOR C IS
SELECT numetud , codmod
FROM INSCRIPTION;
e C%rowtype ;
BEGIN
FOR e IN C LOOP
IF (NOT( c he c kI ns c r i pt i on ( e . numetud , e . codmod ) ) ) THEN
RETURN FALSE;
END IF ;
END LOOP;
RETURN TRUE;
END;
/

CREATE OR REPLACE TRIGGER BeforeUpdateFERModule


BEFORE UPDATE ON MODULE
FOR EACH ROW
BEGIN
IF ( : new. ef f ecmax < : new. e f f e c ) THEN
RAISE APPLICATION ERROR( 20005 ,
L e f f e c t i f ne peut e t r e en dessous de | | : new. e f f e c ) ;
END IF ;
END;
/

Contrai nte 8

CREATE OR REPLACE TRIGGER bef oreInsertUpdateFERPrereq


BEFORE INSERT OR UPDATE ON PREREQUIS
FOR EACH ROW
BEGIN
IF INSERTING THEN
i ns e r t Mi r r or Pr e r e q ( : new. codmod , : new. codmodprereq , : new. noteMin ) ;
END IF ;
IF UPDATING THEN
updateMi rrorPrereq ( : ol d . codmod , : new. codmod ,
: ol d . codmodprereq , : new. codmodprereq , : new. noteMin ) ;
END IF ;
IF ( f i ndModul e ( : new. codmod , : new. codmod ) ) THEN
IF INSERTING THEN
del et eMi r r or Pr er eq ( : new. codmod , : new. codmodprereq ) ;
END IF ;
IF UPDATING THEN
updateMi rrorPrereq ( : new. codmod , : ol d . codmod ,
: new. codmodprereq , : ol d . codmodprereq , : ol d . noteMin ) ;
END IF ;
RAISE APPLICATION ERROR( 20003 , Ci r c ui t dans pr e r e qui s . ) ;
END IF ;
IF(NOT( checkAl l St udent s ( ) ) ) THEN
IF INSERTING THEN
del et eMi r r or Pr er eq ( : new. codmod , : new. codmodprereq ) ;
END IF ;
IF UPDATING THEN
updateMi rrorPrereq ( : new. codmod , : ol d . codmod ,
: new. codmodprereq , : ol d . codmodprereq , : ol d . noteMin ) ;
END IF ;
RAISE APPLICATION ERROR( 20006 , I mpos s i bl e de di mi nuer c e t t e note . ) ;
END IF ;
END;
/

Quel ques i ns er t i ons pour t e s t e r

INSERT INTO ETUDIANT VALUES


(
(SELECT nvl (MAX(numEtud) , 0) + 1 FROM ETUDIANT) ,
Four i er ,
Joseph ,
t o dat e ( 21031768 , ddmmyyyy ) ,
Mr ,
NULL,
168031234567890 ,
NULL
) ;
114
INSERT INTO MODULE
( codMod , nomMod)
VALUES
(
(SELECT nvl (MAX( codMod) , 0) + 1 FROM MODULE) ,
Maths
) ;
INSERT INTO INSCRIPTION
( codMod , numEtud)
VALUES
(
(SELECT numEtud FROM ETUDIANT WHERE nom = Four i er ) ,
(SELECT codMod FROM MODULE WHERE nomMod = Maths )
) ;
INSERT INTO EXAMEN VALUES
(
(SELECT codMod FROM MODULE WHERE nomMod = Maths ) ,
1 ,
t o dat e ( 02012008 , ddmmyyyy )
) ;
INSERT INTO RESULTAT VALUES
(
(SELECT codMod FROM MODULE WHERE nomMod = Maths ) ,
1 ,
(SELECT numEtud FROM ETUDIANT WHERE nom = Four i er ) ,
19 ) ;
UPDATE RESULTAT SET
note = 20
wHERE
numEtud = (SELECT numEtud FROM ETUDIANT WHERE nom = Four i er )
AND codMod = (SELECT codMod FROM MODULE WHERE nomMod = Maths )
AND codExam = 1;
INSERT INTO MODULE VALUES
( 2 , Algo , 30 , 22) ;
INSERT INTO PREREQUIS VALUES
( 1 , 2 , 10) ;
INSERT INTO PREREQUIS VALUES
( 2 , 1 , 10) ;
UPDATE PREREQUIS SET noteMin = 2;
INSERT INTO EXAMEN VALUES ( 2 , 1 , s ys dat e ) ;
115
3.17 Packages
CREATE OR REPLACE PACKAGE BODY ge s t i on ar br e IS
cur s or f e u i l l e s r et ur n personne%rowtype IS
SELECT FROM PERSONNE;
PROCEDURE aj outePersonne (nom personne . nom%type ,
prenom personne . prenom%type , pere personne . pere%type ,
mere personne . mere%type ) IS
BEGIN
INSERT INTO PERSONNE VALUES (
(SELECT nvl (MAX( numpers ) , 0) + 1 FROM PERSONNE) ,
nom, prenom , pere , mere ) ;
END;
FUNCTION descendDe ( numpers personne . numpers%type ,
descendant personne . numpers%type ) RETURN BOOLEAN IS
BEGIN
IF ( descendant IS NULL) THEN
RETURN FALSE;
ELSIF ( descendant = numpers ) THEN
RETURN TRUE;
ELSE
DECLARE
per s PERSONNE%rowtype ;
BEGIN
SELECT INTO per s
FROM PERSONNE
WHERE numpers = descendant ;
RETURN descendDe ( numpers , per s . pere )
OR descendDe ( numpers , per s . mere ) ;
END;
END IF ;
END;
procedure modi f i ePar ent s ( per s personne . numpers%type ,
numPere personne . pere%type , numMere personne . mere%type ) IS
BEGIN
IF ( descendDe ( pers , numPere ) OR descendDe ( pers , numMere ) ) THEN
RAISE CIRCUIT;
END IF ;
UPDATE PERSONNE SET pere = numPere , mere = numMere
WHERE numPers = per s ;
END;
END;
/
CALL ges t i on Ar br e . modi f i ePar ent s ( 20 , 14 , 15) ;
116
3.18 Revisions
Preparat i f s . . .
DROP TABLE MIRRORPERSONNE;
CREATE TABLE MIRRORPERSONNE
(
numpers NUMBERPRIMARY KEY,
pere NUMBER,
mere NUMBER
) ;
CREATE OR REPLACE TRIGGER mi seAJourMi rrorPersonne
BEFORE UPDATE OR INSERT OR DELETE ON PERSONNE
FOR EACH ROW
BEGIN
IF DELETING OR UPDATING THEN
DELETE FROM MIRRORPERSONNE
WHERE numpers = : ol d . numpers ;
END IF ;
IF INSERTING OR UPDATING THEN
INSERT INTO MIRRORPERSONNE VALUES
( : new. numpers , : new. pere , : new. mere ) ;
END IF ;
END;
/
DROP TABLE MIRRORMARIAGE;
CREATE TABLE MIRRORMARIAGE
(
nummari NUMBER,
numfemme NUMBER,
datemari age DATE,
dat edi vor ce DATE
) ;
CREATE OR REPLACE TRIGGER mi seAJourMi rrorMari age
BEFORE UPDATE OR INSERT OR DELETE ON MARIAGE
FOR EACH ROW
BEGIN
IF DELETING OR UPDATING THEN
DELETE FROM MIRRORMARIAGE
WHERE nummari = : ol d . nummari
AND numfemme = : ol d . numfemme
AND datemari age = : ol d . datemari age ;
END IF ;
IF INSERTING OR UPDATING THEN
INSERT INTO MIRRORMARIAGE VALUES
( : new. nummari , : new. numfemme , : new. datemari age , : new. dat edi vor ce ) ;
END IF ;
END;
/
Contrai nte 1
ALTER TABLE PERSONNE ADDCONSTRAINT c k pa r e nt s di f f e r e nt s CHECK( pere <> mere ) ;
Contrai nte 2
CREATE OR REPLACE PACKAGE c ont r ai nt e Ci r c ui t IS
CIRCUIT EXCEPTION;
PROCEDURE v e r i f i e Ci r c u i t ( per s personne . numpers%type ) ;
FUNCTION descendDe ( numpers personne . numpers%type ,
descendant personne . numpers%type ) RETURN BOOLEAN;
END;
/
CREATE OR REPLACE TRIGGER ve r i f i e Co nt r a i nt e Ci r c ui t
AFTER UPDATE OR INSERT ON PERSONNE
FOR EACH ROW
BEGIN
c ont r ai nt e Ci r c ui t . v e r i f i e Ci r c u i t ( : new. numPers ) ;
END;
/
CREATE OR REPLACE PACKAGE BODY c ont r ai nt e Ci r c ui t IS
FUNCTION descendDe ( numpers personne . numpers%type ,
descendant personne . numpers%type ) RETURN BOOLEAN IS
BEGIN
IF ( descendant IS NULL) THEN
RETURN FALSE;
ELSIF ( descendant = numpers ) THEN
RETURN TRUE;
ELSE
DECLARE
117
per s MIRRORPERSONNE%rowtype ;
BEGIN
SELECT INTO per s
FROM MIRRORPERSONNE
WHERE numpers = descendant ;
RETURN descendDe ( numpers , per s . pere )
OR descendDe ( numpers , per s . mere ) ;
END;
END IF ;
END;
PROCEDURE v e r i f i e Ci r c u i t ( per s personne . numpers%type ) IS
l i g ne mi r r or per sonne%rowtype ;
BEGIN
SELECT INTO LIGNE
FROM mi r r or per sonne
WHERE numpers = per s ;
IF ( descendDe ( pers , l i g ne . pere ) OR descendDe ( pers , l i g ne . mere ) ) THEN
RAISE CIRCUIT;
END IF ;
END;
END;
/
Contrai nte 3
ALTER TABLE MARIAGE ADDCONSTRAINT ck dat es mar i age CHECK( dateDi vorce IS NULL OR dateMari age <= dateDi vorce ) ;
Contrai nte 4
CREATE OR REPLACE PACKAGE cont r ai nt es Mar i ages IS
mari agesSuperposes EXCEPTION;
PROCEDURE ve r i f i e Mar i age s Supe r pos e s ( nouveauMariage mari age%rowtype ) ;
END cont r ai nt es Mar i ages ;
/
CREATE OR REPLACE TRIGGER ve r i f i e Cont r ai nt e s Mar i age s
BEFORE UPDATE OR INSERT ON MARIAGE
FOR EACH ROW
DECLARE
nouveauMariage MARIAGE%rowtype ;
BEGIN
nouveauMariage . numMari := : new. numMari ;
nouveauMariage . numFemme := : new. numFemme;
nouveauMariage . dateMari age := : new. dateMari age ;
nouveauMariage . dateDi vorce := : new. dateDi vorce ;
cont r ai nt es Mar i ages . ve r i f i e Mar i age s Supe r pos e s ( nouveauMariage ) ;
END;
/
CREATE OR REPLACE PACKAGE BODY cont r ai nt es Mar i ages IS
FUNCTION seSuperposent (m1 mi rrorMari age%rowtype , m2 mi rrorMari age%rowtype ) RETURN BOOLEAN IS
BEGIN
IF (m1. nummari <> m2. nummari OR m1. numfemme <> m2. numfemme) THEN
RETURN FALSE;
END IF ;
RETURN NOT(
(m2. dat edi vor ce IS NOT NULL AND m1. dateMari age <= m2. dateDi vorce )
OR (m1. dat edi vor ce IS NOT NULL AND m2. dateMari age <= m1. dateDi vorce )
) ;
END;
PROCEDURE ve r i f i e Mar i age s Supe r pos e s ( nouveauMariage mari age%rowtype ) IS
CURSOR aut r esMar i ages IS
SELECT FROM MIRRORMARIAGE
WHERE numMari = nouveauMariage . numMari
OR numFemme = nouveauMariage . numFemme;
autreMari age aut r esMar i ages%ROWTYPE;
BEGIN
FOR autreMari age IN aut r es Mar i ages LOOP
IF ( seSuperposent ( nouveauMariage , autreMari age ) ) THEN
RAISE mari agesSuperposes ;
END IF ;
END LOOP;
END;
END cont r ai nt es Mar i ages ;
/
Cont rai nt es 5 et 6
CREATE OR REPLACE package cont r ai nt es Tr ans IS
t r ans EXCEPTION;
PROCEDURE ve r i f i e Pe r e Me r e ( nouvel l ePer s onne MIRRORPERSONNE%rowtype ) ;
PROCEDURE veri f i eMari Femme ( nouveauMariage MARIAGE%rowtype ) ;
118
end cont r ai nt es Tr ans ;
/
CREATE OR REPLACE TRIGGER pereMere
AFTER UPDATE OR INSERT ON PERSONNE
FOR EACH ROW
DECLARE
nouvel l ePer s onne MIRRORPERSONNE%rowtype ;
BEGIN
nouvel l ePer s onne . numpers := : new. numpers ;
nouvel l ePer s onne . pere := : new. pere ;
nouvel l ePer s onne . mere := : new. mere ;
cont r ai nt es Tr ans . ve r i f i e Pe r e Me r e ( nouvel l ePer s onne ) ;
END;
/
CREATE OR REPLACE TRIGGER mariFemme
AFTER UPDATE OR INSERT ON MARIAGE
FOR EACH ROW
DECLARE
nouveauMariage MARIAGE%rowtype ;
BEGIN
nouveauMariage . numMari := : new. numMari ;
nouveauMariage . numFemme := : new. numFemme;
nouveauMariage . dateMari age := : new. dateMari age ;
nouveauMariage . dateDi vorce := : new. dateDi vorce ;
cont r ai nt es Tr ans . veri f i eMari Femme ( nouveauMariage ) ;
END;
/
CREATE OR REPLACE package BODY cont r ai nt es Tr ans IS
PROCEDURE ve r i f i e Pe r e Me r e ( nouvel l ePer sonne MIRRORPERSONNE%rowtype ) IS
nb INT;
BEGIN
SELECT COUNT( ) INTO nb
FROM MIRRORPERSONNE
WHERE pere = nouvel l ePer sonne . mere
OR mere = nouvel l ePer s onne . pere ;
IF ( nb <> 0) THEN
RAISE TRANS;
END IF ;
SELECT COUNT( ) INTO nb
FROM MIRRORMARIAGE
WHERE numMari = nouvel l ePer s onne . mere
OR numFemme = nouvel l ePer s onne . pere ;
IF ( nb <> 0) THEN
RAISE TRANS;
END IF ;
END;
PROCEDURE veri f i eMari Femme ( nouveauMariage MARIAGE%rowtype ) IS
nb INT;
BEGIN
SELECT COUNT( ) INTO nb
FROM MIRRORMARIAGE
WHERE numMari = nouveauMariage . numFemme
OR numFemme = nouveauMariage . numMari ;
IF ( nb <> 0) THEN
RAISE TRANS;
END IF ;
SELECT COUNT( ) INTO nb
FROM MIRRORPERSONNE
WHERE pere = nouveauMariage . numFemme
OR mere = nouveauMariage . numMari ;
IF ( nb <> 0) THEN
RAISE TRANS;
END IF ;
END;
END cont r ai nt es Tr ans ;
/
Contrai nte 7
CREATE OR REPLACE PACKAGE contrai nteMari ageConsangui n IS
Mari ageConsangui n EXCEPTION;
PROCEDURE ver i f i eMar i ageCons angui n ( nouveauMariage MARIAGE%rowtype ) ;
END contrai nteMari ageConsangui n ;
/
CREATE OR REPLACE TRIGGER mari ageConsangui n
AFTER UPDATE OR INSERT ON MARIAGE
FOR EACH ROW
DECLARE
nouveauMariage MARIAGE%rowtype ;
BEGIN
119
nouveauMariage . numMari := : new. numMari ;
nouveauMariage . numFemme := : new. numFemme;
nouveauMariage . dateMari age := : new. dateMari age ;
nouveauMariage . dateDi vorce := : new. dateDi vorce ;
contrai nteMari ageConsangui n . ver i f i eMar i ageCons angui n ( nouveauMariage ) ;
END;
/
CREATE OR REPLACE PACKAGE BODY contrai nteMari ageConsangui n IS
FUNCTION pere ( p PERSONNE. numpers%type ) RETURN PERSONNE. numpers%type IS
numPere PERSONNE. numpers%type ;
BEGIN
SELECT pere INTO numPere
FROM MIRRORPERSONNE
WHERE numpers = p ;
RETURN numPere ;
EXCEPTION
WHEN NO DATA FOUND THEN
RETURN NULL;
END;
FUNCTION mere ( p PERSONNE. numpers%type ) RETURN PERSONNE. numpers%type IS
numMere PERSONNE. numpers%type ;
BEGIN
SELECT mere INTO numMere
FROM MIRRORPERSONNE
WHERE numpers = p ;
RETURN numMere ;
EXCEPTION
WHEN NO DATA FOUND THEN
RETURN NULL;
END;
FUNCTION rechercheAncetreCommun ( a PERSONNE. numpers%type ,
b PERSONNE. numpers%type ) RETURN BOOLEAN IS
BEGIN
IF ( a IS NULL) THEN
RETURN FALSE;
ELSE
RETURN ( c ont r ai nt e Ci r c ui t . descendDe ( a , b) ) OR rechercheAncetreCommun ( pere ( a ) , b) OR rechercheAncetreCommun ( mere ( a ) , b ) ;
END IF ;
END;
PROCEDURE ver i f i eMar i ageCons angui n ( nouveauMariage MARIAGE%rowtype ) IS
BEGIN
IF ( rechercheAncetreCommun ( nouveauMariage . numMari , nouveauMariage . numFemme) ) THEN
RAISE Mari ageConsangui n ;
END IF ;
END;
END contrai nteMari ageConsangui n ;
/
120
Annexe A
Scripts de creation de bases
A.1 Livraisons Sans contraintes
Attention : Le numero de livraison est une cle secondaire, cest-`a-dire un numero unique etant donne un fournisseur.
CREATE TABLE PRODUIT
( numprod number,
nomprod varchar2 ( 3 0 ) ) ;
CREATE TABLE FOURNISSEUR
( numfou number,
nomfou varchar2 ( 3 0 ) ) ;
CREATE TABLE PROPOSER
( numfou number,
numprod number,
pr i x number ) ;
CREATE TABLE LIVRAISON
( numfou number,
numli number,
da t e l i date default s ys dat e
) ;
CREATE TABLE DETAILLIVRAISON
( numfou number,
numli number,
numprod number,
qte number ) ;
121
A.2 Modules et prerequis
les modules sont repertories dans une table, et les modules pre-requis pour sy inscrire (avec la note minimale) se
trouvent dans la table prerequis. Une ligne de la table PREREQUIS nous indique que pour sinscrire dans le module
numero numMod, il faut avoir eu au moins noteMin au module numModPrereq.
CREATE TABLE MODULE
(numMod number primary key ,
nomMod varchar2 ( 30)
) ;
CREATE TABLE PREREQUIS
(
numMod number r e f e r e nc e s MODULE(numMod) ,
numModPrereq number r e f e r e nc e s MODULE(numMod) ,
noteMin number( 2) DEFAULT 10 NOT NULL ,
PRIMARYKEY(numMod, numModPrereq)
) ;
INSERT INTO MODULE VALUES ( 1 , Oracl e ) ;
INSERT INTO MODULE VALUES ( 2 , C++ ) ;
INSERT INTO MODULE VALUES ( 3 , C ) ;
INSERT INTO MODULE VALUES ( 4 , Algo ) ;
INSERT INTO MODULE VALUES ( 5 , Meri se ) ;
INSERT INTO MODULE VALUES ( 6 , PL/SQL Oracl e ) ;
INSERT INTO MODULE VALUES ( 7 , mySQL ) ;
INSERT INTO MODULE VALUES ( 8 , Algo avanc

A c e ) ;
INSERT INTO PREREQUIS (numMod, numModPrereq) VALUES ( 1 , 5 ) ;
INSERT INTO PREREQUIS (numMod, numModPrereq) VALUES ( 2 , 3 ) ;
INSERT INTO PREREQUIS VALUES ( 6 , 1 , 12) ;
INSERT INTO PREREQUIS (numMod, numModPrereq) VALUES ( 6 , 5 ) ;
INSERT INTO PREREQUIS (numMod, numModPrereq) VALUES ( 8 , 5 ) ;
INSERT INTO PREREQUIS (numMod, numModPrereq) VALUES ( 7 , 5 ) ;
122
A.3 Geometrie
La table INTERVALLE contient des intervalles species par leurs bornes inferieure et superieure. Supprimer de la
table intervalle tous les intervalles qui nen sont pas avec une seule instruction.
CREATE TABLE INTERVALLE
( bor neI nf NUMBER,
borneSup NUMBER,
PRIMARYKEY ( borneI nf , borneSup ) ) ;
CREATE TABLE RECTANGLE
( xHautGauche NUMBER,
yHautGauche NUMBER,
xBasDroi t NUMBER,
yBasDroi t NUMBER,
PRIMARYKEY ( xHautGauche , yHautGauche , xBasDroi t , yBasDroi t ) ) ;
INSERT INTO INTERVALLE VALUES ( 2 , 56) ;
INSERT INTO INTERVALLE VALUES ( 12 , 30) ;
INSERT INTO INTERVALLE VALUES ( 2 , 3 ) ;
INSERT INTO INTERVALLE VALUES ( 12 , 3 ) ;
INSERT INTO INTERVALLE VALUES ( 8 , 27) ;
INSERT INTO INTERVALLE VALUES ( 34 , 26) ;
INSERT INTO INTERVALLE VALUES ( 5 , 10) ;
INSERT INTO INTERVALLE VALUES ( 7 , 32) ;
INSERT INTO INTERVALLE VALUES ( 0 , 30) ;
INSERT INTO INTERVALLE VALUES ( 21 , 8 ) ;
INSERT INTO RECTANGLE VALUES ( 2 , 12 , 5 , 7 ) ;
INSERT INTO RECTANGLE VALUES ( 2 , 12 , 1 , 13) ;
INSERT INTO RECTANGLE VALUES ( 10 , 13 , 1 , 11) ;
INSERT INTO RECTANGLE VALUES ( 10 , 13 , 10 , 11) ;
INSERT INTO RECTANGLE VALUES ( 2 , 7 , 5 , 13) ;
INSERT INTO RECTANGLE VALUES ( 21 , 73 , 15 , 22) ;
INSERT INTO RECTANGLE VALUES ( 1 , 2 , 3 , 4 ) ;
INSERT INTO RECTANGLE VALUES ( 1 , 5 , 3 , 2 ) ;
INSERT INTO RECTANGLE VALUES ( 1 , 6 , 3 , 6 ) ;
INSERT INTO RECTANGLE VALUES ( 4 , 2 , 1 , 4 ) ;
INSERT INTO RECTANGLE VALUES ( 2 , 3 , 4 , 0 ) ;
INSERT INTO RECTANGLE VALUES ( 5 , 4 , 2 , 1 ) ;
123
A.4 Livraisons
CREATE TABLE PRODUIT
( numprod number,
nomprod varchar2 ( 3 0 ) ) ;
CREATE TABLE FOURNISSEUR
( numfou number,
nomfou varchar2 ( 3 0 ) ) ;
CREATE TABLE PROPOSER
( numfou number,
numprod number,
pr i x number NOT NULL) ;
CREATE TABLE LIVRAISON
( numfou number,
numli number,
da t e l i date default s ys dat e
) ;
CREATE TABLE DETAILLIVRAISON
( numfou number,
numli number,
numprod number,
qte number NOT NULL) ;
al ter table pr odui t add constraint pk pr odui t
PRIMARYKEY ( numprod ) ;
al ter table f o ur ni s s e ur add constraint pk f our ni s s e ur
PRIMARYKEY ( numfou ) ;
al ter table pr oposer add constraint pk pr oposer
PRIMARYKEY ( numfou , numprod ) ;
al ter table l i v r a i s o n add constraint pk l i vr a i s o n
PRIMARYKEY ( numfou , numli ) ;
al ter table 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
PRIMARYKEY ( numfou , numli , numprod ) ;
al ter table pr oposer add constraint f k pr o po s e r f o ur ni s s e ur
FOREIGN KEY ( numfou) REFERENCES f o ur ni s s e ur ( numfou ) ;
al ter table pr oposer add constraint f k pr opos e r pr odui t
FOREIGN KEY ( numprod) REFERENCES pr odui t ( numprod ) ;
al ter table l i v r a i s o n add constraint f k l i v r a i s o n
FOREIGN KEY ( numfou) REFERENCES f o ur ni s s e ur ( numfou ) ;
al ter table d e t a i l l i v r a i s o n add constraint 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 ) ;
al ter table d e t a i l l i v r a i s o n add constraint 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 pr oposer ( numfou , numprod ) ;
INSERT INTO PRODUIT values ( 1 , Roue de s ecour s ) ;
INSERT INTO PRODUIT values ( 2 , Poup

A c e Batman ) ;
INSERT INTO PRODUIT values ( 3 , Cotons t i g e s ) ;
INSERT INTO PRODUIT values ( 4 , Corni chons ) ;
INSERT INTO FOURNISSEUR values ( 1 , f 1 ) ;
INSERT INTO FOURNISSEUR values ( 2 , f 2 ) ;
INSERT INTO FOURNISSEUR values ( 3 , f 3 ) ;
INSERT INTO FOURNISSEUR values ( 4 , f 4 ) ;
INSERT INTO PROPOSER values ( 1 , 1 , 200) ;
INSERT INTO PROPOSER values ( 1 , 2 , 15) ;
INSERT INTO PROPOSER values ( 2 , 2 , 1 ) ;
INSERT INTO PROPOSER values ( 3 , 3 , 2 ) ;
INSERT INTO LIVRAISON ( numfou , numli ) values ( 1 , 1 ) ;
INSERT INTO LIVRAISON ( numfou , numli ) values ( 1 , 2 ) ;
INSERT INTO LIVRAISON ( numfou , numli ) values ( 3 , 1 ) ;
INSERT INTO DETAILLIVRAISON values ( 3 , 1 , 3 , 10) ;
INSERT INTO DETAILLIVRAISON values ( 1 , 1 , 1 , 25) ;
INSERT INTO DETAILLIVRAISON values ( 1 , 1 , 2 , 20) ;
INSERT INTO DETAILLIVRAISON values ( 1 , 2 , 1 , 15) ;
INSERT INTO DETAILLIVRAISON values ( 1 , 2 , 2 , 17) ;
124
A.5 Arbre genealogique
La table PERSONNE, le champ pere contient le numero du p`ere de la personne, le champ mere contient le numero
de la m`ere de la personne.
CREATE TABLE PERSONNE
( numpers number PRIMARY KEY,
nom varchar2 ( 30) NOT NULL,
prenom varchar2 ( 30) ,
pere REFERENCES PERSONNE( numpers ) ,
mere REFERENCES PERSONNE( numpers )
) ;
INSERT INTO PERSONNE VALUES ( 1 , de Montmi rai l , di t l e Hardi , Godefroy , NULL, NULL) ;
INSERT INTO PERSONNE VALUES ( 16 , ET , NULL, NULL, NULL) ;
INSERT INTO PERSONNE VALUES ( 2 , Le Croquant , Jacqou , 1 , 16) ;
INSERT INTO PERSONNE VALUES ( 3 , La Fr i po ui l l e , Ja c qo ui l l e , 1 , 16) ;
INSERT INTO PERSONNE VALUES ( 4 , Bush , Kate , NULL, NULL) ;
INSERT INTO PERSONNE VALUES ( 13 , Granger , Hermione , NULL, NULL) ;
INSERT INTO PERSONNE VALUES ( 5 , Du F

Ac mur , M

A c dor , 3 , 4 ) ;
INSERT INTO PERSONNE VALUES ( 12 , Kobalevska

Aa , Sof i a , NULL, NULL) ;


INSERT INTO PERSONNE VALUES ( 6 , Rieu , Andr

A c , NULL, NULL) ;
INSERT INTO PERSONNE VALUES ( 7 , Bontoutou , Rex , 6 , 4 ) ;
INSERT INTO PERSONNE VALUES ( 8 , Di j ks t r a , Edvard , 2 , 13) ;
INSERT INTO PERSONNE VALUES ( 9 , Lei bni z , Got t f r i e1d Wilhem , 8 , 12) ;
INSERT INTO PERSONNE VALUES ( 10 , Bach , Johann Sebas t i en , 5 , 12) ;
INSERT INTO PERSONNE VALUES ( 17 , Mathieu , Mi r e i l l e , NULL, NULL) ;
INSERT INTO PERSONNE VALUES ( 11 , Lemarchal , Gregory , 10 , 17) ;
INSERT INTO PERSONNE VALUES ( 15 , Socr at e , NULL, 3 , 13) ;
INSERT INTO PERSONNE VALUES ( 19 , Leroy , Nolwen , NULL, NULL) ;
INSERT INTO PERSONNE VALUES ( 20 , Bar t ol i , Je nni f e r , 9 , 19) ;
INSERT INTO PERSONNE VALUES ( 21 , Fabian , Lara , 10 , 17) ;
INSERT INTO PERSONNE VALUES ( 14 , Stone , Sharon , 15 , 20) ;
INSERT INTO PERSONNE VALUES ( 18 , Frege , El odi e , 7 , 13) ;
125
A.6 Comptes bancaires
DROP TABLE OPERATION;
DROP TABLE TYPEOPERATION;
DROP TABLE COMPTECLIENT;
DROP TABLE TYPECCL;
DROP TABLE PERSONNEL;
DROP TABLE CLIENT;
CREATE TABLE CLIENT
( numcl i number,
nomcl i varchar2 ( 30) ,
prenomcl i varchar2 ( 30) ,
adr es s e varchar2 ( 60) ,
t e l varchar ( 10)
) ;
CREATE TABLE PERSONNEL
( numpers number,
nompers varchar2 ( 30) ,
prenompers varchar2 ( 30) ,
manager number,
s a l a i r e number
) ;
CREATE TABLE TYPECCL
( numtypeccl number,
nomtypeccl varchar2 ( 30)
) ;
CREATE TABLE COMPTECLIENT
( numcl i number,
numccl number,
numtypeccl number,
dat e c c l date default s ys dat e not null ,
numpers number
) ;
CREATE TABLE TYPEOPERATION
( numtypeoper number,
nomtypeoper varchar2 ( 30)
) ;
CREATE TABLE OPERATION
( numcl i number,
numccl number,
numoper number,
numtypeoper number,
dateoper date default s ys dat e not null ,
montantoper number not null ,
l i be l o pe r varchar2 ( 30)
) ;
ALTER TABLE CLIENT ADD
(
CONSTRAINT pk c l i e nt PRIMARYKEY ( numcl i ) ,
CONSTRAINT ck t el ephone CHECK(LENGTH( t e l )=10)
) ;
ALTER TABLE PERSONNEL ADD
(
CONSTRAINT pk per s onnel PRIMARYKEY ( numpers ) ,
CONSTRAINT c k s a l a i r e CHECK(SALAIRE >= 1254. 28)
) ;
ALTER TABLE TYPECCL ADD
CONSTRAINT pk t ypeccl PRIMARYKEY ( numtypeccl ) ;
ALTER TABLE TYPEOPERATION ADD
CONSTRAINT pk t ypeoper at i on PRIMARYKEY ( numtypeoper ) ;
ALTER TABLE COMPTECLIENT ADD
(
CONSTRAINT pk compt ecl i ent
PRIMARYKEY ( numcli , numccl ) ,
CONSTRAINT f k c c l t y p e c c l
FOREIGN KEY ( numtypeccl )
REFERENCES TYPECCL ( numtypeccl ) ,
CONSTRAINT f k c c l c l i e n t
FOREIGN KEY ( numcl i )
REFERENCES CLIENT ( numcl i ) ,
CONSTRAINT f k c c l pe r s o nne l
FOREIGN KEY ( numpers )
REFERENCES PERSONNEL ( numpers )
) ;
ALTER TABLE OPERATION ADD
(
126
CONSTRAINT pk oper at i on
PRIMARYKEY ( numcli , numccl , numoper ) ,
CONSTRAINT f k o pe r c c l
FOREIGN KEY ( numcli , numoper )
REFERENCES COMPTECLIENT ( numcli , numccl ) ,
CONSTRAINT f k ope r c ode ope r
FOREIGN KEY ( numtypeoper )
REFERENCES t ypeoper at i on ( numtypeoper ) ,
CONSTRAINT montant operati on
CHECK( montantoper <> 0)
) ;
INSERT INTO TYPECCL VALUES (
(SELECT nvl (MAX( numtypeccl ) , 0) + 1
FROM TYPECCL
) ,
Compte courant ) ;
INSERT INTO TYPECCL VALUES (
(SELECT nvl (MAX( numtypeccl ) , 0) + 1
FROM TYPECCL
) ,
l i v r e t ) ;
INSERT INTO TYPECCL VALUES (
(SELECT nvl (MAX( numtypeccl ) , 0) + 1
FROM TYPECCL
) ,
PEL ) ;
INSERT INTO TYPEOPERATION VALUES (
(SELECT nvl (MAX( numtypeoper ) , 0) + 1
FROM TYPEOPERATION
) ,
d

A c p

At esp

Aces ) ;
INSERT INTO TYPEOPERATION VALUES (
(SELECT nvl (MAX( numtypeoper ) , 0) + 1
FROM TYPEOPERATION
) ,
pr

A c l

Avement ) ;
INSERT INTO TYPEOPERATION VALUES (
(SELECT nvl (MAX( numtypeoper ) , 0) + 1
FROM TYPEOPERATION
) ,
vi rement ) ;
INSERT INTO TYPEOPERATION VALUES (
(SELECT nvl (MAX( numtypeoper ) , 0) + 1
FROM TYPEOPERATION
) ,
r e t r a i t ) ;
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;
CREATE TABLE CLIENT
( numcl i number,
nomcl i varchar2 ( 30) ,
prenomcl i varchar2 ( 30) ,
adr es s e varchar2 ( 60) ,
t e l varchar ( 10)
) ;
CREATE TABLE PERSONNEL
( numpers number,
nompers varchar2 ( 30) ,
prenompers varchar2 ( 30) ,
manager number,
s a l a i r e number
) ;
CREATE TABLE TYPECCL
( numtypeccl number,
nomtypeccl varchar2 ( 30)
) ;
CREATE TABLE COMPTECLIENT
( numcl i number,
numccl number,
numtypeccl number,
dat e c c l date default s ys dat e not null ,
numpers number
) ;
CREATE TABLE TYPEOPERATION
( numtypeoper number,
nomtypeoper varchar2 ( 30)
) ;
CREATE TABLE OPERATION
( numcl i number,
numccl number,
numoper number,
numtypeoper number,
dateoper date default s ys dat e not null ,
montantoper number not null ,
l i be l o pe r varchar2 ( 30)
) ;
ALTER TABLE CLIENT ADD
(
CONSTRAINT pk c l i e nt PRIMARYKEY ( numcl i ) ,
CONSTRAINT ck t el ephone CHECK(LENGTH( t e l )=10)
) ;
ALTER TABLE PERSONNEL ADD
(
CONSTRAINT pk per s onnel PRIMARYKEY ( numpers ) ,
CONSTRAINT c k s a l a i r e CHECK(SALAIRE >= 1254. 28)
) ;
ALTER TABLE TYPECCL ADD
CONSTRAINT pk t ypeccl PRIMARYKEY ( numtypeccl ) ;
ALTER TABLE TYPEOPERATION ADD
CONSTRAINT pk t ypeoper at i on PRIMARYKEY ( numtypeoper ) ;
ALTER TABLE COMPTECLIENT ADD
(
CONSTRAINT pk compt ecl i ent
PRIMARYKEY ( numcli , numccl ) ,
CONSTRAINT f k c c l t y p e c c l
FOREIGN KEY ( numtypeccl )
REFERENCES TYPECCL ( numtypeccl ) ,
CONSTRAINT f k c c l c l i e n t
FOREIGN KEY ( numcl i )
REFERENCES CLIENT ( numcl i ) ,
CONSTRAINT f k c c l pe r s o nne l
FOREIGN KEY ( numpers )
REFERENCES PERSONNEL ( numpers )
) ;
ALTER TABLE OPERATION ADD
(
128
CONSTRAINT pk oper at i on
PRIMARYKEY ( numcli , numccl , numoper ) ,
CONSTRAINT f k o pe r c c l
FOREIGN KEY ( numcli , numoper )
REFERENCES COMPTECLIENT ( numcli , numccl ) ,
CONSTRAINT f k ope r c ode ope r
FOREIGN KEY ( numtypeoper )
REFERENCES t ypeoper at i on ( numtypeoper ) ,
CONSTRAINT montant operati on
CHECK( montantoper <> 0 AND montantoper >= 1000 AND montantoper <= 1000)
) ;
INSERT INTO TYPECCL VALUES (
(SELECT nvl (MAX( numtypeccl ) , 0) + 1
FROM TYPECCL
) ,
Compte courant ) ;
INSERT INTO TYPECCL VALUES (
(SELECT nvl (MAX( numtypeccl ) , 0) + 1
FROM TYPECCL
) ,
l i v r e t ) ;
INSERT INTO TYPECCL VALUES (
(SELECT nvl (MAX( numtypeccl ) , 0) + 1
FROM TYPECCL
) ,
PEL ) ;
INSERT INTO TYPEOPERATION VALUES (
(SELECT nvl (MAX( numtypeoper ) , 0) + 1
FROM TYPEOPERATION
) ,
d

A c p

At esp

Aces ) ;
INSERT INTO TYPEOPERATION VALUES (
(SELECT nvl (MAX( numtypeoper ) , 0) + 1
FROM TYPEOPERATION
) ,
pr

A c l

Avement ) ;
INSERT INTO TYPEOPERATION VALUES (
(SELECT nvl (MAX( numtypeoper ) , 0) + 1
FROM TYPEOPERATION
) ,
vi rement ) ;
INSERT INTO TYPEOPERATION VALUES (
(SELECT nvl (MAX( numtypeoper ) , 0) + 1
FROM TYPEOPERATION
) ,
r e t r a i t ) ;
129
A.8 Secretariat pedagogique
DROP TABLE RESULTAT;
DROP TABLE EXAMEN;
DROP TABLE PREREQUIS;
DROP TABLE INSCRIPTION;
DROP TABLE MODULE;
DROP TABLE ETUDIANT;
CREATE TABLE ETUDIANT
(numEtud number,
nom varchar2 ( 40) ,
prenom varchar2 ( 40) ,
dat e nai s s date ,
c i v i l i t e varchar2 ( 4) ,
patronyme varchar2 ( 40) ,
numsecu varchar2 ( 15) NOT NULL) ;
CREATE TABLE MODULE
( codMod number,
nomMod varchar2 ( 15) ,
ef f ecMax number DEFAULT 30) ;
CREATE TABLE EXAMEN
( codMod number,
codExam number,
dateExam date ) ;
CREATE TABLE INSCRIPTION
(numEtud number,
codMod number,
dat eI ns c date default s ys dat e ) ;
CREATE TABLE PREREQUIS
( codMod number,
codModPrereq number,
noteMin number( 4 , 2) NOT NULL) ;
CREATE TABLE RESULTAT
( codMod number,
codExam number,
numEtud number,
note number( 4 , 2 ) ) ;
ALTER TABLE ETUDIANT ADD
CONSTRAINT pk et udi ant
PRIMARYKEY (numEtud ) ;
ALTER TABLE MODULE ADD
CONSTRAINT pk module
PRIMARYKEY ( codMod ) ;
ALTER TABLE EXAMEN ADD
CONSTRAINT pk examen
PRIMARYKEY ( codMod , codExam) ;
ALTER TABLE PREREQUIS ADD
CONSTRAINT pk pr e r e qui s
PRIMARYKEY ( codMod , codModPrereq ) ;
ALTER TABLE INSCRIPTION ADD
CONSTRAINT pk i ns c r i pt i o n
PRIMARYKEY ( codMod , numEtud ) ;
ALTER TABLE RESULTAT ADD
CONSTRAINT pk r e s ul t a t
PRIMARYKEY ( codMod , numEtud , codExam) ;
ALTER TABLE INSCRIPTION ADD
(CONSTRAINT f k i ns c r i pt i o n e t udi a nt
FOREIGN KEY (numEtud)
REFERENCES ETUDIANT(numEtud) ,
CONSTRAINT f k i ns c r i pt i on modul e
FOREIGN KEY ( codMod)
REFERENCES MODULE( codMod ) ) ;
ALTER TABLE PREREQUIS ADD
(CONSTRAINT f k pr er equi s codmod
FOREIGN KEY ( codMod)
REFERENCES MODULE( codMod) ,
CONSTRAINT f k pr er equi s codmodpr er eq
FOREIGN KEY ( codModPrereq )
REFERENCES MODULE( codMod ) ) ;
ALTER TABLE EXAMEN ADD
CONSTRAINT fk examen
FOREIGN KEY ( codMod)
REFERENCES MODULE( codMod ) ;
ALTER TABLE RESULTAT ADD
(CONSTRAINT f k r e s ul t at e xame 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 ) ) ;
130