Vous êtes sur la page 1sur 50

BASES DE DONNÉES RELATIONNELLES

1
1. SOMMAIRE
1. SOMMAIRE ......................................................................................................................... 2
2. INTRODUCTION................................................................................................................ 4
2.1. LES OBJECTIFS DES SYSTEMES DE GESTION DE BASES DE DONNEES (SGBD) ...................................4
2.2. LES METIERS DES BASES DE DONNEES ...............................................................................................4
2.3. HISTORIQUE ......................................................................................................................................4
2.3.1. Modèles hiérarchiques et réseaux...........................................................................................5
3. LE MODELE RELATIONNEL ......................................................................................... 6
3.1. LES BASES DU MODELE RELATIONNEL...............................................................................................6
3.2. LA NOTION DE CLE ............................................................................................................................7
3.2.1. Dépendance fonctionnelle.......................................................................................................7
3.2.2. Clé candidate ..........................................................................................................................7
3.2.3. Clé primaire, clé étrangère .....................................................................................................8
Clé primaire ........................................................................................................................................................... 8
Clé étrangère .......................................................................................................................................................... 8
3.3. LA NORMALISATION ..........................................................................................................................8
3.3.1. Intérêt de la normalisation......................................................................................................8
3.3.2. Première forme normale .........................................................................................................9
3.3.3. Deuxième forme normale ........................................................................................................9
3.3.4. Troisième forme normale ......................................................................................................10
4. LE LANGAGE SQL .......................................................................................................... 12
4.1. SELECTION DE TUPLES.....................................................................................................................12
4.1.1. La valeur NULL ....................................................................................................................13
4.1.2. Requêtes simples ...................................................................................................................13
Lecture d’une table ...............................................................................................................................................13
Projection sur un sous-ensemble des attributs ......................................................................................................14
Suppression des doubles .......................................................................................................................................14
Sélection de certains tuples ...................................................................................................................................15
Utilisation d'opérateurs arithmétiques...................................................................................................................15
Valeur NULL dans une comparaison....................................................................................................................16
Alias de colonnes ..................................................................................................................................................16
Utilisation de l'opérateur de concaténation ...........................................................................................................16
En résumé .............................................................................................................................................................16
4.1.3. Trier les résultats ..................................................................................................................17
4.1.4. Les expressions JOIN............................................................................................................18
Le produit cartésien ..............................................................................................................................................19
Jointure naturelle ..................................................................................................................................................19
Theta jointure........................................................................................................................................................20
Jointure externe.....................................................................................................................................................21
Jointure d’une table à elle même ..........................................................................................................................21
Jointures multiples ................................................................................................................................................22
4.1.5. Le partitionnement ................................................................................................................22
Les fonctions de groupe ........................................................................................................................................22
Fonctions de groupe et valeurs NULL ..................................................................................................................23
Création de groupe de données .............................................................................................................................23
En résumé .............................................................................................................................................................24
4.1.6. Les opérateurs ensemblistes .................................................................................................24
4.1.7. Les sous-interrogations.........................................................................................................24
Sous-interrogations ramenant une seule valeur .....................................................................................................24
Sous-interrogations ramenant plusieurs lignes......................................................................................................25
Sous-interrogations multi-colonne ........................................................................................................................26
Sous-interrogations corrélées avec l’interrogation principale ...............................................................................27
Sous-interrogations multiples ...............................................................................................................................28
4.1.8. Conseils pour écrire une requête ..........................................................................................28
4.2. MANIPULATION DE DONNEES ..........................................................................................................28
4.2.1. Les séquences........................................................................................................................28
4.2.2. Insertion d’éléments dans la table ........................................................................................29
4.2.3. Suppression d’éléments dans une table ................................................................................30
4.2.4. Modification de tuples ..........................................................................................................30

2
4.3. QUELQUES FONCTIONS DE MANIPULATION DE CHAINES, DE DATE, FONCTIONS DE CONVERSION ETC.
31
4.3.1. Fonctions sur les chaînes de caractères ...............................................................................31
4.3.2. Fonctions numériques ...........................................................................................................31
4.3.3. Utilisation des dates..............................................................................................................32
Fonction SYSDATE .............................................................................................................................................32
Opérations arithmétiques sur les dates ..................................................................................................................32
Quelques Fonctions date .......................................................................................................................................33
4.3.4. Fonctions de conversion .......................................................................................................33
La fonction TO_DATE(char, 'format') .................................................................................................................34
Attention avec les données de type DATE ...........................................................................................................34
4.4. DEFINITION DE DONNEES.................................................................................................................35
4.4.1.
Types de données .........................................................................................................................36
Les principaux types de données oracle ................................................................................................................36
Les principaux types de données ANSI supportés par oracle ...............................................................................36
4.4.2. Valeurs par défaut ................................................................................................................37
4.4.3. Contraintes d'intégrité ..........................................................................................................37
Nommer les contraintes ........................................................................................................................................37
Clés : PRIMARY KEY, FOREIGN KEY.............................................................................................................37
Contraintes CHECK niveau colonne ...................................................................................................................39
Contrainte UNIQUE .............................................................................................................................................39
Récapitulatif..........................................................................................................................................................39
Nommer les contraintes ........................................................................................................................................40
Accéder aux contraintes définies ..........................................................................................................................40
4.4.4. Supprimer les tables..............................................................................................................40
4.4.5. Modifier la définition d’une table .........................................................................................40
4.4.6. Accéder à la description des tables.......................................................................................41
4.5. INDEX..............................................................................................................................................41
4.5.1. Introduction au choix d’index ...............................................................................................41
4.6. CREATION DE VUES .........................................................................................................................42
4.7. EXECUTION D'UN ORDRE SQL .........................................................................................................42
5. GESTION DES TRANSACTIONS .................................................................................. 43
5.1. LA NOTION DE TRANSACTION ..........................................................................................................43
5.2. CONTROLE DE LA CONCURRENCE ....................................................................................................44
5.2.1. Protocole de verrouillage à deux phases ..............................................................................45
5.2.2. Inter-blocage.........................................................................................................................45
5.2.3. Granule de verrouillage........................................................................................................46
5.3. TRANSACTIONS ET REPRISE .............................................................................................................46
5.4. TRANSACTIONS EN SQL AVEC ORACLE ...........................................................................................46
5.4.1. Verrouillage implicite ...........................................................................................................46
5.4.2. Lectures inconsistantes niveau transaction ..........................................................................47
5.4.3. Verrouillage explicite ...........................................................................................................48
5.4.4. Lecture avec intention de modification .................................................................................48
6. BIBLIOGRAPHIE ............................................................................................................. 49
7. INDEX ................................................................................................................................. 50

3
2. INTRODUCTION

2.1. Les objectifs des Systèmes de Gestion de Bases de


Données (SGBD)
• assurer l’indépendance données/traitement (i.e. entre la structure des données et les
programmes d’application) pour garantir l’évolutivité de l’application.
• assurer l’indépendance entre l’implantation physique des données et les programmes
d’application de manière à réduire les coûts de maintenance en cas de modification
des structures physiques.
• intégrer l’information pour supprimer la redondance, avoir une saisie unique et
centraliser les contrôles.
• permettre des liaisons entre des ensembles de données de manière à pouvoir
exprimer et contrôler des informations comme « un pilote est affecté à un vol ».
• permettre l’interrogation des données en précisant seulement ce que l’on souhaite
retrouver sans avoir à dire comment le faire. L’interrogation doit pouvoir se faire
selon n’importe quel critère.
• pouvoir assurer la sécurité des données (protection des données par des droits
d’accès) et permettre la définition de points de reprise après panne (permettre de
restaurer des données cohérentes après une panne).
• assurer le partage des données.

2.2. Les métiers des bases de données


L’administrateur de la base de données a un rôle central. C’est lui qui est responsable de la ou des
bases de données. Il définit les utilisateurs et leur accorde des autorisations d'accès à la base. Il est
responsable des problèmes de performances et de sécurité de fonctionnement. Il décide donc des
techniques d’accès et de l’implantation physique des données et c’est à lui que revient de définir la
stratégie de reprise après panne.
L’utilisateur accède aux données à partir d’un programme d’application. S'il est un utilisateur
spécialisé, il sera capable d'interroger la base à travers le langage d'interrogation.
Les concepteurs et développeurs d'applications de bases de données doivent identifier et structurer
les types de données de la base ainsi que les différents traitements que ces données doivent subir. Ils
spécifient et implantent les transactions. Les compétences requises incluent une méthode de
conception de logiciels, la maîtrise de langages de manipulation de données, la construction de
programmes et les outils de tests.

2.3. Historique
La notion de base de données date des années 60. A l’époque elles étaient basées sur des SGF plus
ou moins sophistiqués. Ensuite, dans les années 70 sont apparus les premiers SGBD qui respectaient
plus ou moins les contraintes de l’architecture fonctionnelle. Ils s’appuyaient soit un modèle dit
hiérarchique, soit sur un modèle dit réseau. Dans les années 80 sont apparues les bases de données
relationnelles qui constituent l’écrasante majorité des systèmes vendus aujourd’hui. On ne trouve plus
sur le marché de systèmes basés sur les modèle réseaux ou hiérarchiques, mais on les trouve encore
dans les entreprises, c’est pourquoi on les appelle systèmes légataires.

4
2.3.1. Modèles hiérarchiques et réseaux
Le modèle hiérarchique est caractérisé par une forte dépendance des niveaux logique et physique.
Reprenons l’exemple de la compagnie aérienne. Au moins trois entités doivent être représentées : le
vol, le pilote et l’avion. Une hiérarchie doit être établie entre elles. Si nous choisissons :

AVION

PILOTE

VOL

Figure n°1 : Modèle hiérarchique


Dans ce cas, les données seront stockées comme suit :
2 B707 150
Kermarrec Paul Paris 34
IT100 Paris Nice 17 18
IT20 Nice Lyon 21 22
3 A320 310
Desprez Jean Nantes 10
Cela signifie qu’il est impossible d’ajouter un pilote sans ajouter aussi un vol, que supprimer un
avion entraîne la suppression des pilotes et des vols associés. Enfin, s’il faut mettre à jour l’adresse
d’un pilote, il faudra parcourir tous les enregistrements pour en trouver toutes les occurrences. Ce
modèle ne respecte donc qu’en partie l’architecture fonctionnelle des SGBD.
Le modèle réseau est caractérisé par une notion d’enregistrement propriétaire auquel se rattachent
un ou plusieurs enregistrements membres. Toujours avec les trois entités avion, pilote et vol, nous
pourrions envisager la structure suivante :
Avion Pilote

Vol Vol

Figure n°2 : Modèle réseau


Ce qui produirait une organisation des données telle qu’indiquée ci-après :

Pilote2
Pilote1

Vol2 Vol3
Vol1

Avion1 Avion2

Figure n°3 : Un exemple de structure dans le modèl e réseau


L’inconvénient majeur de cette approche est le temps de traitement qui sera nécessaire pour
parcourir les chaînages : pour accéder aux vols sur lesquels les pilotes sont programmés, il faut
parcourir la liste chaînée des vols associée à chaque pilote.

5
3. LE MODELE RELATIONNEL
Ce modèle a été formalisé par Codd en 1970. Le succès de ce modèle est du en grande partie à la
simplicité des concepts sur lesquels il repose ainsi que sur la solidité de ses bases théoriques.

3.1. Les bases du modèle relationnel


Dans le modèle relationnel, les données sont représentées par une structure appelée relation. Une
relation peut être donnée par un tableau à deux dimensions (ou table). La figure ci-dessous donne un
exemple de relation.
NUMERO NOM ADRESSE NOM_CONTACT
1 Grossistes Barentin M. Clément
Normands
2 ACCoop Evreux Mme Durant
3 Horizon Dieppe Mme Laseaux
5 Bezon Rouen M. Pierre

Fig 1. La relation FOURNISSEUR


Le nom de cette relation est FOURNISSEUR. Chaque ligne correspond à un fournisseur particulier.
Une ligne d’une table est un tuple. Le nombre de tuples d’une table évolue lors de l’utilisation de la
base de données par insertion ou suppression.
Le nombre de colonnes est fixe pour une relation donnée. Chaque colonne est désignée par un
attribut (ici NUMERO, NOM, ADRESSE, NOM_CONTACT). Chaque attribut représente une
information : par exemple l’attribut NOM_CONTACT représente le nom de la personne à contacter
chez le fournisseur. Chaque attribut désignant une colonne d’une table, on ne doit pas trouver deux
attributs de même nom dans une table. Par contre, on peut trouver des noms d’attributs identiques dans
des tables différentes.
Le nom de la relation et l’ensemble des attributs de cette relation constituent le schéma de la
relation. Le schéma de la relation FOURNISSEUR sera donné de la manière suivante :
FOURNISSEUR(NUMERO, NOM, ADRESSE, NOM_CONTACT).
Le modèle relationnel impose que chaque composant d’un tuple soit atomique, autrement dit soit
une valeur issue de types élémentaires comme chaîne de caractère ou date, ou encore nombre. A
chaque attribut est associé un domaine qui est donné par l’un de ces types élémentaires. Par exemple,
dans la relation FOURNISSEUR, l’attribut NOM doit être une chaîne de caractères. Les domaines font
partie du schéma de la relation. Il est rare que le schéma d’une relation évolue. Bien que cela soit
possible, de tels changements sont extrêmement coûteux pour les applications. En effet, des milliers,
voire des millions de tuples peuvent être affectés par une modification portant sur le schéma de la
relation.
L’ordre dans lequel les tuples apparaissent dans la relation n’a pas d’importance. De plus, les
attributs peuvent être donnés dans un autre ordre sans que la relation soit changée. Ainsi la relation ci-
après est « la même » que celle de la figure 1.

6
NOM ADRESSE NOM_CONTACT NUMERO
Grossistes Barentin M. Clément 1
Normands
Horizon Dieppe Mme Laseaux 3
Bezon Rouen M. Pierre 5
ACCoop Evreux Mme Durant 2

Fig 2. Une autre représentation de la relation FOURNISSEUR


L’ensemble des relations détermine la structure des informations de la base de données. On
l’appelle schéma de la base de données. Les relations doivent être nommées, l’unicité des noms des
relations doit être respectée.

3.2. La notion de clé


3.2.1. Dépendance fonctionnelle
Soit R une relation sur les ensembles d’attributs X, Y et Z. On dit que X
détermine Y ou que Y dépend fonctionnellement de X si et seulement si des
valeurs identiques de X impliquent des valeurs identiques de Y.
On le note X → Y
Parfois la dépendance fonctionnelle peut s’exprimer par une formule de calcul (l’attribut A1
dépend de la valeur des attributs A2, …, An car il existe une fonction f telle que A1=f(A2, …, An)).
Mais très souvent la dépendance fonctionnelle est sémantique, inhérente au problème traité, et non
exprimable par une fonction de calcul. Par exemple :
• Le jour de fête d’une personne dépend de son prénom
• La nature d’un produit consommable conditionne son taux de TVA
• La paye d’un employé dépend de sa catégorie, de son diplôme universitaire et de son
ancienneté
Les lois des formes normales dont nous parlerons plus loin établissent des règles de « bonne »
conception d’une base de données. Elles sont basées sur cette notion de dépendance fonctionnelle.

3.2.2. Clé candidate


Une clé candidate est un ensemble d’attributs qui permet d’identifier un tuple de manière unique.
Cet ensemble doit être minimal. Toute relation possède une clé. Au pire, cette clé est formée de tous
les attributs de la relation.
Soit R une relation sur les ensembles d’attributs X, Y, Z. X est une clé de R si et
seulement si :
X → (Y, Z)
X est minimal.
Par exemple, dans la relation « Fournisseur », le couple (numéro, adresse) n’est pas une clé
candidate, car l’attribut « numéro » suffit pour déterminer de manière unique un fournisseur.

7
3.2.3. Clé primaire, clé étrangère

Clé primaire
La clé primaire d’une relation est choisie parmi les clés candidates de la relation, s’il en existe
plusieurs. Toutes les tables créées doivent avoir une unique clé primaire.
On peut choisir la clé primaire parmi les attributs dégagés lors de l’étape de modélisation. Dans ce
cas, le ou les attributs choisis pour clé primaire ont une signification pour les utilisateurs qui vont
savoir le saisir et l’utiliser pour rechercher de l’information. On parle alors d’une clé naturelle.
On peut aussi utiliser une clé de substitution, c’est-à-dire un attribut que l’on ajoute pour servir de
clé. Cet attribut n’a pas de signification pour les utilisateurs, il sera généré par le système et les
utilisateurs ne le connaîtront pas. On peut pas exemple décider, dans une table adresse ADRESSE (
rue, code_postal, ville) d’ajouter un attribut id_adr et le choisir comme clé primaire.

Clé étrangère
Une clé étrangère est un attribut défini sur le domaine primaire d’une autre relation. Soit une
relation FOURNISSEUR donnée par FOURNISSEUR(num_fournisseur, nom_fournisseur, adresse,
nom_contact) et dont la clé primaire est num_fournisseur. Si on définit une seconde relation, la
relation COMMANDE donnée par COMMANDE(num_commande, num_produit, quantité,
num_fournisseur). Les valeurs possibles pour num_fournisseur correspondent aux valeurs présentes
dans la table FOURNISSEUR. Ainsi, si j’ai les numéros 1, 2, et 5 dans la table FOURNISSEUR, ces
valeurs sont les seules possibles pour l’attribut num_fournisseur de la table COMMANDE. L’attribut
num_fournisseur est clé primaire dans la table FOURNISSEUR et clé étrangère dans la table
COMMANDE. La notion de clé étrangère sert de base à la définition de contraintes d'intégrité
référentielles.
C’est pourquoi l’utilisation d’une clé naturelle peut poser problème. Si la décision est prise de
modifier la structure du numéro de fournisseur, il faudra changer, non seulement la table founisseur,
mais aussi toutes les tables dans laquelle num_fournisseur est utilisée comme clé étrangère. Un des
avantages d’une clé de substitution est que n’étant pas connue des utilisateurs, elle n’est pas
susceptible d’être modifiée.

3.3. La normalisation
3.3.1. Intérêt de la normalisation
Des relations non normalisées peuvent présenter des problèmes de :
• redondance,
• mise à jour
• insertion
• suppression
Si par exemple on crée une relation PERSONNE : PERSONNE(num_personnne, nom, prénom).
Puis une relation VOITURE : VOITURE(num_immatriculation, num_personne, age_proprio). Cette
relation a un lien vers la personne pour indiquer la notion de propriétaire et on a placé l’âge du
propriétaire dans cette relation. Dans ce cas, on introduit des problèmes dans la base de données.
En effet, on accroche une information à la place incorrecte (âge est relatif à personne et non à
voiture). Cela conduit à effectuer des recherches absurdes si l’on veut connaître l’âge d’une personne :
il faut aller consulter les voitures.
Cela introduit des duplications d’informations : si une personne a plusieurs voitures, alors son âge
est dupliqué pour chaque voiture (problème de redondance).

8
De plus lorsque l’âge de la personne change, il faut penser à répercuter la modification dans tous
les attributs stockant l’âge dans la table VOITURE (problème de mise à jour).
Si une personne vend ses voitures, on supprimera les tuples correspondant de la relation
VOITURE, et on perdra l’information concernant l’âge du propriétaire. S’il rachète une voiture peu
après, il faudra de nouveau saisir son âge (problème de suppression).
Pour insérer l’information selon laquelle telle personne a tel âge, il faut d’abord connaître le
numéro d’immatriculation de sa voiture qui est la clé de la relation VOITURE (problème d’insertion).
Afin de résoudre ces problèmes, des règles ont été définies pour caractériser une bonne
modélisation, ce sont les lois des formes normales. En respectant les 3 premières formes normales,
nous éviterons les principaux problèmes.
Ces règles doivent s'appliquer dans l’ordre sur une modélisation donnée. En effet, le respect de la
troisième forme normale impose le respect de la seconde qui elle-même impose de le respect de la
première forme normale.

3.3.2. Première forme normale


La première forme normale consiste à interdire la définition d’un attribut comme une structure de
données ou comme un ensemble de valeurs (tableau, liste). Les valeurs d’un tuple doivent toutes être
atomiques.
Une relation R est en première forme normale si et seulement si tout attribut
est atomique.
La relation VOITURE ci-dessous ne respecte pas la première forme normale.
Num_immatriculation Modèle_marque Num_propriétaire
1364 RT 76 (Mégane, Renault) 2
7895 AN 76 (C3, Citroën) 1
879 TY 29 (Clio, Renault) 2

La relation devient, en première forme normale :


Num_immatriculation Modèle Marque Num_propriétaire
1364 RT 76 Mégane, Renault 2
7895 AN 76 Saxo Citroën 1
879 TY 29 Super 5 Renault 2

3.3.3. Deuxième forme normale


La deuxième forme normale assure que chaque relation possède une clé et certifie que chaque
attribut de la relation ne participant pas à la définition de la clé dépend de toute la clé.
Une relation est en seconde forme normale si :
- elle est en première forme normale
– les attributs n’appartenant pas à la clé dépendent de TOUTE la clé.
La relation PERSONNE ci-dessous n’est pas en deuxième forme normale. La clé choisie pour cette
relation est (Nom, Prénom, Date_naissance, Lieu_naissance).
Nom Prénom Date_naissance Lieu_naissance Adresse Jour_de_fête
Durant Colette 18/11/1974 Rouen Paris 6 mars
Kermarrec Yves 10/08/1956 Brest Darnétal 19 mai

9
En effet, on a les dépendances fonctionnelles suivantes :
Prénom → Jour de fête
Nom, Prénom, Date_naissance, Lieu_naissance → Adresse, Jour_de_fête
Elle n’est pas en seconde forme normale car l’attribut Jour_de_fête ne dépend que d’une partie de
la clé (l’attribut Prénom). Pour la mettre en conformité avec la seconde forme normale, il est
nécessaire de décomposer la relation. Il faut extraire la dépendance fonctionnelle qui pose problème,
c’est-à-dire Prénom → Jour de fête.
On créera donc une première table PERSONNE :
Nom Prénom Date_naissance Lieu_naissance Adresse
Durant Colette 18/11/1974 Rouen Paris
Kermarrec Yves 10/08/1956 Brest Darnétal

Puis une seconde table JOUR_DE_FETE :


Prénom Jour_de_fête
Colette 6 mars
Yves 19 mai

L’information sur le prénom doit être conservée dans la nouvelle table PERSONNE. En effet, les
décompositions réalisées pour normaliser les tables doivent impérativement préserver les données et
les dépendances fonctionnelles existant dans la relation avant normalisation.
Il faut pouvoir retrouver les informations présentes initialement par jointure sur les deux tables
produites à l’issu de l’étape de normalisation. Dans le cas ci-dessus une jointure naturelle entre
PERSONNE et JOUR_DE_FETE permet de retrouver le résultat initial.
Une décomposition qui suit la démarche proposée est une décomposition sans perte.

3.3.4. Troisième forme normale


La troisième forme normale consiste à imposer que tout attribut de la relation dépende
exclusivement de la clé.
Une relation est en troisième forme normale si :
- elle est en deuxième forme normale
– tout attribut n’appartenant pas à une clé ne dépend pas d’un attribut non clé
La relation ci-dessous n’est pas en troisième forme normale :
Num_immatriculation Marque Modèle Puissance Couleur
4526 TY 76 Renault Mégane 7 Bleu
786 PL 29 Renault Clio 4 Rouge
8956 TY 76 Citroën C3 4 Vert
3245 AD 38 Peugeot 307 7 Bleu

On a les dépendances fonctionnelles :


Modèle → Marque
Un modèle de voiture donné détermine la marque

10
Modèle → Puissance
Un modèle de voiture donné détermine la puissance du véhicule
Num_immatriculation → Marque, Modèle, Puissance, Couleur
Num_immatriculation est la clé primaire de la relation
Des problèmes de redondance apparaissent dans la table : on répètera que la Mégane est une
Renault et que la Mégane a une puissance de 7cv.
Cette relation est en deuxième forme normale : la clé primaire est constituée d’un unique attribut,
par conséquent, tous les attributs dépendent de la totalité de la clé.
Par contre des dépendances fonctionnelles entre attributs non-clés introduisent la redondance
observée. La troisième forme normale vise à éviter ces problèmes. Pour transformer cette relation, il
faut la décomposer en extrayant les dépendances fonctionnelles qui posent problème.
On crée une table dont la clé est Modèle contenant les informations « Une voiture d’un certain
modèle est d’une certaine marque et est dotée d’une certaine puissance fiscale ».
Modèle Marque Puissance
Mégane Renault 7
Clio Renault 4
C3 Citroën 4
307 Peugeot 7
On crée une table qui contient l’information : « Une voiture ayant tel numéro d’immatriculation est
de telle couleur et de tel modèle ».
Num_immatriculation Modèle Couleur
4526 TY 76 Mégane Bleu
786 PL 29 Clio Rouge
8956 TY 76 C3 Vert
3245 AD 38 307 Bleu

De la même manière que précédemment, pour retrouver l’information présente dans la table
initiale, il faudra combiner par une jointure les informations contenues dans ces deux tables.
Tout schéma a au moins une décomposition en troisième forme normale qui préserve les
dépendances fonctionnelles et les données.

11
4. LE LANGAGE SQL
Le langage SQL a été initialement développé par IBM à San José. D’abord baptisé SEQUEL, il est
devenu le standard pour décrire et manipuler les bases relationnelles depuis 1986. A cette date, une
première version a été normalisée sous le nom de SQL1. Depuis, d'autres versions normalisées de SQL
ont été produites. Ainsi, en 1992, une version étendue appelée SQL2, puis en 1998 une version très
étendue baptisée SQL3.
La syntaxe utilisée est celle d’oracle. Elle est conforme au standard SQL2. De plus, en introduisant
la notion de types de données personnalisés (Relationnel-Objet), elle respecte certains aspects de la
norme SQL3.
SQL (Structured Query Langage) est un langage non-procédural. Il ne dispose pas des structures
des langages de programmation (variables, alternatives, boucles, etc.). En effet, l’objectif de ce
langage est de mettre à la disposition d’un utilisateur non informaticien un moyen d’interroger la base
de données. Celui-ci spécifiera les informations à récupérer (QUOI) sans avoir à indiquer comment les
récupérer (les algorithmes, la localisation des données sur les disques etc.).
Chaque SGBD commercial est associé à un langage procédural qui permet de stocker dans le
schéma d’une base de données des procédures ou des fonctions. Ces sous-programmes permettent de
réaliser des traitements qui ne peuvent pas être exprimés en SQL. Dans ORACLE, ce langage
s’appelle PL/SQL.
SQL permet de remplir 5 rôles :
• La recherche de données
• La définition des données (Langage de Définition de Données, LDD)
• La modification des données (Langage de Modification de Données LMD)
• Le contrôle des données (Langage de Contrôle des Données, LCD)
• Le contrôle de la concurrence d’accès aux données
Nous commencerons par présenter les ordres SQL permettant de réaliser des requêtes (ordre
SELECT). Ensuite nous aborderons succinctement la manipulation des données (insérer, modifier,
supprimer). Puis nous présenterons les ordres de création de tables (LDD). La notion de concurrence
d’accès aux données est traitée dans un chapitre séparé. Nous n'aborderons pas les instructions de
contrôle des données (définition des droits des utilisateurs de la base de données).

4.1. Sélection de tuples


Les exemples de requêtes seront donnés à partir des quatre tables définies ci-dessous. La clé
primaire de la table est indiquée en gras. Le contenu de ces tables est le suivant :
Table fournisseur :
Num_f Nom_f Ville Remise
1 Carrefour Barentin 22
2 Leclerc Rouen 20
3 Leclerc Caen 10
4 Castorama Rouen 15
5 Monoprix Oissel 0
6 Géant Le Havre 10
7 Leroy-merlin Isneauville

12
Table produit:
Num_p Designation Couleur Origine
1 Raquette BLANC Chine
2 VTT BLEU Taiwan
3 Parasol VERT France
4 Tondeuse ROUGE Corée

Table stock:
Num_p Num_f Quantité
1 1 50
2 1 10
3 2 100
3 6 50
4 4 20
4 7 10
1 6 120

Table Employes:
Num_emp Nom_emp N_sup Fonction Salaire N_service Date_emb
1 Dupont PRESIDENT 50 000 1 14-OCT-95
2 Kermarrec 1 INGENIEUR 4000 2 18-OCT-95
3 Kanellos 2 TECHNICIEN 2000 2 07-NOV-95
4 Durand 1 INGENIEUR 4500 3 17-AVR-96

4.1.1. La valeur NULL


Lorsqu'on n'affecte pas de valeur à une colonne dans une ligne, la valeur est NULL. NULL a
plusieurs significations, elle représente une valeur non disponible, non affectée, inconnue ou
inapplicable. La valeur NULL est donc différente de 0 ou du caractère espace.
Lorsqu'une valeur NULL est utilisée dans une expression arithmétique, le résultat de cette
expression est NULL. Lorsque la valeur NULL est utilisée dans une comparaison, le résultat de la
comparaison est INCONNU.

4.1.2. Requêtes simples

Lecture d’une table


La requête la plus simple consiste à accéder au contenu d’une table. Pour lire le contenu de la table
« employes », nous écrirons :
SELECT *
FROM employes ;
Après le SELECT, le signe « * » indique que l’on souhaite visualiser tous les attributs de la
relation. Après le FROM on donne le nom de la table dont on veut lire le contenu.

13
Le résultat1 est :
Num_emp Nom_emp N_sup Fonction Salaire N_service Date_emb
1 Dupont PRESIDENT 50 000 1 14-OCT-95
2 Kermarrec 1 INGENIEUR 4000 2 18-OCT-95
3 Kanellos 2 TECHNICIEN 2000 2 07-NOV-95
4 Durand 1 INGENIEUR 4500 3 17-AVR-96

Projection sur un sous-ensemble des attributs


On peut souhaiter ne récupérer que certaines colonnes de la table. Par exemple, pour accéder au
nom et à la fonction de tous les employés, on écrira :
SELECT nom_emp, fonction
FROM employes ;
Le résultat est :
Nom_emp Fonction
Dupont PRESIDENT
Kermarrec INGENIEUR
Kanellos TECHNICIEN
Durand INGENIEUR

Suppression des doubles


Lors d’une projection, il est possible que la table résultat contienne des doublons. Il est possible de
préciser dans la requête que l’on ne souhaite que des valeurs distinctes. On utilisera le mot-clé
DISTINCT.
La requête demandant le nom des fournisseurs, formulée comme indiqué ci-dessous produira des
doublons :
SELECT nom_f
FROM fournisseur ;
Nom_f
Carrefour
Leclerc
Leclerc
Castorama
Monoprix
Géant
Leroy-merlin

Pour empêcher la génération de doublons, on écrira :

1
Lors de l'exécution de la requête par oracle, vous obtiendrez les mêmes résultats mais présentés sous une
autre forme. En particulier vous constaterez que les chaînes de caractères sont affichées par défaut en
majuscules.

14
SELECT DISTINCT nom_f
FROM fournisseur ;
Et on obtiendra :
Nom_f
Carrefour
Leclerc
Castorama
Monoprix
Géant
Leroy-merlin

Sélection de certains tuples


Souvent, on souhaite spécifier un critère qui permette de sélectionner les tuples de la table. Ainsi, si
je cherche les employés qui sont des ingénieurs j’écrirais :
SELECT *
FROM employes
WHERE fonction = 'INGENIEUR' ;
Cette requête produira le résultat :

Num_emp Nom_emp N_sup Fonction Salaire N_service


2 Kermarrec 1 INGENIEUR 4000 2
4 Durand 1 INGENIEUR 4500 3

Utilisation d'opérateurs arithmétiques


Pour obtenir le salaire annuel des employés, vous pourrez écrire:
SELECT Nom_emp, salaire * 12
FROM employes;
Nom_emp Salaire*12
Dupont 600 000
Kermarrec 48 000
Kanellos 24 000
Durand 54 000

Si une valeur NULL est présente dans la table, le résultat d'une opération arithmétique est toujours
NULL. Il existe cependant un moyen de forcer la prise en compte des valeur NULL : il s'agit de la
fonction NVL Son rôle est de substituer une valeur à la valeur NULL lors de l'exécution d'une requête.
Cette fonction s'écrit : NVL(la_colonne, la_valeur). Lorsqu'une valeur NULL est trouvée dans la
colonne la_colonne, la valeur la_valeur lui est substituée.

15
Valeur NULL dans une comparaison
Un tuple est retenu dans le résultat d’une sélection si la condition de sélection est évaluée à VRAI.
Lorsque la comparaison s’effectue avec une valeur NULL, le résultat d’une comparaison est
INCONNU et le tuple n’est pas conservé dans le résultat.
Comment cette valeur « INCONNU » se combine-t-elle avec VRAI et FAUX dans des
combinaisons de conditions utilisant des opérateurs tels que AND ou OR ? Pour le savoir, on suppose
qu’une valeur numérique est attribuée aux valeurs de vérité VRA1, FAUX, INCONNU, valeurs qui
sont respectivement 1, 0 et ½. Pour connaître le résultat d’un AND entre deux conditions simples, on
prendra toujours le minimum des valeurs. Ainsi 1 AND 0 donne 0 (si une condition est fausse, la
combinaison par AND est fausse) et 1 AND ½ donne ½ (si une condition est inconnu et l’autre vrai, le
résultat est inconnu et le tuple ,’est pas retenu). Pour connaître le résultat d’un OR entre deux
conditions, on prend toujours le maximum. Ainsi 1 OR 0 donne 1 (il suffit qu’une condition soit vraie
pour que le résultat d’un OR soit vrai) et 1 OR ½ donne VRAI (su une condition est inconnue et
l’autre vraie, le résultat est VRAI). Dans le cas de la négation NOT , le résultat est 1 – la valeur. La
négation d’une condition INCONNU est donc INCONNU.

Alias de colonnes
Il est possible de renommer un en-tête de colonne. Par exemple, dans l'exemple ci-dessus, il serait
souhaitable de renommer la deuxième colonne en "salaire annuel". Dans ce cas, la requête serait
réécrite:
SELECT nom_emp, salaire*12 AS "Salaire annuel"
FROM employes;
La requête s'affichera de la façon suivante :

Utilisation de l'opérateur de concaténation


Le seul opérateur existant pour les chaînes est la concaténation. Il est désigné par deux barres
verticales accolées ( || ).
Pour obtenir une chaîne constituée à partir du nom et de la fonction des employés, on écrira :
SELECT 'NOM : ' || nom_emp || ‘ ‘ || 'FONCTION :' || fonction
AS "Les employes"
FROM employes ;
Le résultat obtenu est le suivant :

En résumé
La syntaxe d’un SELECT peut s’écrire :

16
SELECT attribut1,…, attributn
FROM une_table
WHERE critère ;
• Attribut1, …, attributn sont les colonnes que l’on souhaite voir figurer dans le résultat
• Une_table est le nom de la table interrogée
• Critère peut être constitué de différentes façons. Il existe de nombreux opérateurs de
comparaison ainsi que des moyens d’associer les expressions entre elles. Quelques
opérateurs sont listés ci-dessous.
Opérateur Signification Exemple
= Egalité N_sup=1
!= ou <> Différent Nom_emp != 'Dupont'
< Plus petit que Salaire < 4500
> Plus grand que Salaire > 4000
<= Plus petit ou égal Salaire <= 4500
>= Plus grand ou égal Salaire >= 4000
IN (liste) Contenu dans la liste Salaire in (4000, 4500)
IS NULL N’a pas de valeur Remise IS NULL
BETWEEN … AND Contenu entre deux valeurs Salaire BETWEEN 3000 AND 5000

LIKE Correspond aux caractères Nom_emp LIKE 'D%'
Commence par D % correspond à 0 ou plusieurs
caractères
_ correspond à 1 caractère
Possède A en second
caractère Nom_emp LIKE '_A%'

Les opérateurs logiques AND, OR et NOT permettent d’associer des conditions entre elles.
Attention aux règles de priorité des opérateurs. NOT est prioritaire sur AND qui est lui-même
prioritaire sur OR. Utilisez des parenthèses pour forcer la priorité.

4.1.3. Trier les résultats


Le tri des résultats est effectué en ajoutant la clause ORDER BY à la fin de l’instruction SELECT.
Celle-ci peut alors s’écrire :
SELECT attribut1,…, attributn
FROM une_table
WHERE critère
ORDER BY attribut1 [asc|desc]
attribut2 [asc|desc],
… ;
Le tri est ascendant pas défaut. Les valeurs nulles sont toujours retournées en fin de liste si le tri est
demandé par ordre croissant, au début s’il est demandé par ordre décroissant.
Par exemple, pour obtenir la liste des fournisseurs par ordre décroissant de la remise, il faudra
écrire :

17
SELECT num_f, nom_f, remise
FROM fournisseur
ORDER BY remise DESC;
Le résultat de la requête est :

Pour obtenir la table stock triée selon les numéros de fournisseurs et selon les numéros de produits :
SELECT *
FROM stock
ORDER BY num_f, num_p;
Le résultat sera :

4.1.4. Les expressions JOIN


Le code SQL indiqué ci-après est conforme au standard SQL-2. Cependant, ces formes n’ont été
implémentées dans Oracle qu’à partir de la version 9i. Dans le cas où vous seriez amenés à travailler
avec une version antérieure, consultez la documentation !
Soit la relation COMMANDE(date, num_f, num_p, quantité) donnée ci-dessous. Cette relation
indique en quelle quantité ont été commandés les produits de numéro num_p au fournisseur de numéro
num_f.
Date Num_p Num_f Quantité
10/10/2000 1 2 10
2/2/2002 2 2 30
3/3/2003 3 3 54

Fig 3. La relation COMMANDE

18
Le produit cartésien
Le produit cartésien est une opération qui permet de construire toutes les combinaisons possibles en
prenant une ligne d’une table et une ligne d’une autre table. La structure du résultat comporte toutes
les colonnes des tables utilisées.
Le produit cartésien entre FOURNISSEUR et COMMANDE, noté FOURNISSEUR x
COMMANDE produira 7 (pour fournisseur) * 3 (pour commandes) = 21 lignes. Le résultat
comportera 4 (pour fournisseur) + 4 (pour commande) = 8 colonnes.
Num_f Nom_f Adresse_f Nom_contact Date Num_f Num_p Quantité
1 Grossistes Barentin Mme Durant 10/10/2000 1 2 10
Normands
1 Grossistes Barentin Mme Durant 10/10/2000 2 2 30
Normands
1 Grossistes Barentin Mme Durant 10/10/2000 3 3 54
Normands
2 ACCoop Evreux M Clement 2/2/2002 1 2 10
2 ACCoop Evreux M Clement 2/2/2002 2 2 30
2 ACCoop Evreux M Clement 2/2/2002 3 3 54

etc…
Fig 4. Le résultat du produit cartésien FOURNISSEUR x COMMANDE
L’instruction SQL permettant d’écrire un produit cartésien est :
SELECT *
FROM fournisseur
CROSS JOIN commande ;

Jointure naturelle
Cette opération permet de combiner des éléments de deux relations sur les attributs communs (ie
ayant le même nom). Dans l’exemple ci-dessous, les tables stock et fournisseur seront mises en
relation sur les colonnes num_f (seul attribut commun). Les lignes figurant dans le résultat de la
jointure sont celles pour lesquelles une égalité a été trouvée entre la colonne num_f de stock et la
colonne num_f de fournisseur. Les fournisseurs 3 et 5 ne seront pas retournés, car il n’y a pas de valeur
correspondante dans stock.

Num_p Num_f Quantité


1 1 50
2 1 10
3 2 100
3 6 50
4 4 20
4 7 10
1 6 120

19
Num_f Nom_f Ville Remise
1 Carrefour Barentin 22
2 Leclerc Rouen 20
3 Leclerc Caen 10
4 Castorama Rouen 15
5 Monoprix Oissel 0
6 Géant Le Havre 10
7 Leroy-merlin Isneauville

L’écriture en SQL d’une jointure naturelle entre les tables fournisseur et stock est la suivante :
SELECT *
FROM fournisseur
NATURAL JOIN stock ;
La colonne num_f n’est présente qu’une fois dans le résultat.
Le résultat produit sera le suivant :
Num_f Nom_f Ville Remise Num_p Quantite

1 Carrefour Barentin 22 1 50

1 Carrefour Barentin 22 2 10

2 Leclerc Rouen 20 3 100

4 Castorama Rouen 15 4 20

6 Géant Le Havre 10 3 50

6 Géant Le Havre 10 1 120

7 Leroy-merlin Isneauville 4 10

Theta jointure
On doit pouvoir écrire une opération de jointure entre 2 tables, même si elles n’ont aucun attribut
ayant le même nom. Ainsi dans la situation ci-dessous, nous ne pourrons pas utiliser NATURAL JOIN
pour joindre les 2 tables. Pour produire le même résultat que précédemment, nous utiliserons
l’opérateur INNER JOIN.
SELECT *
FROM fournisseur
INNER JOIN stock
ON (fournisseur.id_four = stock.num_f) ;

Il est parfois nécessaire de mettre en correspondance des tables sur des attributs de nom différent,
ou bien en utilisant des conditions plus complexes qu’une simple égalité de valeur. C’est ce que
permet aussi l’opérateur INNER JOIN : il suffit de préciser la condition de rapprochement dans la
clause ON. Par exemple pour connaître les employés gagnant plus que Kermarrec, on écrira :

20
SELECT employes.nom_emp, employes.fonction,
employes.salaire
FROM employes
INNER JOIN employes kerma
ON employes.salaire > kerma.salaire
WHERE kerma.nom_emp = ‘Kermarrec’;
Le résultat obtenu est la table :
Nom_emp Fonction Salaire
Dupont PRESIDENT 50 000
Durand INGENIEUR 4500

Jointure externe
Dans l’exemple précédent, les fournisseurs numéro 3 et 5 n'apparaissent pas dans le résultat car il
n'y a aucun tuple correspondant dans la table stock. Cela peut être intéressant de les faire apparaître
dans le résultat et c’est ce que permet la jointure externe.
SELECT *
FROM fournisseur
LEFT OUTER JOIN stock
ON founisseur.num_f = stock.num_f ;
Le mot clé LEFT permet d’afficher, en plus des lignes retournées normalement pas la jointure, les
tuples sans correspondance de l’argument gauche (ici la table fournisseur).
Num_f Nom_f Ville Remise Num_p Quantité
1 Carrefour Barentin 22 1 50

1 Carrefour Barentin 22 2 10
2 Leclerc Rouen 20 3 100

3 Leclerc Caen 10

4 Castorama Rouen 15 4 20
5 Monoprix Oissel 0

6 Géant Le Havre 10 3 50

6 Géant Le Havre 10 1 120

7 Leroy-merlin Isneauville 4 10

En lieu et place de LEFT, il est possible d’utiliser les mots-clés RIGHT ou FULL (pour afficher
tous les tuples sans correspondance, aussi bien de l’argument droit que de l’argument gauche).

Jointure d’une table à elle même


Il peut être utile de rassembler des informations venant d’une ligne d’une table avec des
informations venant d’une autre ligne de la même table. Par exemple, « donner pour chaque employé
le nom de son supérieur hiérarchique » pourra s’écrire :

21
SELECT employes.nom_emp, chefs.nom_emp AS nom_chef
FROM employes
INNER JOIN employes chefs
ON employes.n_sup = chefs.num_emp;
Dans ce cas, il est nécessaire de renommer au moins l’une des deux occurrences de la table (ici,
employes) en lui donnant un autre nom (ici, chefs). Cela permet de préfixer sans ambiguïté chaque
nom de colonne.

Jointures multiples
Il est possible de réaliser plusieurs jointures dans un ordre SQL. Par exemple, pour afficher à la fois
lesnoms de produits et les noms des fournisseurs ayant des produits en stock, nous aurons besoin de la
table produit (nom des produits), stock (numéro de produit et numéro de founisseur ) et fournisseur
(nom des fournisseurs).
SELECT fournisseur.nom_f, produit.nom_p, qte
FROM fournisseur INNER JOIN stock
ON founisseur.num_f = stock.num_f
INNER JOIN produit
ON produit.num_p = fournisseur.num_p;

4.1.5. Le partitionnement

Les fonctions de groupe


Les fonctions de groupe agissent sur des groupes de lignes et donnent un résultat par groupe. Un
groupe peut être une table entière ou un ensemble de tuples d'une table.
• AVG( [DISTINCT | ALL] expression)
Renvoie la moyenne des valeurs d’expression. Les valeurs NULL sont ignorées. S'utilise
avec des valeurs numériques.
• COUNT( * | [DISTINCT | ALL] expression)
Renvoie le nombre de lignes du résultat de la requête. Nombre de lignes ou expression est
différent de NULL. Le caractère * comptabilise toutes les lignes sélectionnées, y compris
les valeurs NULL et les doublons.
• MAX( [DISTINCT | ALL] expression)
Renvoie la plus grande des valeurs de expression. Les valeurs NULL sont ignorées.
S'utilise avec tous types de données.
• MIN( [DISTINCT | ALL] expression)
Renvoie la plus petite des valeurs de expression. Les valeurs NULL sont ignorées. S'utilise
avec tous types de données.
• SUM( [DISTINCT | ALL] expression)
Renvoie la somme des valeurs. Les valeurs NULL sont ignorées. S'utilise avec des valeurs
numériques.
• STDDEV( [DISTINCT | ALL] expression )
Renvoie l'écart standard de expression. Les valeurs NULL sont ignorées.
• VARIANCE( [DISTINCT | ALL] expression )
Renvoie la variance de expression. Les valeurs NULL sont ignorées.

22
DISTINCT : indique à la fonction de groupe de ne prendre en compte que les valeurs distinctes
ALL : indique à la fonction de groupe de prendre en compte toutes les valeurs, y compris les
doublons (option par défaut).
Par exemple, pour compter le nombre de fournisseurs m'ayant accordé une remise inférieure ou
égale à 10 %, on écrira :
SELECT COUNT(num_f) AS "Nombre fournisseurs"
FROM fournisseur
WHERE remise <= 10;

Le résultat obtenu sera :

Vous constatez que la valeur NULL n'a pas été comptabilisée.

Fonctions de groupe et valeurs NULL


Il est possible de forcer la prise en compte des valeurs NULL. On utilise pour cela la fonction NVL.
Son rôle est de substituer une valeur à la valeur NULL lors du calcul de la fonction de groupe.
SELECT AVG( NVL(remise, 0) )
FROM fournisseur ;
La moyenne sera calculée sur toutes les lignes, y compris celles où figure une valeur NULL. Pour
le calcul, la valeur NULL sera remplacée par 0. Si la fonction NVL n'est pas utilisée, la moyenne sera
calculée uniquement pour les lignes ne comportant pas de valeur NULL.

Création de groupe de données


En général, on cherche à réaliser des groupes selon une certaine caractéristique. Par exemple, on
veut connaître la moyenne des salaires des employés pour chaque service. La clause GROUP BY
permet de spécifier cette caractéristique. Dans ce cas, la requête sera formulée de la manière suivante :
SELECT AVG(salaire), n_service
FROM employes
GROUP BY n_service ;
Et on obtiendra le résultat :

Dans cet exemple, l’ensemble des tuples de la relation employes est partitionné en sous-ensembles
(ou groupes) caractérisés par un même numéro de service. La moyenne des salaires est réalisée pour
chacun de ces groupes.
Attention, la liste des colonnes résultat d’un SELECT comportant une fonction de groupe ne doit
contenir QUE des fonctions de groupe (AVG dans l’exemple ci-dessus), et éventuellement des
expressions figurant dans le GROUP BY (n_service).
Il est possible de sélectionner certains groupes grâce à la clause HAVING qui se place après la
clause GROUP BY. La syntaxe utilisée pour le HAVING est la même que celle qu’on utilise pour le
WHERE. Cependant, la condition ne peut porter que sur des caractéristiques du groupe.

23
Par exemple, la requête permettant d’obtenir la liste des salaires moyens par fonction pour les
fonctions ayant au moins deux employés s’écrira :
SELECT fonction, COUNT(*), AVG(salaire)
FROM employes
GROUP BY fonction
HAVING COUNT(*) >= 2 ;
Fonction COUNT AVG
INGENIEUR 2 4250

Il est possible que le SELECT contienne à la fois une clause WHERE et une clause HAVING. La
clause WHERE sera d’abord appliquée pour sélectionner les lignes, puis les groupes seront constitués
à partir des lignes sélectionnées, et enfin les fonctions de groupes seront évaluées.
Une clause de tri (ORDER BY) peut être ajoutée en fin de requête.

En résumé
SELECT column, fonction_groupe
FROM table
[ WHERE condition ]
[ GROUP BY group_by_expression]
[ HAVING condition_groupe ]
[ ORDER BY column]

4.1.6. Les opérateurs ensemblistes


Le but de ces opérateurs (UNION, INTERSECT et MINUS) est de combiner dans un résultat
unique des lignes provenant de deux interrogations. Il est nécessaire que les tables ainsi combinées
aient un même schéma de relation (même nombre de colonnes et domaines un à un identiques).
La syntaxe d’utilisation est la même pour ces trois opérateurs :
SELECT …
[UNION | INTERSECT | MINUS]
SELECT …
• Les titres des colonnes sont ceux du premier SELECT
• Les doubles sont éliminés (DISTINCT implicite)

4.1.7. Les sous-interrogations


Lorsque que le critère employé dans une clause WHERE est lui-même le résultat d’un SELECT, on
parle de sous-interrogation.
Remarque : SQL permet souvent plusieurs formulations pour une recherche d’informations. En
particulier, il est possible de réécrire certaines des sous-interrogations présentées ci-dessous par des
jointures.

Sous-interrogations ramenant une seule valeur


Pour répondre à une interrogation comme « Quels sont les employés ayant la même fonction que
Kermarrec ? », on peut procéder en deux étapes. D'abord rechercher la fonction de Kermarrec, puis
utiliser ce résultat dans une autre interrogation. Les deux interrogations seront placées l'une à
l'intérieur de l'autre. La requête interne (ou sous-interrogation) ramène un résultat utilisé par la requête
externe, ou interrogation principale.
La requête permettant d'obtenir les employés ayant la même fonction que Kermarrec peut s'écrire :

24
SELECT nom_emp
FROM employes
WHERE fonction = (SELECT fonction
FROM employes
WHERE nom_emp = ‘Kermarrec’);
Les résultats obtenus seront:
Nom_emp
Kermarrec
Durand
Dans l’exemple ci-dessus, les deux requêtes ne sont pas corrélées : la sous-question rend toujours le
même résultat quelque soit le nom de l’employé considéré dans la requête principale.
Les sous-interrogations mono-lignes (qui ne renvoient qu'une seule ligne) utilisent des opérateurs
mono-lignes:
Opérateur Signfication
= Egal à
> et >= Supérieur, supérieur ou égal
< et <= Inférieur, inférieur ou égal
<> Différent de

Il est possible d'utiliser une fonction de groupe ne ramenant qu'une seule ligne dans une sous-
interrogation mono-ligne.

Sous-interrogations ramenant plusieurs lignes


Une sous-interrogation peut ramener plusieurs lignes à condition que l’opérateur utilisé dans la
clause WHERE admette à sa droite un ensemble de valeurs. Les opérateurs multi-lignes sont les
suivants:
• IN : Egal à une élément quelconque de la liste
• ANY : la comparaison est vraie si elle est vraie pour au moins un des éléments de
l’ensemble
o < ANY signifie inférieur à au moins une des valeurs, donc inférieur au
maximum
o > ANY signifie supérieur à au moins une des valeurs, donc supérieur au
minimum
o = ANY équivaut à IN
• ALL : la comparaison est vraie si elle est vraie pour tous les éléments de l’ensemble.
o > ALL signifie supérieur au maximum
o < ALL signifie inférieur au minimum
Voici deux exemples d’utilisation de telles sous-interrogations.
Donnez le nom des fournisseurs pour lesquels je n’ai rien en stock.
SELECT nom_f, ville
FROM fournisseur
WHERE num_f NOT IN( SELECT num_f
FROM stock );

25
Nom_f Ville
Leclerc Caen
Monoprix Oissel

Donnez les fournisseurs qui me consentent une remise supérieure à celle de tous ceux qui sont
situés à Rouen.
SELECT nom_f, ville, remise
FROM fournisseur
WHERE remise > ALL( SELECT remise
FROM fournisseur
WHERE ville = ‘Rouen’) ;
Nom_f Ville Remise
Carrefour Barentin 22

Sous-interrogations multi-colonne
Il est possible de comparer le résultat d’un SELECT ramenant plusieurs colonnes avec une liste de
colonnes. La liste de colonnes figurera entre parenthèses à gauche de l’opérateur de comparaison.
Pour ces exemples, nous supposerons que la table employés est la suivante :

Quels sont les employés ayant à la fois même fonction et même supérieur hiérarchique qu'un des
employés du service 2 ?
SELECT nom_emp, n_sup, fonction
FROM employes
WHERE (fonction,NVL(n_sup, -1)) IN
( SELECT fonction, NVL(n_sup, -1)
FROM employes
WHERE n_service = 2) ;

Dans l'exemple ci-dessus, ce sont des couples (fonction, n_sup) qui sont comparés. On peut aussi
formuler des requêtes qui réalisent des comparaisons colonne par colonne.
SELECT nom_emp, n_sup, fonction
FROM employes
WHERE fonction IN( SELECT fonction
FROM employes
WHERE n_service = 2)
AND NVL(n_sup, -1) IN ( SELECT NVL( n_sup, -1)
FROM employes
WHERE n_service = 2) ;

26
Sous-interrogations corrélées avec l’interrogation principale

ECRIRE UNE SOUS-INTERROGATION CORRELEE


Dans une sous-interrogation normale, l'ordre SELECT interne est d'abord exécuté pour retourner
des valeurs qui seront récupérées par la requête principale. Par contre, une sous-interrogation corrélée
est exécutée une fois pour chaque ligne candidate prise en compte par la requête externe. La requête
interne est donc pilotée par la requête externe.
Le traitement d'une sous-interrogation corrélée est plus complexe car il faut:
1. Récupérer une ligne candidate pour la requête externe
2. Exécuter la requête interne avec la valeur de la ligne candidate
3. Utiliser la ou les valeurs résultant de la requête interne pour sélectionner ou ne pas
sélectionner la ligne candidate
4. Recommencer jusqu'à ce que toutes les lignes candidates aient été traitées.
Quels sont les employés travaillant dans le même service que leur supérieur hiérarchique ?
SELECT nom_emp
FROM employes emp_externe
WHERE n_service =( SELECT n_service
FROM employes emp_interne
WHERE emp_externe.n_sup =
emp_interne.num_emp );
Nom_emp
Kermarrec
Durand

Remarquez que la requête interne utilise la valeur d'une colonne de la requête externe, ici la
colonne n_sup.

SOUS-INTERROGATIONS RAMENANT AU MOINS UNE LIGNE


L‘opérateur EXISTS permet de construire une condition vraie si la sous-interrogation ramène au
moins une ligne.
Donnez le nom des fournisseurs ayant fourni des produits.
SELECT nom_f, ville
FROM fournisseur
WHERE EXISTS ( SELECT num_p
FROM stock
WHERE fournisseur.num_f = stock.num_f) ;

27
Nom_f Ville
Carrefour Barentin
Leclerc Rouen
Castorama Rouen
Géant Le Havre
Leroy-merlin Isneauville

Sous-interrogations multiples
Une interrogation peut comporter plusieurs sous-interrogations, soit imbriquées, soit au même
niveau dans différentes conditions combinées avec des AND ou des OR.
Donner la liste des employés du département 2 ayant la même fonction que quelqu’un du
département de Durand.
SELECT nom_emp, fonction
FROM employes
WHERE n_service = 2
AND fonction IN (SELECT fonction
FROM employes
WHERE n_service = (SELECT n_service
FROM employes
WHERE nom_emp =
‘Durand’)) ;

Nom_emp Fonction
Kermarrec INGENIEUR

4.1.8. Conseils pour écrire une requête


Lorsque vous écrivez une requête, vous augmentez sensiblement vos chances de réussite en:
1. développant votre requête incrémentalement
2. vérifiant les résultats après chaque étape
3. travaillant sur les différentes clauses dans l'ordre suivant :
FROM , WHERE, GROUP BY, HAVING, SELECT et ORDER BY

4.2. Manipulation de données


4.2.1. Les séquences
Pour chacune des clés primaires des tables fournisseur, produit et employes, on souhaite laisser
ORACLE générer automatiquement des numéros uniques. Cela nécessite l’utilisation d’une séquence.
Les séquences sont des objets de la base de données, au même titre que les tables. Cela signifie en
particulier que les numéros de séquence sont stockés et générés indépendamment des tables.
CREATE SEQUENCE fournisseur_num_f_seq ;
CREATE SEQUENCE produit_num_p_seq;
CREATE SEQUENCE employes_num_emp_seq;

28
Des options permettent par exemple de fixer une valeur initiale, une valeur maximale, ou encore de
gérer l'incrément, etc.
Pour vérifier les valeurs de la séquence, vous pouvez interroger la table USER_SEQUENCE du
dictionnaire de données.
SELECT *
FROM user_sequences;
Pour supprimer une séquence, utiliser l'instruction:
DROP SEQUENCE nom_séquence
Regardez la section concernant la commande « INSERT » pour voir comment s’utilise la séquence.

4.2.2. Insertion d’éléments dans la table


La commande pour insérer un tuple est INSERT INTO … VALUES. Son utilisation la plus simple
consiste à préciser les valeurs de chacune des colonnes.
Pour insérer un fournisseur :
INSERT INTO fournisseur
VALUES (fournisseur_num_f_seq.NEXTVAL, ‘Carrefour’,
‘Barentin’, 15) ;
fournisseur_num_f_seq.NEXTVAL signifie que l'on demande la génération de la valeur suivante sur
la séquence, préalablement définie, fournisseur_num_f_seq.
Si une des colonnes est omise (la colonne remise), il devient nécessaire de préciser les attributs de
chaque colonne.
INSERT INTO fournisseur (num_f, nom_f, ville)
VALUES (fournisseur_num_f_seq.NEXTVAL, ‘Carrefour’,
‘Mont Saint Aignan’) ;
Pour insérer un produit :
INSERT INTO produit (num_p, designation, origine)
VALUES(produit_num_p_seq.NEXTVAL, ‘VTT’, ‘Taiwan’) ;
Dans le cas du VTT, la couleur, conformément à la contrainte de valeur par défaut précisée dans la
table vaudra : BLEU.
Pour insérer un élément dans les stocks :
INSERT INTO stock (num_p, num_f, quantite)
VALUES(1, 1, 50);
Les contraintes d'intégrité définies lors de la création des tables sont vérifiées. Cela peut empêcher
l'insertion d'un tuple qui ne respecte pas ces contraintes. C'est le cas de l'insertion ci-dessous, car le
produit n°10 n'existe pas dans la table PRODUIT (contrainte de clé étrangère définie sur la colonne
num_p).
INSERT INTO stock (num_p, num_f, quantite)
VALUES(10, 1, 50);
Le message d'erreur affiché dans l'environnement SQL*Plus est le suivant :

Pour insérer un élément dans les employés :

29
INSERT INTO employes (num_emp, nom_emp, fonction, salaire,
n_service, date_emb)
VALUES (employes_num_emp_seq.NEXTVAL, ‘Dupont’, ‘PRESIDENT’,
200000, 1, TO_DATE('14/10/1995', 'DD/MM/YYYY'));
Les insertions ci-dessus n’ajoutent qu’une ligne dans une table. Il est possible de produire un
ensemble de lignes à insérer à partir d’une sous-requête. Supposons que nous voulions ajouter dans
une table listant les fournisseurs à contacter pour une négociation commerciale (aContacter(nom_f))
les noms de fournisseurs nous consentant une remise inférieure à 10% . L’insertion s’écrirait :
INSERT INTO aContacter (nom_f)
(SELECT nom_f
FROM fournisseur
WHERE nvl(remise, 0) < 10) ;

4.2.3. Suppression d’éléments dans une table


Cette suppression peut concerner soit tous les tuples de la table, soit certains tuples selon un critère
donné.
DELETE FROM nom_de_la_table
WHERE condition ;
La condition est facultative. Si elle n’est pas spécifiée, tous les tuples seront détruits. Sinon, seuls
les tuples répondant à la condition le seront. Dans certains cas la suppression peut être récupérée (cf.
section sur la gestion des transactions dans ORACLE).

4.2.4. Modification de tuples


De la même manière que précédemment, cette modification portera sur tous les tuples, ou certains
d’entre eux.
Pour indiquer que le supérieur hiérarchique de Kermarrec est Monsieur Dupont :
UPDATE employes
SET n_sup = 1
WHERE nom_emp = ‘Kermarrec’ ;
Pour augmenter de 10% tout le personnel :
UPDATE employes
SET salaire = salaire * 1.1 ;
La forme générale d’un ordre UPDATE est :
UPDATE table
SET col = val [, col = val, …]
[WHERE condition];
Un ordre UPDATE peut aussi contenir une sous-interrogation, par exemple dans la partie SET.
Dans l’exemple ci-dessous, le supérieur hiérarchique de Kanellos est affecté à la même valeur que
celui de Kermarrec.
UPDATE employes
SET n_sup = ( SELECT n_sup
FROM employes
WHERE nom_emp = ‘Kermarrec’ )
WHERE nom_emp = ‘Kanellos’;

30
4.3. Quelques fonctions de manipulation de chaînes, de date,
fonctions de conversion etc.
Les fonctions mono-ligne, comme leur nom l'indique, ramènent une seule valeur par ligne issue de
la requête. Les fonctions multi-ligne manipulent des groupes de lignes, ce sont les fonctions de groupe.

4.3.1. Fonctions sur les chaînes de caractères


Ces fonctions acceptent des données caractères en entrée et retournent des données caractères ou
numériques.
Fonction Description et résultat
LOWER Transforme en minuscules
LOWER(Cours BDD) cours bdd
UPPER Transforme en majuscules
UPPER(Cours BDD) COURS BDD
INITCAP Première lettre en majuscule, les autres en minuscules
INITCAP(Cours BDD) Cours Bdd

D'autres fonctions permettent de réaliser des manipulations de chaînes de caractères.


Fonction Description et résultat
CONCAT Concaténation de 2 chaînes de caractères
Il fait beau
CONCAT('Il fait', ' beau')
SUBSTR Recherche une sous-chaîne
SUBSTR('Il fait beau', 1, 2) Il
LENGTH Longueur de la chaîne
LENGTH('Il fait beau') 12
INSTR Première position d'un caractère
INSTR('Il fait beau') 5
LPAD Ajoute des caractères de remplissage à la
gauche d'une valeur
LPAD(salaire, 10, '*') ******5000

4.3.2. Fonctions numériques


Les fonctions numériques utilisent et retournent des valeurs numériques.
Fonction Description et résultat
ROUND(colonne|expression, n) Arrondit la valeur de le colonne, selon la
valeur de n
Si n > 0, arrondi à n décimales
Si n est omis, pas de décimales
Si n < 0, arrondi sur la partie gauche
ROUND(123.789, 2)
123.79
TRUNC(colonne|expression, n) Tronque la valeur de la colonne, selon la

31
valeur de n
Si n > 0, le nombre sera tronqué à n
décimales
Si n est omis, pas de décimales
Si n < 0, troncature sur la partie gauche.
TRUNC(123.789, 2) 123.78
MOD Retourne le reste d'une division
MOD(1600, 300) 100

4.3.3. Utilisation des dates


Oracle stocke les dates dans un format numérique interne : siècle, année, mois, jour, heure, minutes
et secondes. Le format par défaut est DD-MON-RR. Ce format est identique au format DD-MON-YY,
mais il permet en outre de changer de siècle selon le tableau suivant :
Si l'année spécifiée est située entre :
0-49 50-99
Si les 2 0-49 La nouvelle date appartient La nouvelle date appartient au
chiffres de au siècle courant siècle précédent
l'année en
cours sont 50-99 La nouvelle date appartient La nouvelle date appartient au
: au siècle suivant siècle courant

Par exemple, si nous sommes en l'an 2000, et que la date spécifiée est: 06-Nov-86. L'année en
format YY vaut 2086, tandis qu'en format RR elle vaut 1986. Par contre, si la date spécifiée est 18-
JUN-40, la valeur de l'année est 2040 au format YY et au format RR.

Fonction SYSDATE
La fonction SYSDATE retourne la date et l'heure courante. Pour simplement afficher la date et
l'heure courante, il faut utiliser une table spécifique appelée DUAL. Cette table ne contient qu'une
colonne et dans cette colonne qu'une unique valeur. On peut l'utiliser de cette manière:
SELECT SYSDATE
FROM DUAL;

Opérations arithmétiques sur les dates


Les opérations possibles sont les suivantes :
Opération Résultat Description
Date + nbre de jours Date Ajoute un certain nombre
de jours à une date
Date – nbre de jours Date Soustrait une certain
nombre de jours à une date
Date – Date Nombre de jours Soustrait une date d'une
autre

Par exemple :

32
SELECT nom_emp, (SYSDATE – date_emb) / 7 AS Semaines
FROM employes;

Quelques Fonctions date


Fonction Description
MONTHS_BETWEEN(d1, d2) Nombre de mois entre deux date
ADD_MONTHS(d, nbre_mois) Ajoute des mois calendaires à une date
NEXT_DAY(d, le_jour_chaine) Jour qui suit la date spécifiée
LAST_DAY(d, le_jour_chaîne) Dernier jour du mois

4.3.4. Fonctions de conversion


Oracle est capable de réaliser un certain nombre de conversions de type implicites. Cependant, il
est préférable de spécifier explicitement les conversions de type à effectuer lors des requêtes. Cela
améliore la lisibilité, les performances et préserve l'évolution ultérieure du code.
Les fonctions de conversion sont:
Fonction Description
TO_CHAR(nombre|date, ['format']) Convertit un nombre ou une date en une
chaîne de caractères de type VARCHAR2 et
de format format
TO_NUMBER(char) Convertit une chaîne de caractères en un
nombre
TO_DATE(char, ['format']) Convertit une chaîne de caractères
représentant une date au format format en
une date au format Oracle. Lorsque format
est omis, le format est DD-MON-RR

Les chaînes de caractères entre doubles quotes sont reproduites telles quelles dans le résultat.
Quelques exemples d'utilisation vous sont donnés ci-dessous:
SELECT nom_emp, TO_CHAR(date_emb, '"le "DAY DD MONTH
YYYY') AS "Date d'embauche"
FROM employes;

SELECT nom_emp, TO_CHAR(date_emb, 'DD/MM/YYYY') AS


"Date d''embauche"
FROM employes;

33
SELECT nom_emp, TO_CHAR(salaire, '999999.99') AS
"Salaire"
FROM employes;

La fonction TO_DATE(char, 'format')


Les modèles de format valides ont été explicités précédemment.
SELECT nom_emp, date_emb
FROM employes
WHERE date_emb = TO_DATE('14/10/1995',
'DD/MM/YYYY');
Dans ce cas, la partie “heure” de la date est initialisée à « zéro heure ».

Attention avec les données de type DATE


Supposons les deux insertions ci-dessous (en supposant que la date du jour est le 10 février 2004 ) :
INSERT INTO employes (num_emp, nom_emp, date_emb)
VALUES (123, ‘Martinet’, TO_DATE('10/02/2004',
'DD/MM/YYYY'));
INSERT INTO employes (num_emp, nom_emp, date_emb)
VALUES (124, ‘Dimort’, SYSDATE);
La requête ci-dessous ne renverra que la ligne concernant monsieur ou madame Martinet.
SELECT nom_emp, date_emb
FROM employes
WHERE date_emb = TO_DATE('10/02/2004',
'DD/MM/YYYY');
En effet, les dates contiennent aussi une information “temps”. Avec SYSDATE, la valeur est
l’heure courante, avec TO_DATE c’est « zéro heure ». D’où la différence de traitement dans la
sélection opérée.
Comme solution lorsqu’on sélectionne sur la date, mais pas sur l’heure : utiliser la fonction
TRUNC pour ne considérer que la partie « date », par exemple dans l’insertion si la partie « heure »
de l’information n’est pas utile.
INSERT INTO employes (num_emp, nom_emp, date_emb)
VALUES (124, ‘Dimort’, TRUNC(SYSDATE));

34
4.4. Définition de données
L’instruction de base pour définir des données est CREATE TABLE. Nous allons définir 4 tables
que nous utiliserons ensuite dans tous les exemples de requêtes. Il s’agit des tables FOURNISSEUR,
PRODUIT, STOCK et EMPLOYES.
La table fournisseur contient les informations suivantes :
• Le numéro de fournisseur :num_f, clé primaire de la relation. C’est un entier, on souhaite
que la valeur de ce nombre soit gérée par le système (incrément à chaque nouveau tuple).
• Le nom du fournisseur : nom_f, de type chaîne de caractères, de taille maximum 20, doit
toujours être saisi.
• La ville du fournisseur : ville, de type chaîne de caractères, taille maximum 20
• Le pourcentage de remise qu’il me consent : remise, de type entier. Remise doit être
compris entre 0 et 50.
La table produit est définie à partir de :
• Le numéro de produit, num_p, clé primaire de la table. C’est un entier, on souhaite que la
valeur de ce nombre soit gérée par le système (incrément à chaque nouveau tuple).
• La désignation du produit, désignation, chaîne de caractère d’au plus 30 caractères, doit
toujours être saisie.
• La couleur du produit, couleur, chaîne de caractères d’au plus 10 caractères, la valeur par
défaut est BLEU
• L’origine de fabrication du produit, origine chaîne d’au plus 30 caractères
La table stock est constituée de :
• Le numéro du produit, num_p
• Le numéro du fournisseur : num_f
• La quantité en stock : qté, un entier toujours différent de NULL.
La clé de la table stock est le couple formé des deux clés étrangères (num_p, num_f). On demande
l’application des contraintes d’intégrité référentielles.
La table EMPLOYES contient les données :
• Le numéro de l’employé, num_emp. C’est la clé primaire de la table. Sa valeur, un entier,
devra être gérée par le système.
• Le nom de l’employé, nom_emp, une chaîne de caractères d’au plus 20 caractères, ne
pouvant jamais prendre la valeur NULL.
• Le numéro de son supérieur hiérarchique, n_sup, est un entier
• Le salaire mensuel de l’employé, salaire, valeur numérique réelle
• La fonction de l’employé, fonction, chaîne de caractères d'au plus 10 caractères.
• Le numéro du service, n_service, dans lequel travaille l’employé, entier.
L’instruction CREATE TABLE doit avoir la forme suivante :
CREATE TABLE nom_de_la_table (
nom_de_la_colonne1 type_de_la_colonne1,
nom_de_la_colonne2 type_de_la_colonne2,

)

35
Lors de la définition de la table, il faut ajouter les contraintes d'intégrité mises en évidence lors de
la conception.
4.4.1.
Types de données

Les principaux types de données oracle


Les principaux types prédéfinis pour les colonnes vous sont donnés ci-après. D'autres types de
données existent, en particulier pour gérer des données de grande taille.
NUMBER Valeur numérique NUMBER(2)
On peut préciser le NUMBER(10,2)
nombre de chiffre et le
nombre de décimales
CHAR(size) Données caractère de CHAR(5)
longueur fixe
VARCHAR2 Chaîne de caractères VARCHAR2(30)
de taille variable.
La taille maximale doit
être précisée
DATE Valeur de date et DATE
heure

Les principaux types de données ANSI supportés par oracle


Des ordres de création de table utilisant des types ANSI seront exécutés par oracle. Cependant,
chaque donnée stockée dans une colonne de type ANSI est en fait convertie et stockée dans le type
oracle correspondant (cf. la tableau ci-après).
Libellé du type Description Type oracle correspondant
ANSI
INT Valeur numérique NUMBER(38)
entière
INTEGER
SMALLINT
NUMERIC(p,s) Valeur numérique avec NUMBER(p,s)
spécification d’une
précision
FLOAT NUMBER
REAL
CHARACTER(size) Données caractère de CHAR(5)
longueur fixe
CHAR(n) Chaîne de caractères de VARCHAR2(n)
taille variable.
La taille maximale doit être
précisée

36
4.4.2. Valeurs par défaut
Lorsque l’on insère ou que l’on modifie des tuples, on a pas toujours de valeurs pour tous les
éléments. Dans le cas d’une insertion, si une colonne n’est pas mentionnée dans l’ordre INSERT
INTO, c’est la valeur NULL qui sera affectée pour cette colonne dans la ligne insérée.
Il est possible, lors de la définition de la colonne dans l’ordre CREATE TABLE de placer une
valeur par défaut. Cette valeur doit être une constante, ou une valeur fournie par le système, comme la
date courante.
Date_emb DATE DEFAULT SYSDATE

4.4.3. Contraintes d'intégrité


Ce chapitre présente les moyens fournis pas le SGBD pour réaliser un ensemble de vérifications
lors de la mise à jour des données. Réalisées au niveau du SGBD, ces vérifications déchargent les
programmes d’applications de contrôles complexes et répétitifs car ils sont à effectuer lors de chaque
mise à jour des données.
SQL nous fournit un certains nombre de moyens pour définir des contraintes d’intégrité. Ces
contraintes font partie du schéma de la base de données. Cependant, elles ne suffisent pas à exprimer
toutes les vérifications nécessaires. Il sera alors nécessaire d’utiliser des triggers.

Nommer les contraintes


Il est préférable de nommer les contraintes si l’on souhaite modifier ou supprimer une contrainte
existante. Respectez une convention de nommage comme par exemple table_colonne_contrainte. Si
vous ne nommez pas vos contraintes, Oracle génère un nom automatiquement.
La syntaxe permettant de définir une contrainte est la suivante :
CONSTRAINT nom_de_la_contrainte type_de_contrainte

Clés : PRIMARY KEY, FOREIGN KEY


La clé primaire est déclarée lors de la création de la table. Il y a une seule clé primaire. Le mot
« clé » est utilisé aussi pour désigner la contrainte d’intégrité référentielle ou « clé étrangère ».

CLE PRIMAIRE
L’effet de la déclaration d’un attribut, ou un ensemble d’attributs comme clé primaire est
d’interdire des doublons et la valeur NULL sur cet ou ces attributs.
On peut déclarer une clé primaire soit lors de la définition de l’attribut (1), soit à la fin de la
définition de la table (2). Dans l’exemple (2), la contrainte est nommée.
(1)
CREATE TABLE fournisseur (
num_f NUMBER(3) PRIMARY KEY,
nom_f VARCHAR2(20) NOT NULL,
ville VARCHAR2(20),
remise NUMBER(2)
);

(2)
CREATE TABLE fournisseur (
num_f NUMBER(3),
nom_f VARCHAR2(20) NOT NULL,
ville VARCHAR2(20),
remise NUMBER(2),
CONSTRAINT PK_fournisseur PRIMARY KEY(num_f)

37
);

Dans le cas où la clé primaire est constituée de deux attributs, la formulation (1) n’est pas possible.
CREATE TABLE stock (
num_f NUMBER(3),
num_p NUMBER(4),
qte NUMBER(4) NOT NULL,
CONSTRAINT PK_stock PRIMARY KEY (num_f, num_p)
);

MISES EN ŒUVRE DES CONTRAINTES DE CLE PRIMAIRE


Un index est généralement associé à la clé primaire d’une table. Cette définition d’index est réalisée
par le SGBD. Construire un index sur la clé primaire permet de rendre plus efficaces toutes les
requêtes – très fréquentes – qui mettent en jeu la clé primaire. De plus, cet index va être très utile pour
mettre en œuvre la contrainte de clé primaire. La vérification de l’unicité de la clé doit s’effectuer lors
d’une mise à jour ou d’une insertion. L’index va permettre de vérifier rapidement l’existence d’un
tuple ayant la même valeur pour la colonne considérée. Si c’est le cas, la mise à jour doit échouer.

CLE ETRANGERE
La clé étrangère permet de mettre en œuvre une contrainte d’intégrité référentielle.

Déclarer une clé étrangère


Une clé étrangère peut être définie soit (1) lors de la déclaration de la colonne soit (2) à la fin de la
définition de la table. Dans l’exemple (2) la contrainte est nommée.
(1)
CREATE TABLE stock (
num_f NUMBER(3) REFERENCES fournisseur(num_f),
num_p NUMBER(4),
qte NUMBER(4) NOT NULL,
PRIMARY KEY(num_f, num_p)
);

(2)
CREATE TABLE stock (
num_f NUMBER(3),
num_p NUMBER(4),
qte NUMBER(4) NOT NULL,
PRIMARY KEY(num_f, num_p),
CONSTRAINT FK_stock_numf FOREIGN KEY(num_f)
REFERENCES fournisseur(num_f)
);

Conserver l’intégrité référentielle


La stratégie par défaut est de rejeter toute modification qui ne respecte pas la contrainte d’intégrité
référentielle. Ainsi un ordre INSERT INTO dans la table stock qui concerne un numéro de fournisseur
absent de la table fournisseur, génèrera une erreur, et l’insertion de sera pas réalisée. De même une
suppression dans la table fournisseur d’une ligne pour laquelle le numéro de fournisseur apparaît aussi
dans la table stock sera refusée.
Des stratégies alternatives existent.

CASCADE

38
Les changements (suppression, modification) opérés sur l’attribut référencé sont propagés sur la clé
étrangère. Dans ce cas, la suppression d’un fournisseur peut entraîner la suppression des lignes
correspondantes dans la table stock.

SET NULL
Les changements (suppression, modification) opérés sur l’attribut référencé entraînent une mise à
NULL de la clé étrangère.
CREATE TABLE stock (
num_f NUMBER(3),
num_p NUMBER(4),
qte NUMBER(4) NOT NULL,
CONSTRAINT PK_stock PRIMARY KEY(num_f, num_p),
CONSTRAINT FK_stock_numf FOREIGN KEY (num_f)
REFERENCES fournisseur(num_f) ON DELETE CASCADE
);

Remarque : seul le cas de la suppression est géré par oracle.

Contraintes CHECK niveau colonne


Une contrainte niveau colonne référence une seule colonne et se définit dans la spécification de
cette colonne.
En pratique, la contrainte CHECK permet de définir les valeurs possibles pour une colonne en
listant les valeurs possibles. En théorie, une contrainte CHECK peut être formulée de manière plus
complexe.
CREATE TABLE employes (
num_emp NUMBER(3) CONSTRAINT emp_pk PRIMARY KEY,
nom_emp VARCHAR2(20) CONSTRAINT NN_nomemp NOT NULL,
n_sup NUMBER(3),
salaire NUMBER(7,2) CONSTRAINT emp_sal_ck CHECK
(salaire >= 1000),
fonction VARCHAR2(10) CONSTRAINT emp_fonc_ck CHECK
(fonction IN
('INGENIEUR','TECHNICIEN','DIRECTEUR')),
n_service NUMBER(2),
date_emb DATE DEFAULT SYSDATE
);
La condition peut contenir une sous-requête.
La contrainte est vérifiée lors de l’insertion d’un nouveau tuple ou lors de la modification d’un
tuple.

Contrainte UNIQUE
Une autre façon de définir un clé est d’utiliser le mot-clé UNIQUE. C’est presque la même chose
que « PRIMARY KEY » à ceci près que (1) il peut y avoir plusieurs colonnes UNIQUE et (2) les
valeurs NULL sont permises.

Récapitulatif
Elle est applicable à n'importe quelle type de contrainte d'intégrité. Les contraintes niveau table
référencent une ou plusieurs colonnes et se définissent indépendamment de la déclaration d’une
colonne particulière.
Contrainte Description Niveau

39
NOT NULL Cette colonne ne doit pas COLONNE
contenir de valeur NULL
UNIQUE Spécifie une colonne ou COLONNE ou
une combinaison de colonnes TABLE (obligatoire si
dont les valeurs doivent être cela concerne plusieurs
uniques pour toutes les lignes colonnes)
de la table
PRIMARY KEY Identifie chaque ligne de COLONNE ou
la table de manière unique TABLE (obligatoire si
cela concerne plusieurs
colonnes)
FOREIGN KEY Etablit et contrôle une COLONNE ou
relation de clé étrangère entre TABLE (obligatoire si
la colonne et une colonne de cela concerne plusieurs
la table référencée. colonnes)
CHECK Spécifie une condition qui COLONNE ou
doit être vraie TABLE

Nommer les contraintes


Il est préférable de nommer les contraintes si l’on souhaite modifier ou supprimer une contrainte
existante. Respectez une convention de nommage comme par exemple table_colonne_contrainte. Si
vous ne nommez pas vos contraintes, Oracle génère un nom automatiquement.
La syntaxe permettant de définir une contrainte est la suivante :
CONSTRAINT nom_de_la_contrainte type_de_contrainte

Accéder aux contraintes définies


Pour vérifier les définitions et noms de toutes les contraintes, utilisez la table
USER_CONSTRAINTS.
SELECT constraint_name, constraint_type, table_name
FROM user_constraints
WHERE table_name = 'Fournisseur';

4.4.4. Supprimer les tables


L’instruction permettant de supprimer une table est :
DROP TABLE nom_de_la_table ;
La table est détruite définitivement ainsi que les données qu’elle contenait.

4.4.5. Modifier la définition d’une table


L’instruction permettant de modifier une table, par exemple pour lui ajouter une colonne est la
suivante :
ALTER TABLE nom_de_la_table
ADD (nom_colonne type_colonne) ;
Pour modifier une colonne (le type de données, la valeur par défaut) :

40
ALTER TABLE nom_de_la_table
MODIFY (nom_colonne le_colonne [DEFAULT expr]) ;
Par exemple, pour changer la valeur par défaut de la table PRODUIT :
ALTER TABLE produit
MODIFY (couleur VARCHAR2(10) DEFAULT 'ROUGE');

4.4.6. Accéder à la description des tables


Pour accéder à la description des tables vous appartenant interroger le dictionnaire de données :
SELECT *
FROM user_tables;

4.5. Index
Un index sur un attribut A est une structure de données que augmente la performance des requêtes
qui contiennent des comparaisons de A avec une constante. Par exemple A < 10 ou A = 10.
Quand les tables sont très volumineuses, trouver les lignes qui répondent à un critère tel que « A =
10 » est extrêmement coûteux. En effet, pour trouver ces lignes, il faut que la comparaison s’effectue
pour chacun des tuples de la table. S’il y en a 15 000 et qu’un seul correspond au critère, il faut au pire,
réaliser 15 000 comparaisons. Cela serait plus rapide si nous disposions d’un moyen qui nous permette
d’obtenir directement le tuple qui correspond au critère de sélection.
Un index peut être créé de la manière suivante :
CREATE INDEX aIndex ON relation(A) ;
aIndex est le nom de l’index, A l’attribut de la relation “relation”.
Une fois l’index créé, toutes les requêtes SQL qui impliquent une comparaison sur A seront
exécutées de telle sorte que seuls les tuples de la relation ayant la valeur recherchée sur l’attribut A
seront examinés. Le temps d’exécution de la requête est alors significativement réduit.
Il est possible de définir un index sur plusieurs attributs. Cela permet de trouver plus rapidement
des tuples qui ont une valeur particulière pour chacun des attributs impliqués dans l’index.
Par exemple, dans la table stock, la clé est constituée des attributs num_f et num_p. Si nous créons
l’index de cette façon :
CREATE INDEX keyIndex ON stock(num_f, num_p) ;
Comme le couple (num_f, num_p) est la clé, nous savons que lorsque pour une valeur de num_f et
num_p donnée, nous n’aurons qu’un unique tuple dans la table qui sera le tuple recherché. L’ordre des
attributs dans la création d’un index multi-attributs n’est pas sans importance. Il est préférable de
placer en premier l’attribut qui sera sollicité le plus souvent lors des requêtes.

4.5.1. Introduction au choix d’index


Le choix des index est important pour la performance d’une application, et il requiert un
compromis. En effet, les deux facteurs à prendre en compte sont les suivants :
• La présence d’un index augmente très sensiblement la rapidité des requêtes qui
sélectionnent une valeur particulière pour cet attribut, et parfois accroît aussi la rapidité des
jointures impliquant cet attribut
• Un index créé sur un attribut d’une relation rend les insertions, suppressions, et
modifications de cette relation plus compliquées et plus coûteuses en temps. En effet, un
index est une structure de données qui doit elle-même être modifiée lors de ces opérations
de mises à jour.

41
Si on estime qu’une table sera plus souvent interrogée que mise à jour, et que l’on peut déterminer
quels sont les attributs que l’on retrouvera le plus souvent dans les sélections ou dans les jointures, une
création d’index peut s’imposer. Si les opérations prédominantes sont des modifications, alors mieux
vaut être prudent. Cependant, même dans ce cas, un gain de performance peut être obtenu par un index
si les modifications impliquent une requête sur la base (par exemple un INSERT avec une sous requête
SELECT FROM WHERE, ou un DELETE avec une condition).

4.6. Création de vues


Une vue est une table logique basée sur une ou plusieurs tables. C'est comme une fenêtre par
laquelle on peut visualiser ou modifier des données venant des tables.
Les vues permettent:
• de limiter l'accès à la base de données
• de faciliter la création de requête complexes
On parle de vue simple lorsque les vues sont basées sur une unique table et qu'elles ne contiennent
ni fonctions ni groupes de données. Dans ce cas, on peut réaliser des opérations de modifications de
données à partir de la vue.
On parle de vue complexe lorsque la vue est basée sur une ou plusieurs tables et qu'elle contient des
fonctions et des groupes de données. Dans ce cas, il n'est pas toujours possible de réaliser des
opérations de modification de données à travers la vue.
Voici un exemple de création de vue :
CREATE VIEW empvue
AS SELECT num_emp, nom_emp, fonction
FROM employes
WHERE num_dept = 10;
On peut interroger les vues comme on le fait des tables :
SELECT *
FROM empvue;

4.7. Exécution d'un ordre SQL


Dans un ordre SQL, on spécifie les données que l'on veut visualiser, mais on ne fournit pas les
algorithmes d'accès aux données. C'est l'optimiseur qui transforme la requête en un plan d'exécution
composé d'une suite d'opérations de bas niveau réalisant l'accès aux données. L'objectif de tels
programmes, intégrés aux SGBD, est de trouver le moyen le plus efficace de traiter et d'exécuter une
commande SQL.
L'optimisation de requêtes passe par une étape d'analyse de la requête : la validité syntaxique est
vérifiée, la validité des noms de colonnes et de tables, celle des droits d'accès aux objets. Pour élaborer
le plan d'exécution, l'optimiseur devra réécrire la requête en une séquence d'opérations élémentaires de
l'algèbre relationnel, puis évaluer les coûts d'exécution en minimisant le nombre d'entrées/sorties et le
temps de calcul. Plusieurs plans peuvent être générés (il n'est pas toujours possible de les générer
tous), celui de coût minimal (ou proche du minimum) est retenu.
L'existence de l'optimiseur ne dispense ni le développeur de s'intéresser aux performances des
applications, ni l'administrateur de chercher à améliorer les performances de la base de données. En
effet, lorsque de nouvelles applications utilisant des bases de données sont installées, il n'est pas rare
que les utilisateurs se plaignent de performances médiocres. Une application optimisée a pour
avantage de permettre aux utilisateurs finaux de travailler efficacement, d'exploiter efficacement les
ressources du système, de moins solliciter développeurs et administrateurs.

42
5. GESTION DES TRANSACTIONS
Deux objectifs des systèmes de gestion de bases de données sont concernés par la notion de
transaction. Il s’agit de la sécurité des données et de la gestion des accès concurrents aux données.
Quels sont les problèmes ?
Dans le cas d’une application bancaire, nous pouvons nous trouver dans le cas suivant. Monsieur
Dupont est avec son banquier pour un problème de découvert sur son compte courant. Il demande
d’effectuer un transfert à partir de son CODEVI vers son compte courant. Au même moment (ou
presque) Madame Dupont consulte les deux comptes sur internet.

Temp Monsieur Dupont Madame Dupont


s
t1 Débiter CODEVI 20 000 F
t2 Consulte CODEVI
t3 Consulte Compte courant
t4 Créditer Compte courant 20 000F

Dans ce cas, la consultation fournit un résultat incohérent : Mme Dupont constate que le CODEVI
a été débité mais le compte courant, lui, est toujours à découvert. De même, dans le cas où une panne
surviendrait après le débit du CODEVI mais avant le crédit sur le compte courant, les Dupont
perdraient leurs économies.
Pour éviter ces problèmes, il est nécessaire de mettre en œuvre des protocoles qui permettent de
synchroniser les traitements concurrents et de restaurer une base de données dans un état cohérent
après une défaillance. Ces protocoles sont complexes. Les SGBD offrent de tels protocoles, ce sont les
protocoles transactionnels.

5.1. La notion de transaction


Une transaction est un script décrivant des opérations (lecture, écriture) sur les objets du système
d’information. Par exemple, une transaction peut contenir une séquence de consultation de comptes,
un retrait d’argent et un virement d’un compte à un autre. Une transaction doit vérifier les propriétés
d’Atomicité, de Cohérence, d’Isolation et de Durabilité. Ces propriétés sont résumées par
l’acronyme ACID.

ATOMICITE
Une transaction doit se dérouler complètement et elle a alors les effets désirés (on dit qu’elle est
validée) ou elle est interrompue et elle n’a aucun effet (on dit qu’elle est abandonnée). Dans ce dernier
cas, le système doit annuler toutes les modifications engagées par la transaction. L’atomicité est
menacée en particulier par des pannes du système ou du matériel.

Temp Transaction
s
t1 Débiter CODEVI
t2 DEFAILLANCE
t3 Créditer Compte Courant

Fig 5. Atomicité

43
Dans le cas où le transfert est interrompu par une défaillance du système, la transaction doit être
abandonnée complètement : le débit sur le CODEVI ne doit pas être réalisé. De cette manière la base
reste dans un état cohérent.

COHERENCE
Une transaction préserve la cohérence des objets qu’elle manipule. Cette cohérence peut être
menacée par une erreur dans un programme ou par un conflit d’accès concurrent entre transactions.
Temp Transaction
s
t1 Débiter CODEVI 20 000F
Les
montants
t2 doivent être
t3 Créditer Compte Courant 2 000 F identiques

Fig 6. Cohérence
Le maintien de la cohérence repose sur les contraintes d'intégrité imposées sur la base. Si un
transfert d'un compte vers un autre est défini comme "Débiter une somme sur le compte 1 et créditer la
même somme sur le compte 2", cette propriété doit être garantie lors des transactions.

ISOLATION
Les effets d’une transaction sont invisibles aux autres transactions concurrentes. Autrement dit, il
ne doit pas y avoir d’interférence avec les autres transactions.
Temp Monsieur Dupont Madame Dupont
s
t1 Débiter CODEVI 20 000 F
t2 Consulte CODEVI
t3 Consulte Compte courant
t4 Créditer Compte courant 20 000F

Fig 7. Isolation
La consultation réalisée par madame Dupont doit lui fournir un résultat cohérent : le débit réalisé
par monsieur Dupont ne devra être visible qu'à l'issue de sa transaction.

DURABILITE
Les effets d’une transaction validée sont permanents.
Une défaillance postérieure à la validation de la transaction n’affectera pas les résultats du transfert
entre le CODEVI et le compte courant de M. Dupont.
Les systèmes transactionnels assurent les propriétés AID (atomicité, isolation, durabilité) en
contrôlant la concurrence. La propriété C (cohérence) est du ressort du programmeur : à lui de
programmer les transactions pour assurer cette cohérence.

5.2. Contrôle de la concurrence


L’objectif du contrôle de la concurrence est de rendre invisibles aux clients le partage simultané des
données. Cette transparence nécessite de mettre en place des mécanismes de contrôle des accès
concurrents au sein du SGBD. Ceux-ci s’effectuent grâce à des protocoles spéciaux chargés de
synchroniser les opérations de mises à jour et de lecture afin d’éviter pertes d’informations et
apparitions d’incohérence, tout en permettant l’entrelacement des actions. Une des techniques
fréquemment utilisée est le protocole de verrouillage à deux phases.

44
5.2.1. Protocole de verrouillage à deux phases
Cette technique repose sur l'utilisation de verrous. On distingue les verrous de lecture qui sont
partagés (on peut permettre plusieurs accès simultanés en lecture) et les verrous d'écriture qui sont
exclusifs (toute lecture simultanée et bien sûr toute autre écriture sont interdites).
Deux opérations élémentaires sont gérées :
• Verrouiller un objet x en mode lecture ou écriture : verrouiller[x, mode]
• Libérer le verrou : déverrouiller[x]
La taille de l'objet x (une table, une partie d'une table, un tuple, etc.) est un élément important du
mécanisme de verrouillage. En effet, plus l'objet x est petit, plus le degré de concurrence est grand. En
contrepartie, le temps dédié au contrôle risque d'être élevé. Un objet de grande taille réduit le temps
absorbé par le contrôle mais peut accroître le temps d'attente.
Les verrous sont demandés par les transactions. Ils ne sont pas forcément obtenus : cela dépend des
verrous déjà posés par d'autres transactions (cf. tableau ci-dessous). Si la transaction demandeuse
n'obtient pas ses verrous, elle est mise en attente.
Verrou détenu → Lecture Ecriture
Verrou demandé ↓
Lecture OUI NON
Ecriture NON NON

Le principe du verrouillage à deux phases est le suivant :


Chaque opération de lecture (ou écriture) doit être précédée d'une demande de verrous et doit être
suivie d'une libération de verrous. Donc une transaction va d'abord poser tous les verrous dont elle a
besoin. A la fin de son exécution, elle est validée. C'est seulement après cette validation qu'elle libère
tous les verrous posés. D'où le nom de verrouillage à deux phases.

5.2.2. Inter-blocage
Des transactions concurrentes peuvent être mises en attente, d'où des problèmes possibles d'inter-
blocage (dead lock en anglais).
Temp Transaction 1 Transaction2
s
t1 Verrouiller[x, lecture]
t2 Lire[x]
t3 Verrouiller[y, lecture]
t4 Lire[y]
t5 Verrouiller[y, écriture]
t6 Verrouiller[x, écriture]

Les deux transactions manipulent les objets x et y. Si le plan d'exécution indiqué par les numéros
est suivi, l'opération à t5 met la transaction 1 en attente car y est verrouillé en lecture par la transaction
2. Ce verrou ne peut être libéré qu'après la validation de transaction 2. De même, l'opération à t6 met la
transaction 2 en attente. Il y a attente mutuelle et risque de paralysie si des mécanismes de prévention
ou de guérison des inter-blocages (généralement par abandon d'une des transactions) ne sont pas mis
en œuvre.

45
5.2.3. Granule de verrouillage
Le granule de verrouillage est un paramètre qui affecte les performances. Ce granule peut être
logique (table, ligne) ou physique (segment, fichier, page). La taille du granule influence le degré de
concurrence, mais il entraîne des contrôles plus importants. Les petits granules sont plus adaptés aux
transactions courtes manipulant peu de données, alors que les granules plus importants sont mieux
adaptés aux transactions lourdes.

5.3. Transactions et reprise


Nous avons évoqué précédemment (cf. propriété d'Atomicité) la nécessité de rétablir la cohérence
en cas d'une fin anormale de la transaction. Les raisons de l'échec d'une transaction sont variées :
erreur hardware, erreur de programmation, etc. Dans nombre de cas d'échec le système pourra tenter
(et réussir) le rétablissement de la cohérence de la base. Pour cela, il doit disposer de suffisamment
d'informations sur les opérations qui ont précédé le moment de l'incident. C'est le rôle du journal des
transactions (ou log).
Le journal contient des informations concernant chaque transaction (identification de la transaction,
donnée concernée par l'opération, ancienne et nouvelle valeur, etc.) En cas d'incident, le système est à
même d'annuler les effets des transactions non validées et de rejouer les actions de celles qui ont été
validées.

5.4. Transactions en SQL avec oracle


Dans oracle, une transaction commence à l'exécution du premier ordre SQL et se termine par une
validation (COMMIT) ou une annulation (ROLLBACK), ou encore par la fin de la session utilisateur
(COMMIT implicite) ou par une panne du système (ROLLBACK automatique). Les ordres du LDD
(Langage de Définition de Données) valident automatiquement les transactions.

5.4.1. Verrouillage implicite


Oracle effectue automatiquement tous les verrouillages nécessaires pour le maintien de la
cohérence des données. Ils sont effectués sans aucune intervention de l'utilisateur. Le verrouillage
s'effectue au niveau des lignes. L'exemple ci-après illustre la mise en œuvre de ce mécanisme.
Temps Transaction1 Transaction2
t1 SQL> SELECT *
2 FROM stock;
NUM_F NUM_P QTE
t2
--------- ------ ------- SQL> SELECT *
2 1 10 2 FROM stock;
2 1 10 NUM_F NUM_P QTE
2 3 97 --------- ------ -------
6 3 47 2 1 10
4 4 20 2 1 10
t3
7 4 10 2 3 97
6 1 10 6 3 47
t4 7 ligne(s) sélectionnée(s). 4 4 20
7 4 10
6 1 10
7 ligne(s) sélectionnée(s).

46
t5 SQL> UPDATE stock
2 SET qte = qte + 2
3 WHERE num_p = 1; SQL> UPDATE stock
3 ligne(s) mise(s) à jour. 2 SET qte = 0
3 WHERE num_p = 1;

SQL> commit;
Validation effectuée.
3 ligne(s) mise(s) à jour.
SQL>
Les deux transactions ci-dessus démarrent à la première instruction SQL exécutée, soit la lecture de
la table stock. Le verrou partagé obtenu par la transaction 1 permet une lecture concurrente demandée
par la transaction 2. L'instruction de mise à jour dans la transaction 1 a eu pour conséquence
l'obtention d'un verrou exclusif sur les lignes concernées par la modification. La transaction 2 est donc
mise en attente. Lors de la validation de la transaction 1, les verrous posés sont libérés et la transaction
2 peut se terminer.

5.4.2. Lectures inconsistantes niveau transaction


Le mécanisme par défaut offert par oracle peut entraîner des lectures inconsistantes : une
transaction qui n'opère que des lectures sur la base peut cependant permettre de visualiser des
modifications réalisées dans d'autres transactions. Ceci n'est pas forcément souhaité.

Fig 8. Lectures inconsistantes niveau transaction


Après validation de la transaction 1, la modification apportée à la table produit est rendue
visible à la transaction 2. Pourtant celle-ci n'a réalisé que des lectures. Offrir le respect de la
consistance des données au niveau d'une transaction consiste à rendre invisibles à une transaction

47
les modifications réalisées par les transactions concurrentes, même après la validation de ces
transactions.

5.4.3. Verrouillage explicite


Oracle permet d'obtenir la consistance de lecture niveau transaction. Dans l'exemple ci-après
l'instruction SET TRANSACTION READ ONLY permet de rendre invisibles à la transaction 2 les
modifications réalisées la transaction 1 (après le début de la transaction 2). Le mode READ ONLY
reste valable jusqu'à la fin de la transaction 2. Le mode par défaut est ensuite rétabli.

Fig 9. Consistance de lecture niveau transaction

5.4.4. Lecture avec intention de modification


L'exemple ci-dessous illustre un second moyen d'intervention explicite sur le mécanisme de
verrouillage. La transaction 2 réalise un verrouillage exclusif des lignes de la table PRODUIT vérifiant
la condition, dès l'opération de lecture. Les autres transactions sollicitant un verrou sur ces mêmes
lignes seront mises en attente.

Fig 10. Verrouillage explicite : SELECT … FOR UPDATE

Oracle offre d'autres possibilités d'agir sur le verrouillage des données.

48
6. BIBLIOGRAPHIE
N. Boudjlida, Bases de données et systèmes d'informations, Dunod, 1999.
G. Gardarin, O. Gardarin, Le client-serveur, Eyrolles, 1996.
Editions ENI, Oracle 8, Editions ENI, 1998.
C. Morley, J. Hugues et B. Leblanc UML pour l’analyse d’un système d’information 2ième édition
Paris : Dunod 2002 232p
J.D. Ullman et J. Widom A first course in database systems 2ième édition Prentice Hall 2002 511p
C. Soutou De UML à SQL Paris : Eyrolles 2002 500p
M. Blaha et J. Rumbaugh Modélisation et conception orientées objet avec UML 2 2ième édition
Paris : Pearson education France 2005 585 p.

49
7. INDEX
ALTER TABLE, 41 MOD, 32
BETWEEN, 17 Modification de tuples, 30
CASCADE, 39 NEXTVAL, 29
CONCAT, 31 NULL, 13, 16, 23
CONSTRAINT, 37, 40, Voir Contraintes NVL, 23
d'intégrité ROUND, 32
contraintes d'intégrité, 36 séquence, 29
COUNT, 22, 23 SET NULL, 39
CREATE TABLE, 35 sous-requête, 30
DEFAULT, 37 SYSDATE, 32, 34
DELETE FROM TABLE, 30 TO_CHAR, 33
DISTINCT, 14 TO_DATE, 33
DROP TABLE, 41 TO_NUMBER, 33
DUAL, 32 TRUNC, 32, 35
index, 38, 42 types, 36
INSERT INTO, 29 user_constraints, 40
IS NULL, 17 user_sequences, 29
LIKE, 17 user_tables, 41

50

Vous aimerez peut-être aussi