Académique Documents
Professionnel Documents
Culture Documents
José Gil
EXPLOITATION
DES DONNÉES
COURS
Retrouvez la liste de nos formations sur www.cned.fr
Pour plus d’informations, appelez le 05 49 49 94 94
Du lundi au vendredi, 8 h 30-18 h.
Coût d’une communication ordinaire.
*82943TGPA0013* www.cned.fr
Sommaire
Conseils généraux 3
Séquence 1 : Présentation de SQL 5
Séquence 2 : Le langage d’interrogation des données (LID) 23
Séquence 3 : Le langage de modification des données (LMD) 69
Séquence 4 : Le langage de description des données (LDD) 79
Séquence 5 : Le langage de contrôle de données (LCD) 97
Séquence 6 : Le langage de contrôle des transactions (LCT) 119
Corrigé des exercices 133
Les cours du CNED sont strictement réservés à l’usage privé de leurs destinataires et ne sont pas destinés à une utilisation collective.
Les personnes qui s’en serviraient pour d’autres usages, qui en feraient une reproduction intégrale ou partielle, une traduction sans
le consentement du CNED, s’exposeraient à des poursuites judiciaires et aux sanctions pénales prévues par le Code de la propriété
intellectuelle. Les reproductions par reprographie de livres et de périodiques protégés contenues dans cet ouvrage sont effectuées
par le CNED avec l’autorisation du Centre français d’exploitation du droit de copie (20, rue des Grands Augustins, 75006 Paris).
© CNED 2013
Conseils généraux
Présentation générale du module
Ce module intervient au premier semestre de la première année. Le référentiel lui
réserve 4 heures de cours / TP par semaine sur 15 semaines, ce qui représente un volume
total de 60 heures. Il faut cependant compter beaucoup plus d’heures de travail person-
nel pour les exercices.
Ce module concerne les deux options de la formation (SLAM et SISR).
Il porte sur un langage extrêmement important dans le monde des bases de données. Il
existe de nombreux logiciels de gestion de bases de données. Tous sont différents, soit
par leurs modes de fonctionnement, soit par leurs origines ou philosophies respectives.
Ils ont toutefois une chose en commun : ils utilisent le SQL au sein de leurs systèmes pour
interagir avec les bases de données.
Une fois que vous connaîtrez le SQL, vous pourrez manipuler des données de quasiment
n’importe quelle plateforme logicielle de gestion de bases de données.
Organisation du module
Le cours se décline en six séquences, ponctuées par des exercices applicatifs (dont la cor-
rection se trouve à la fin de ce fascicule) et des travaux pratiques.
Il est très important de suivre toutes les séquences, dans l’ordre, et de les réaliser dans
leur intégralité, quelles que soient vos connaissances préalables dans le domaine des
bases de données et du SQL. En effet, si vous avez déjà des connaissances, elles ne sont
peut-être pas totalement adaptées aux attentes de l’examen.
Conseils généraux
Ce cours est volontairement synthétique pour éviter de vous donner une surcharge de
travail. En contrepartie, tout ce qu’il contient est fondamental et c’est pour cette raison Page 3
qu’il faut le traiter en détail et dans son intégralité.
Deux devoirs d’évaluation sont à faire en respectant la chronologie suivante :
tDevoir 1 : à l’issue de la séquence 3 ;
tDevoir 2 : à l’issue de la séquence 4.
Outils
Dans ce cours, vous allez travailler avec les outils suivants :
PostgreSQL
SGBDR gratuit et téléchargeable sur le site officiel (http://www.postgresql.fr/accueil). Ce
cours a utilisé la version 8.4 mais vous pouvez a priori récupérer la version la plus récente.
Ce SGBDR est l’un des plus connus et des plus appréciés dans le monde gratuit : il est très
puissant et multiplateforme.
FlySpeed SQL Query
Logiciel gratuit permettant l’interrogation de bases de données. Il est téléchargeable sur le
site de l’éditeur Active Database Software : www.activedbsoft.com/overview-querytool.html.
Ce logiciel présente l’avantage de permettre la construction de requêtes graphiques tout
en générant du SQL compatible SQL-92.
Bon courage à tous !
8 2943 TG PA 00
Séquence 1
Présentation de SQL
Cette première séquence présente le langage SQL. Nous allons commen-
cer par un peu d’histoire et terminer par l’installation de PostgreSQL sous
Windows, l’utilisation de pgAdmin et l’installation de FlySpeed SQL Query
pour que vous puissiez programmer en SQL dès la fin de cette séquence.
X Prérequis
Aucun.
X Contenu
1. Qu’est-ce que le SQL ? ................................................................................. 6
2. Un peu d’histoire, normes et standards .................................................. 6 Séquence 1
8 2943 TG PA 00
1. Qu’est-ce que le SQL ?
C’est l’acronyme de Structured Query Language, soit en français : Langage structuré de
requêtes.
Ce langage, bientôt quarantenaire, permet d’assurer la gestion de bases de données
relationnelles. Sa syntaxe se présente sous la forme d’un pseudo-langage prenant appui
sur des mots de la langue anglaise.
La normalisation du SQL fait qu’il est utilisé par les principaux Systèmes de Gestion de
Bases de Données Relationnelles (SGBDR) : Oracle, DB2, SQL Server, MySQL, PostgreSQL …
Les développeurs de chacun de ces SGBDR ont adapté le SQL pour des besoins spéci-
fiques, on parle alors d’"extensions" (PL/pgSQL pour PostgreSQL, par exemple).
À la base, le SQL n’est pas un langage procédural. En effet, en SQL, lorsque vous voulez
obtenir quelque chose, il vous suffit d’indiquer au système ce que vous souhaitez obte-
nir. Alors qu’avec un langage procédural (VB6, par exemple), il vous faudrait dire au
système comment obtenir ce que vous souhaitez.
Mais ce n’est plus le cas. En 1999, lors d’une révision de la norme SQL (SQL-99), des fonc-
tionnalités procédurales ont été intégrées, satisfaisant ainsi des millions de développeurs
habitués à raisonner en procédural.
8 2943 TG PA 00
Ce modèle organise les données sous forme de tables en deux dimensions avec des index
de ligne permettant l’accès direct aux enregistrements.
Il faudra attendre 1974 pour qu’IBM crée SEQUEL (Structured English QUery Langage),
un langage d’interrogation des données respectant les concepts du modèle relationnel,
qui, deux ans plus tard, fut renommé en SQL. Dès lors, SQL devient le standard dans la
manipulation de bases de données.
En 1987, SQL est adopté comme norme par l’Organisation Internationale de Normalisation
(ISO) et, par la suite, subit un certain nombre de révisions :
t1989 : SQL-89
t1992 : SQL-92
t1999 : SQL-99
t2003 : SQL:2003
t2008 : SQL:2008
3. Le SGBDR
Le SGBDR est un ensemble logiciel permettant de définir, manipuler et administrer des Séquence 1
bases de données relationnelles.
Présentation de SQL
Il faut bien distinguer "La base de données" de son "SGBDR":
tLa base de données est un ensemble structuré et organisé de manière à pouvoir
Page 7
contenir des données.
tLe SGBDR est l’outil qui va vous permettre de créer la base de données et de mani-
puler les données qui se trouvent à l’intérieur.
8 2943 TG PA 00
4. Les différentes parties du SQL
Le langage SQL est divisé en cinq parties ayant chacune un périmètre bien défini :
tLangage d’Interrogation de Données (LID) : c’est la partie que nous utilisons le plus
fréquemment, celle qui nous permet d’extraire de l’information d’une base de don-
nées. Par exemple, on souhaite obtenir la liste de tous les articles (libellés et prix)
présents dans notre base dont le prix est strictement inférieur à 3 € :
UPDATE article
SET prix = prix * 0.93
WHERE idRayon = 9
tLangage de Définition de Données (LDD) : on utilise cette partie pour créer, modi-
fier ou détruire une base de données. Par exemple, on souhaite pouvoir identifier
un article "bio". Pour cela, on va modifier la structure de la table pour y ajouter une
nouvelle colonne "bio" de type booléen (oui/non) :
Séquence 1
ALTER TABLE article
ADD COLUMN bio BOOLEAN
Présentation de SQL
tLangage de Contrôle de Données (LCD) : c’est cette partie qui va nous permettre de
Page 8 sécuriser les accès à une base de données en indiquant des niveaux de privilèges.
Par exemple, on ne souhaite pas que n’importe quel utilisateur du SGBDR puisse
modifier les informations de la table articles :
REVOKE INSERT, UPDATE, DELETE
ON article
FROM PUBLIC
tLangage de Contrôle de Transactions (LCT) : cette partie va nous permettre de
sécuriser les transactions en nous donnant des mécanismes de sauvegarde et de
validation des transactions (pour éviter, par exemple, qu’une panne matérielle ou
logicielle ne vienne interrompre une transaction et ainsi risquer de corrompre des
informations). En cas d’erreur, le contrôle des transactions nous permet d’effectuer
des retours à des situations antérieures :
SAVEPOINT maSauvegarde
...
ROLLBACK TO SAVEPOINT MaSauvegarde
8 2943 TG PA 00
5. Installation de PostgreSQL et pgAdmin
Séquence 1
tUne fois le serveur PostgreSQL installé, vous pourrez constater que l’outil d’admi- Présentation de SQL
nistration pgAdmin a également été installé.
tLancez-le. Par défaut, vous verrez apparaître votre serveur local (serveur barré Page 9
d’une croix rouge).
tDouble-cliquez sur votre serveur pour vous y connecter. Une demande d’authenti-
fication apparaît. Saisissez le mot de passe que vous avez donné pendant l’instal-
lation :
8 2943 TG PA 00
6. Prise en main de pgAdmin
Fenêtre principale
Cette fenêtre affiche la structure des bases de données. À partir de cette fenêtre, on peut
créer de nouveaux objets, supprimer et modifier les objets déjà existants.
Rafraîchissement
Propriétés
Navigateur de l’objet
d’objets
Panneau
SQL
Séquence 1 Ligne de
statut
Présentation de SQL
8 2943 TG PA 00
Création d’un utilisateur pour le cours
tCliquez avec le bouton droit sur "Rôles de connexion" et choisissez "Ajouter un rôle
de connexion":
Séquence 1
Présentation de SQL
Page 11
tDans l’onglet "Droits du rôle", décochez la case "Hérite des droits des rôles parents",
cochez les cases "Peut créer des bases de données" et "Peut créer des rôles".
tLe dernier onglet "SQL" vous donne l’instruction SQL qui va être exécutée pour
créer le rôle.
8 2943 TG PA 00
tReconnectez-vous, le mot de passe qui vous est demandé est celui de l’utilisateur
"myuser":
Présentation de SQL
Page 12
Lorsque vous créez une base, une table ou même un champ dans PostgreSQL avec un outil
comme pgAdmin, veillez à toujours saisir les libellés en minuscules. C’est capital pour
que vos futures requêtes soient insensibles à la casse (indifférence majuscules / minuscules).
8 2943 TG PA 00
Contexte d’étude "magasin"
L’entreprise que nous allons étudier est un commerce de proximité de type "supérette"
organisé en rayons contenant des articles de diverses marques.
Lors du passage en caisse, on conserve la date, le détail des articles achetés ainsi que le
montant total qui a été réglé pour cet achat.
On conserve également les informations concernant les fournisseurs et les livraisons.
Pour chaque livraison, on mémorise le fournisseur ainsi que le ou les lots qui ont été
livrés.
Chaque lot concerne un seul article. Un lot est identifié par son numéro de lot et par le
code-barres de l’article qu’il concerne. Un article possède un identifiant unique, le code-
barres. C’est son appartenance à un lot qui permet de retrouver les informations qui le
concernent (dates de fabrication, de livraison et de péremption).
On peut d’ailleurs voir sur les photos suivantes quatre articles ayant le même code-
barres, mais des numéros de lot différents et donc des dates de péremption différentes.
Séquence 1
Présentation de SQL
Page 13
8 2943 TG PA 00
Schéma conceptuel de la base de données "magasin"
LOT ARTICLE RAYON
idLot
1,1 Placer 0,n
idArticle idRayon
(1,1) Appartenir 1,n
dateFabrication libelle libelle
dateLivraison prix
datePeremption packaging
MARQUE
uniteMesure
1,1 1,1 0,n idMarque
quantite Être
Livrer bio nom
0,n
0,n
FOURNISSEUR ListeCourses
idFournisseur quantite
raisonSociale
adresseRue 1,n
adresseCP ACHAT
adresseVille
email idAchat
numeroTelephone dateAchat
distanceKm montantTotal
Séquence 1
Présentation de SQL
Diagramme de classes de la base de données "magasin"
LOT ARTICLE RAYON
Page 14
idLot 1..* 1 idArticle * 1 idRayon
dateFabrication libelle libelle
dateLivraison prix
datePeremption packaging
uniteMesure
* quantite
* 1 MARQUE
bio
1 idMarque
1..* nom
FOURNISSEUR
idFournisseur
raisonSociale LISTECOURSES
adresseRue
quantite
adresseCP
adresseVille ACHAT
email idAchat
numeroTelephone * dateAchat
distanceKm montantTotal
8 2943 TG PA 00
Ces deux schémas sont issus de deux "mondes" différents :
s Le schéma conceptuel (également appelé "schéma entité/association") provient de la
méthodologie Merise qui a été, pendant des décennies, "la" méthode à utiliser pour
analyser et concevoir des projets informatiques.
s Le diagramme de classes est l’élément central du langage de modélisation UML.
Normalisé à la fin des années 1990, ce langage de modélisation orienté objet est de plus
en plus utilisé dans les projets informatiques.
Quelle que soit la modélisation, cela représente toujours des règles de gestion. Quelques
éléments pour comprendre les deux modélisations :
s Règle : Un article est placé dans un rayon.
s Règle : Une liste de courses représente un achat d’articles. Chaque article y figure une
seule fois, dans une certaine quantité.
Présentation de SQL
LISTECOURSES
Page 15
quantite
s Règle : Chaque lot concerne un seul article. Un lot est identifié par son numéro de
lot et par le code-barres de l’article qu’il concerne 1.
1. C’est d’ailleurs pour cela qu’au niveau relationnel (c’est-à-dire dans la description logique des
données), la relation "Lot" aura sa clé primaire, composée également de la clé primaire de la
relation "Article".
8 2943 TG PA 00
Schéma relationnel de la base de données "magasin"
FOURNISSEUR (idFournisseur, raisonSociale, adresseRue, adresseCP,
adresseVille, email, numeroTelephone, distanceKm)
idFournisseur : Clé primaire
FOURNISSEUR
idFournisseur numeric 2 4 0
raisonSociale character varying 3
adresseRue character varying
adresseCP character 4 5
adresseVille character varying
email character varying
numeroTelephone character varying
8 2943 TG PA 00
Nom Type de données Longueur Précision
distanceKm numeric 4 1
LOT
idLot character 10
dateFabrication date 5
dateLivraison date
datePeremption date
ARTICLE
idArticle numeric 13 0
libelle character varying
prix numeric 6 2
packaging character varying
uniteMesure character varying
quantite numeric 8 3
bio boolean 6
ACHAT
idAchat numeric 8 0
dateAchat date
montantTotal numeric 6 2
LISTECOURSES Séquence 1
quantité numeric 3 0
Présentation de SQL
RAYON
idRayon numeric 2 0 Page 17
libelle character varying
MARQUE
idMarque numeric 3 0
nom character varying
8 2943 TG PA 00
tSaisissez le "Nom" de la table (rayon) et son propriétaire (myuser).
tAllez dans l’onglet "Colonnes" et cliquez sur le bouton "Ajouter".
tSaisissez le "Nom" de la colonne (idrayon), le "Type de données" (numeric), la
"Longueur" (2), "Précision" (0), cochez la case "Non NULL" et validez par OK.
tCliquez de nouveau sur "Ajouter".
tSaisissez le "Nom" de la colonne (libelle), le "Type de données" (character varying)
et validez par "OK".
tAllez maintenant dans l’onglet "Contraintes", choisissez "Clé primaire" dans le
menu déroulant et cliquez sur le bouton "Ajouter".
tSaisissez le "Nom" de la clé primaire (pk_rayon) 7, dans l’onglet "Colonnes" choisis-
sez "idrayon" dans le menu déroulant et cliquez sur le bouton "Ajouter".
tValidez l’ajout de cette clé en cliquant sur OK.
tValidez l’ajout de cette table en cliquant à nouveau sur OK.
tDépliez l’arborescence de la table "rayon", de ses "Colonnes" et de ses "Contraintes",
vous devriez avoir l’affichage suivant :
Séquence 1
Présentation de SQL
Page 18
8 2943 TG PA 00
tCliquez de nouveau sur "Ajouter".
tSaisissez le "Nom" de la colonne (prix), le "Type de données" (numeric), la
"Longueur" (6), "Précision" (2) et validez par OK.
tCliquez de nouveau sur "Ajouter".
tSaisissez le "Nom" de la colonne (packaging), le "Type de données" (character
varying) et validez par OK.
tCliquez de nouveau sur "Ajouter".
tSaisissez le "Nom" de la colonne (unitemesure), le "Type de données" (character
varying), et validez par OK.
tCliquez de nouveau sur "Ajouter".
tSaisissez le "Nom" de la colonne (quantite), le "Type de données" (numeric), la
"Longueur" (8), "Précision" (3) et validez par OK.
tCliquez de nouveau sur "Ajouter".
tSaisissez le "Nom" de la colonne (bio), le "Type de données" (boolean) et validez
par OK.
Séquence 1
Présentation de SQL
Page 19
8. Respect de la cardinalité minimale "1" entre "Article" et "Rayon" de notre schéma conceptuel.
8 2943 TG PA 00
tSaisissez le "Nom" de la clé étrangère (fk_rayon) 9, sélectionnez "rayon" dans le
menu déroulant "Références".
tDans l’onglet "Colonnes" choisissez "idrayon" dans le menu déroulant "Colonne
locale" et "idrayon" dans le menu déroulant "Référence vers". Cliquez sur le bou-
ton "Ajouter".
tValidez l’ajout de cette clé en cliquant sur OK.
tValidez l’ajout de cette table en cliquant à nouveau sur OK.
Exercice 1
En vous appuyant sur les schémas de la page 14, le schéma relationnel de la page 16,
le dictionnaire des données et les manipulations des pages précédentes, terminez la
création de la base de données à l’aide de pgAdmin.
8 2943 TG PA 00
tL’assistant se lance, validez le message de bienvenue en cliquant sur "Next".
Choisissez ensuite le type de connexion désirée. Ici, il faut, bien évidemment,
prendre "PostgreSQL". Cliquez ensuite sur "Next" pour passer à l’écran suivant :
Séquence 1
tSaisissez ensuite les informations de connexion comme ci-dessous et validez avec Présentation de SQL
"Next":
Page 21
8 2943 TG PA 00
tNommez la connexion "connmagasin" et cochez les cases comme ci-dessous :
Zone de
Tables de requêtes
la base de graphique
données
Détails et
précisions
Zone SQL
Ligne de
statut
8 2943 TG PA 00
Séquence 2
Le langage d’interrogation
des données : SELECT
Cette séquence aborde la partie la plus utilisée de SQL : l’interrogation.
C’est cette partie qui permet d’extraire les informations que nous recher-
chons. Contrairement aux idées reçues, c’est loin d’être la partie la plus
facile, au contraire ! La véritable difficulté ne réside pas dans l’utilisation
du langage à proprement dit, mais bien dans sa mise en œuvre.
X Prérequis
Avoir compris le sens des manipulations effectuées à la séquence 1.
Séquence 2
X Contenu
Le langage
1. Le choix des colonnes ......................................................................... 24 d'interrogation
des données (LID)
2. Les tables concernées ......................................................................... 28
3. Les conditions simples ........................................................................ 30 Page 23
4. Les calculs ............................................................................................ 36
5. Les jointures ........................................................................................ 41
6. Les tris ................................................................................................. 49
7. Les requêtes imbriquées .................................................................... 51
8. Les regroupements ............................................................................. 56
9. Les conditions sur regroupements .................................................... 58
10. La soustraction ................................................................................. 59
11. La division ......................................................................................... 62
12. Les opérations entre requêtes ......................................................... 63
...........................................................................................................
Synthèse 67
8 2943 TG PA 00
1. Le choix des colonnes
Le résultat d’une requête d’interrogation est une nouvelle table. Ce qui veut dire que
c’est à vous, concepteur de la requête, de prévoir quelle(s) colonne(s) vous voulez voir
affichée(s).
tPar exemple, on souhaite envoyer un email à tous nos fournisseurs. Pour cela, nous
allons avoir besoin de récupérer leurs noms et leurs emails respectifs.
Dans la zone SQL, vous pouvez voir que, lorsqu’il y a plusieurs champs à afficher, on
sépare leurs noms par une virgule :
Prenons le cas où 2 attributs portent le même nom, dans des tables distinctes (ici on sou-
haite obtenir la liste des articles avec le rayon où ils sont placés) :
Sans préfixe
Avec préfixe
(attention, cette requête provoque une erreur 10)
SELECT article.libelle,
SELECT libelle, libelle rayon.libelle
FROM article, rayon FROM article, rayon
WHERE … WHERE …
Deux attributs portant le même nom doivent être préfixés par le nom de la table d’origine
pour éviter toute ambigüité quant à leurs tables d’appartenance.
10. Le moteur d'exéction SQL ne sait pas où aller chercher les champs "libelle" avec exactitude.
8 2943 TG PA 00
Le caractère * ("étoile")
L’étoile est un caractère qui désigne "tout".
tPar exemple, on souhaite afficher l’intégralité de la table "article". On pourrait
cocher toutes les cases de la table, mais, à la place, cochez uniquement la case "*":
…
Dans la zone SQL, on peut voir qu’utilisé avec l’instruction SELECT, cela correspond à
"toutes les colonnes de la table":
SELECT *
FROM article
Lorsque le moteur d’exécution SQL construit un résultat, par défaut, il prend toutes les
lignes qui satisfont à la requête demandée, y compris les lignes en double.
Ce qui nous donne en SQL, sans DISTINCT :
SELECT idFournisseur
FROM lot
tPour utiliser la suppression de doublons, il suffit de cliquer avec le bouton droit dans
la zone de requête (près d’une table), de choisir "DISTINCT" comme "SELECT Type"
(type d’interrogation) et de valider avec OK :
8 2943 TG PA 00
Séquence 2
Le mot clé DISTINCT, utilisé avec l’instruction SELECT, a pour effet de ne pas afficher de
Le langage doublons (lignes en double) :
d'interrogation
des données (LID) SELECT DISTINCT idFournisseur
FROM lot
Page 26
Dans la zone SQL, on peut voir que la requête est tout à fait semblable aux précédentes :
8 2943 TG PA 00
tNous allons à présent utiliser des alias. Pour cela, dans la zone "Détails et préci-
sions", saisissez dans la colonne "Alias" les correspondances suivantes (les alias
devront être entourés de guillemets). Exécutez-la, et regardez de plus près les inti-
tulés de colonnes :
Séquence 2
Le langage
d'interrogation
des données (LID)
Dans la zone SQL, on peut voir que la clause "AS" a été ajoutée après chaque champ
pour spécifier un alias :
Page 27
SELECT raisonSociale AS "Nom",
adresseRue AS "Adresse",
adresseCP AS "Code Postal",
adresseVille AS "Ville"
FROM fournisseur
Les guillemets qui entourent l’alias sont facultatifs mais fortement recommandés pour
plusieurs raisons :
s ils évitent tout risque de conflit si l’alias est un mot réservé (par le SQL ou le SGBDR) ;
s ils préviennent d’un éventuel conflit en cas d’ajout futur de mot-clé ;
s ils permettent de conserver la casse exacte de l’alias (majuscules/minuscules) ;
s ils permettent d’avoir plusieurs mots séparés par des espaces.
8 2943 TG PA 00
2. Les tables concernées
Comme vous avez pu le constater dans les précédents exemples, en plus de l’instruction
SELECT, il y a l’instruction "FROM". Celle-ci permet de définir les tables dont nous avons
besoin pour construire le résultat. Lorsqu’il y a plusieurs tables, on sépare leurs noms par
une virgule.
tPar exemple, si on a besoin de connaître la liste des fournisseurs de "kiwis", on aura
obligatoirement besoin des tables "fournisseur", "lot" et "article". Glissez-déposez
ces trois tables :
Le langage ...
d'interrogation FROM fournisseur, lot, article
des données (LID)
...
Page 28
Le mot clé "AS"
Comme pour les alias de colonnes, on peut créer des alias de tables, c’est-à-dire un nom
de substitution ou un pseudonyme, pour nous permettre encore une fois d’améliorer la
lisibilité d’une requête.
tReprenons l’exemple d’utilisation du préfixage avec le nom de table :
Attention, dès lors que l’on a créé un alias, il devient le nouveau nom de la table et on ne
peut plus utiliser le nom d’origine pour s’y référer (contrairement aux alias de colonnes).
8 2943 TG PA 00
tPour créer un alias de table, le mot clé "AS" n’est en réalité pas obligatoire et,
comme pour les alias de champs, un espace suffit (cela rend toutefois la requête un
peu moins lisible) :
SELECT a.libelle "Article", r.libelle "Rayon"
FROM article a, rayon r
WHERE ...
Pour créer un alias de table dans FlySpeed SQL Query, il vous suffit de cliquer avec le bou-
ton droit sur la table où l’on souhaite insérer un alias et de choisir dans le menu qui appa-
raît "Properties…". Dans la fenêtre qui apparaît, il suffit ensuite de saisir l’alias désiré :
Séquence 2
Le langage
d'interrogation
des données (LID)
Exercice 1 Page 29
8 2943 TG PA 00
3. Les conditions simples
Nous allons maintenant voir comment restreindre une requête à un ensemble bien défini
en effectuant une sélection dite "conditionnelle" des enregistrements. Pour cela, nous
avons besoin de l’instruction "WHERE". Cette instruction va nous permettre de définir
une ou plusieurs conditions que les enregistrements devront vérifier pour pouvoir faire
partie des enregistrements concernés par notre requête.
Les opérateurs et les mots-clés utilisés dans les conditions sont également appelés "prédi-
cats"
tOn souhaite à présent obtenir la liste de tous les articles à "moins d’1 euro". Il nous
suffit donc de sélectionner la table "article" et les champs désirés. Ensuite, il ne nous
reste plus qu’à insérer notre condition "< 1" dans la colonne "Criteria" sur la ligne
correspondant au champ "prix" (puisque, ici, ce qui nous intéresse, c’est de retenir
les articles, dont le prix est inférieur à 1 euro) :
Séquence 2
Le langage
d'interrogation
des données (LID)
Page 30
En examinant la zone SQL, on peut voir que notre condition a été reportée après l’ins-
truction "WHERE":
8 2943 TG PA 00
Les prédicats de comparaison
< inférieur à
> supérieur à
<= inférieur ou égal à ≤
>= supérieur ou égal à ≥
= égal à
<> ou != différent de ≠
tExemple : on souhaite obtenir la liste de tous les articles à "1 euro". En graphique,
il nous suffit de modifier le contenu de la colonne "Criteria".
8 2943 TG PA 00
Le prédicat d’intervalle "BETWEEN"
Le prédicat "BETWEEN" nous permet de définir des intervalles d’une manière plus effi-
cace et plus intuitive qu’avec les prédicats de comparaison.
tSi on reprend l’exemple précédent, on peut donc écrire la condition de cette
manière :
Il faut toujours bien lire ce qui est demandé. Ici, par exemple, on souhaite obtenir unique-
ment les adresses électroniques et rien d’autre. C’est pour cette raison que seul le champ
"email" est coché. Le champ "raisonsociale" est bien entendu présent car on en a besoin
pour y appliquer une condition, mais ce dernier n’ayant pas à apparaître dans le résultat,
il ne devra pas être coché.
8 2943 TG PA 00
Ce qui nous donne en SQL :
SELECT email
FROM fournisseur
WHERE raisonSociale BETWEEN 'A' AND 'M'
Comme pour la requête précédente, ici, seul le champ "idLot" est demandé. Cela doit donc
être le seul champ coché.
SELECT idLot
FROM lot
WHERE dateLivraison BETWEEN '2010/03/15'
AND '2010/03/31'
Séquence 2
Par défaut, le format de date des SGBDR est "année/mois/jour". C’est pourquoi il est
souvent nécessaire, pour que la requête fonctionne, de renseigner la date en respectant ce Le langage
d'interrogation
format.
des données (LID)
SELECT raisonSociale
FROM fournisseur
WHERE adresseVille = 'Toulon'
OR adresseVille = 'Ollioules'
OR adresseVille = 'La Seyne sur Mer'
OR adresseVille = 'Sanary sur Mer'
8 2943 TG PA 00
– Avec le prédicat de liste "IN":
SELECT raisonSociale
FROM fournisseur
WHERE adresseVille IN ('Toulon','Ollioules',
'La Seyne sur Mer','Sanary sur Mer')
Le prédicat "IN" permet de sélectionner les enregistrements qui contiennent l’une des valeurs
de la liste. En associant l’opérateur logique "NOT", on peut faire l’inverse en sélectionnant
les enregistrements qui ne contiennent aucune des valeurs présentes dans la liste.
tPar exemple, on veut obtenir le nom des fournisseurs qui ne sont ni sur "Toulon",
ni sur "Ollioules", ni sur "La Seyne sur Mer":
Séquence 2
SELECT raisonSociale
FROM fournisseur
WHERE adresseCP LIKE '83%'
8 2943 TG PA 00
tLe blanc souligné "_" (également appelé "tiret du bas" ou "underscore") remplace
n’importe quel caractère (1 seul par "_") :
– même requête que précédemment. On souhaite obtenir la liste des fournis-
seurs présents dans le Var (département 83) :
SELECT raisonSociale
FROM fournisseur
WHERE adresseCP LIKE '83_ _ _'
L’inconvénient du blanc souligné est qu’il faut connaître avec exactitude le nombre de
caractères sur lesquels on veut un "joker".
tPar exemple, on veut obtenir la liste des fournisseurs (raisons sociales et numéros de Le langage
téléphone) pour qui on ne dispose pas de leurs emails : d'interrogation
des données (LID)
Page 35
On ne peut pas écrire "= NULL" parce que NULL n’est pas "égal à" NULL (la valeur NULL
représente une valeur inconnue et il est impossible de dire si deux valeurs inconnues sont
égales).
En utilisant l’opérateur "NOT", on peut faire l’inverse, c’est-à-dire ne récupérer que les
enregistrements où la valeur de la colonne n’est pas nulle.
8 2943 TG PA 00
tPar exemple, on veut obtenir la liste des fournisseurs (raisons sociales et numéros de
téléphone) qui nous ont fourni leurs emails :
Exercice 2
Réaliser les requêtes permettant d’obtenir les informations ci-dessous. Comme
pour les exercices précédents, essayez, dans la mesure du possible, de réaliser ces
requêtes directement en SQL. Si vous n’y arrivez pas, essayez ensuite en graphique :
tla liste des fournisseurs dont la distance est de moins de 100 km ;
tla liste des fournisseurs qui se situent à plus de 10 km mais à moins de 100 km ;
tla liste des fournisseurs ayant une adresse email chez "orange.fr";
Séquence 2
tla liste des lots fabriqués avant le 23 mars 2010 et qui ont été livrés entre le
Le langage 24 et le 26 mars ;
d'interrogation
tla liste des articles du rayon n° 12 dont le packaging ou l’unité de mesure n’a
des données (LID)
pas été renseigné ;
Page 36 tla liste des articles dont le packaging est "Par 3", "Par 6" ou "Par 12".
4. Les calculs
8 2943 TG PA 00
Ce qui nous donne, en SQL :
SELECT idArticle, libelle, prix + 1
FROM article
Depuis quelques pages, nous savons utiliser les "alias" de colonnes. Prenons l’habitude
de les utiliser dès que l’occasion se présente. Ici, par exemple, c’est une bonne occasion
en effet, dès lors que l’on utilise une opération, il faudra utiliser un alias de colonnes :
Séquence 2
Le langage
d'interrogation
Ce qui nous donne, en SQL : des données (LID)
SELECT idArticle, libelle, prix * 1.20 AS "Prix livré"
FROM article Page 37
Les priorités opératoires sont respectées dans les instructions SQL permettant ainsi de
limiter l’usage des parenthèses. Bien sûr, comme en mathématiques, on peut tout de
même combiner les opérations à l’aide des parenthèses :
Avec uniquement les calculs simples, les capacités de SQL sont vite limitées. C’est pour-
quoi des fonctions permettant à SQL d’effectuer des opérations complexes ont été
créées.
8 2943 TG PA 00
La fonction "COUNT"
La fonction "COUNT" vous permet d’obtenir le nombre de lignes que comporte la table
résultante de votre requête.
tPar exemple, on veut obtenir le nombre d’articles présents dans notre base.
Graphiquement nous allons à présent utiliser la colonne "Aggregate" qui va nous
permettre d’utiliser les fonctions SQL :
Page 38
tOn souhaite obtenir le nombre de nos fournisseurs qui possèdent un email :
SELECT COUNT(email)
AS "Nb de fournisseurs avec email"
FROM fournisseur
8 2943 TG PA 00
tOn souhaite obtenir le nombre de fournisseurs qui nous ont déjà livrés. Il faut, pour
cela, choisir la fonction "COUNT DISTINCT":
Séquence 2
Le langage
Ce qui nous donne, en SQL : d'interrogation
des données (LID)
SELECT MAX(distanceKm) AS "Distance max fourn."
FROM fournisseur Page 39
tMaintenant, on veut obtenir le prix de l’article le moins cher du rayon n° 1 :
8 2943 TG PA 00
Les fonctions "SUM" et "AVG"
Les fonctions "SUM" et "AVG" retournent respectivement la somme et la moyenne de
la colonne passée à la fonction.
tPar exemple, on veut obtenir le chiffre d’affaires réalisé le 1er avril 2010 :
Exercice 3
Réaliser les requêtes permettant d’obtenir les informations ci-dessous. Comme
pour les exercices précédents, essayez, dans la mesure du possible, de réaliser ces
requêtes directement en SQL. Si vous n’y arrivez pas, essayez ensuite en graphique :
tla liste des articles ("idArticle", "libelle", "prix" que l’on renomme en "prix
en €") avec en plus les prix en livres sterling (on prend comme taux de change :
1 £ = 1,21 €) ;
tle nombre de marques référencées dans notre base de données ;
tle chiffre d’affaires pour le mois d’avril 2010 ;
tla date de la dernière livraison reçue ;
tla distance moyenne des fournisseurs du Var (département 83) ;
tle prix HT (taux de TVA de 19,6 %) de l’article le plus cher ;
tle prix moyen au kilo des articles dont l’unité de mesure est le gramme.
8 2943 TG PA 00
5. Les jointures
La jointure est le mécanisme le plus puissant du langage SQL. Elle permet de combiner
les données de plusieurs tables en les liant logiquement suivant les relations qui existent
entre elles (clés primaires et / ou étrangères).
Comme nous l’avons vu dans la séquence 1, le SQL repose sur le concept mathématique
d’algèbre relationnelle reposant lui-même sur la théorie des ensembles.
Il faut savoir que la base de la jointure est le "produit cartésien". Pour faire simple, le
résultat d’un produit cartésien entre 2 tables est l’ensemble formé par tous les couples
possibles entre ces 2 tables. Ce qui veut dire que si, dans la première table, il y a 5 enre-
gistrements et, dans la seconde 2, on obtiendra une table résultante de 10 enregistre-
ments :
Séquence 2
Le langage
d'interrogation
des données (LID)
Page 41
Cette jointure, également appelée "jointure croisée", est effectuée à chaque fois que
l’on indique plusieurs tables dans l’instruction "FROM" sans indiquer de condition dans
le "WHERE".
tPar exemple, on veut obtenir la liste des articles et des rayons :
Résultat :
Article Rayon
Camembert Apéritifs
Merguez Apéritifs
… …
Camembert Boissons
Merguez Boissons
… …
8 2943 TG PA 00
Dans notre cas, le résultat comporte de nombreuses incohérences car le modèle qui nous
a permis de créer la base de données possède la règle de gestion suivante : "Un article
est placé dans un et un seul rayon" (cardinalité 1,1 dans notre schéma conceptuel des
données ou multiplicité 1 dans notre diagramme de classes UML ).
Dans la majeure partie des cas, pour obtenir un résultat cohérent, il faudra spécifier
une condition de jointure. Dans une base de données créée à l’aide d’un modèle rela-
tionnel la condition de jointure sera tout simplement la représentation du respect des
règles de gestion : "La clé étrangère k de la table t fait référence à la clé primaire p de
la table x".
La jointure "classique"
La jointure "classique" est une jointure basée sur l’équivalence entre 2 champs. Elle
opère en associant l’enregistrement d’une première table à l’enregistrement d’une
seconde table, uniquement si la valeur d’un champ de la première table est égale à la
valeur du champ correspondant de la seconde table.
Séquence 2
Le langage
d'interrogation
des données (LID)
Page 42
Reprenons l’exemple précédent : on souhaite obtenir la liste des articles et des rayons. Ce
qui veut dire que si on veut obtenir la liste des articles avec le rayon où ils sont placés, il
faut que l’on associe un article à un rayon.
8 2943 TG PA 00
D’après notre schéma relationnel, on dispose de la clé étrangère "idRayon" de la table
article qui fait référence à la clé primaire "idRayon" de la table "rayon", ce qui signifie
rappelons-le, qu’un article est placé dans un et un seul rayon (conséquence de la cardi-
nalité 1,1 de notre schéma conceptuel des données).
Tout ce qui nous reste à faire, c’est donc de préciser au moteur d’interprétation SQL
qu’au lieu de faire un produit cartésien, on ne veut associer que les enregistrements de
la table article et de la table rayon où la valeur de la clé étrangère "idrayon" de "article"
correspond à la valeur de la clé primaire de la table "rayon".
tVous allez donc rajouter "WHERE a.idRayon = r.idRayon" à la requête précédente
pour donner la requête suivante :
SELECT a.libelle AS "Article", r.libelle AS "Rayon"
FROM article AS a, rayon AS r
WHERE a.idRayon = r.idRayon
Résultat :
Article Rayon
Galettes au millet et champignons Apéritifs
Galettes au riz complet Apéritifs
Pochon de légumes bio préparés Apéritifs
Rillettes de truite bio Apéritifs
Chips salées Boissons
Pur jus de citron bio Boissons Séquence 2
Attention, dans notre exemple, la clé primaire et la clé étrangère portent le même nom Page 43
mais ce n’est absolument pas obligatoire !
Si la clé étrangère idRayon de la table article se nommait en réalité "placementRayon",
on aurait la requête suivante, qui fonctionnerait exactement de la même façon et qui
fournirait exactement le même résultat :
8 2943 TG PA 00
Nous allons également voir que la relecture d’une requête avec JOIN apparaît beaucoup
plus simple à nos yeux d’humains.
Pour cela, vous allez cliquer sur le champ "idrayon" de la table "article" et, tout en res-
tant "appuyé", vous allez venir sur le champ "idrayon" de la table "rayon". Cela va avoir
pour effet d’associer les deux champs et de faire apparaître un lien entre les deux tables :
Séquence 2
Le langage
d'interrogation
des données (LID)
Page 44
tAvec l’opérateur “JOIN”, la requête va donc pouvoir s’écrire ainsi :
SELECT a.libelle AS "Article", r.libelle AS "Rayon"
FROM article AS a INNER JOIN rayon AS r
ON a.idRayon = r.idRayon
La clause "INNER" est facultative et est utilisée par défaut dès lors que l’on utilise l’opé-
rateur "JOIN". L’explication est que cette clause permet d’indiquer au moteur d’interpré-
tation SQL que la jointure est de type "interne", qui est le comportement par défaut de
l’opérateur "JOIN".
Pour plus de facilité, nous continuerons d’écrire "JOIN" sans "INNER" même si FlySpeed
SQL Query vous la propose à chaque fois.
Pour bien vous en convaincre, supprimez la clause "INNER" dans la zone SQL et réexé-
cutez-la.
Dans notre base de données, la clé étrangère idrayon de la table "article" fait référence
à la clé primaire idrayon. Ce cas, très fréquent, où l’on souhaite faire une jointure à
l’aide de champs portant le même nom, rend la manœuvre encore plus simple. Il suffit
de donner le nom du champ "commun":
SELECT a.libelle AS "Article", r.libelle AS "Rayon"
FROM article AS a JOIN rayon AS r USING (idRayon)
8 2943 TG PA 00
Dans FlySpeed SQL Query, cette requête va provoquer une erreur car le logiciel ne connaît
pas la clause "USING". La requête va toutefois bien fonctionner car PostgreSQL connaît
la clause "USING" et sait l’utiliser. Il y aura d’ailleurs le même type d’erreur pour la
requête ci-après…
On peut même faire encore plus simple en utilisant une jointure "naturelle", c’est-à-dire
que l’on va laisser le moteur d’exécution SQL joindre les champs ayant les mêmes noms.
tOn souhaite, par exemple, afficher le libellé d’article avec la marque associée :
SELECT libelle AS "Article", nom AS "Marque"
FROM article NATURAL JOIN marque
Attention, la jointure "naturelle" est un cas particulier de jointure. Lors d’une jointure
"naturelle", le moteur d’exécution SQL effectue automatiquement la comparaison des
champs ayant le même nom.
C’est pourquoi elle ne fonctionnerait pas dans le cas "article/rayon" car les tables portent
un champ de même nom (libelle), et ça ne fonctionnerait pas non plus dans le cas
"article/listeCourses" (à cause de "quantite"). Cet homonyme va contraindre le moteur
d’exécution à joindre les deux champs :
s soit les contenus sont différents, et aucun résultat n’est retourné ;
s soit il y a des contenus identiques, et le résultat retourné ne correspond pas à ce
que l’on voulait.
L’analyse à réaliser avant de pouvoir utiliser la jointure naturelle fait que ce type de
Séquence 2
jointure est très peu utilisé. Certains vont même, à juste titre, jusqu’à déconseiller son
usage car si l’analyse avant utilisation est mal faite, le risque d’erreur est important. Le langage
Je vous la donne tout de même, car le but, ici, et de vous faire connaître tout le SQL, ce d'interrogation
qui inclut également, selon moi, les instructions dites "dangereuses". des données (LID)
L’utilisation de "JOIN" telle qu’on vient de le voir, supprime toutes les lignes qui ne sont Page 45
pas équivalentes dans les deux tables utilisées. Nous allons maintenant voir comment
faire pour conserver ou non les lignes sans lignes équivalentes en distinguant les tables
qui se situent à gauche de "JOIN" des tables qui se situent à droite.
tOn souhaite, par exemple, afficher la liste des fournisseurs ainsi que la liste de leurs
livraisons. On va donc conserver toutes les lignes de la table de gauche. Pour cela,
cliquez avec le bouton droit sur le lien entre fournisseur et lot (que vous aurez créé
au préalable) et choisissez "Select all rows from fournisseur":
8 2943 TG PA 00
Visuellement, cela va modifier le lien :
Séquence 2
Le langage
d'interrogation Et, dans la zone SQL, on peut constater que la clause “LEFT” est venue se position-
des données (LID) ner avant le “JOIN":
SELECT raisonSociale, idLot, idArticle
Page 46
FROM fournisseur LEFT JOIN lot ON
(fournisseur.idFournisseur = lot.idFournisseur)
8 2943 TG PA 00
La jointure "DROITE" avec "RIGHT JOIN"
La jointure "droite" s’effectue avec "RIGHT" et conserve les lignes sans lignes équiva-
lentes dans la table de droite, mais supprime les lignes sans lignes équivalentes dans la
table de gauche.
tOn souhaite à présent afficher la liste des marques ainsi que les articles correspon-
dants en magasin. On va donc procéder de la même manière que pour la jointure
gauche sauf que l’on va sélectionner tous les champs de la table de droite (ici,
"marque") en choisissant l’option "Select all rows from marque":
Séquence 2
Le langage
d'interrogation
des données (LID)
Page 47
Dans la zone SQL, on peut voir que la clause "RIGHT" est venue se placer avant
l’opérateur “JOIN” afin de réaliser une jointure "droite" :
SELECT nom, libelle
FROM article RIGHT JOIN marque ON
(article.idMarque = marque.idMarque)
8 2943 TG PA 00
Cette jointure "droite" nous permet d’avoir la liste des marques qui n’ont aucune corres-
pondance dans la table "article" en conservant lors de la jointure, les lignes de marque
(table de droite) qui n’ont pas de lignes équivalentes dans la table "article".
tEn utilisant l’instruction "NATURAL", on peut également écrire notre requête de
cette manière :
SELECT nom, libelle
FROM article NATURAL RIGHT JOIN marque
Une jointure "naturelle" peut également être droite ("NATURAL RIGHT JOIN") ou
gauche ("NATURAL LEFT JOIN").
Exercice 4
Réaliser les requêtes permettant d’obtenir les informations ci-dessous. Comme pour
les exercices précédents, essayez dans la mesure du possible, de réaliser ces requêtes
directement en SQL. Si vous n’y arrivez pas, essayez ensuite en graphique :
tla liste des articles (références et libellés) qui ont été achetés ;
tla liste des articles (références et libellés) qui ont été achetés avec la date à
laquelle ils ont été achetés ;
Séquence 2 tla liste des articles (références, libellés et prix) avec le nom de la marque de l’ar-
ticle (renommé en "Marque") et le libellé du rayon d’appartenance (renommé
Le langage en "Rayon") ;
d'interrogation
des données (LID) tla liste des articles (Références, libellés et prix), qui ont été achetés, avec le nom
de la marque de l’article et le libellé du rayon d’appartenance ainsi que la date
Page 48 à laquelle ils ont été achetés ;
treprenez la requête précédente et utilisez des alias de champs pour chaque
champ utilisé :
– idArticle Î "Référence"; – nom Î "Marque";
– libelle Î "Produit"; – libelle Î "Rayon";
– prix Î "P.U"; – dateAchat Î "Date".
tla liste des fournisseurs qui n’ont pas encore effectué de livraison ;
tla liste des rayons qui n’ont aucun article attribué.
8 2943 TG PA 00
6. Les tris
SQL nous offre la possibilité de trier les résultats d’une requête grâce à l’instruction
"ORDER BY". Par défaut, l’instruction SELECT nous retourne les enregistrements dans
l’ordre dans lequel ils apparaîssent dans la table.
" ORDER BY " nous permet d’organiser les enregistrements en s’appuyant sur n’importe
quel type de champ :
s Ordre alphabétique : si le champ est basé sur des chaînes de caractères ;
s Ordre chronologique : si le champ est basé sur des dates ;
s Ordre incrémental : si le champ est basé sur des nombres ;
s Ordre de vérité : si le champ est basé sur des valeurs booléennes.
Par exemple, on souhaite obtenir la liste des fournisseurs triés par ordre alphabétique.
tCela signifie que l’on souhaite tous les champs et tous les enregistrements de la
table "fournisseur", mais cela veut également dire que l’on souhaite effectuer un
tri "croissant" sur le champ raisonSociale. On va donc se servir des colonnes "Sort
Type" (Type de tri) et "Sort Order" (Priorité de tri). Dans la colonne "Sort Type",
choisissez "Ascending" (croissant) :
Séquence 2
La priorité de tri se positionne automatiquement à 1. Nous verrons plus loin à quoi
cela correspond. Le langage
d'interrogation
Dans la zone SQL, on peut voir que l’instruction “ORDER BY” est venue s’ajouter, des données (LID)
accompagnée du champ sur lequel porte le tri “raisonSociale":
SELECT * Page 49
FROM fournisseur
ORDER BY raisonSociale
Le tri par ordre croissant se fait grâce à la clause "ASC" qui est normalement positionnée
après le champ à trier. Le type de tri par défaut, activé par l’instruction "ORDER BY", est
"ASC", ce qui fait que cette clause est facultative. C’est pourquoi FlySpeed SQL Query ne
vous le propose pas. Modifiez la requête précédente en ajoutant "ASC" et réexécutez-la :
SELECT *
FROM fournisseur
ORDER BY raisonSociale ASC
" ASC " permet de préciser que l’on souhaite effectuer un tri "croissant":
s si c’est un champ de type "chaînes de caractères", l’affichage se fera de "A" à "Z";
s si c’est un champ de type "date", l’affichage commencera par les dates les plus
anciennes pour se terminer avec les plus récentes ;
s si c’est un champ de type "numérique", l’affichage commencera par les nombres
les plus "petits" (−'), pour se terminer avec les plus grands (+') ;
s si c’est un champ de type "booléen", l’affichage commencera par les valeurs
"fausses" (false en anglais) pour se terminer par les valeurs "vraies" (true).
On souhaite à présent obtenir la liste des lots, mais on souhaite également que l’affi-
chage commence par les livraisons les plus récentes.
8 2943 TG PA 00
tCela signifie que l’on souhaite effectuer un tri "décroissant" (date les plus récentes
en premier) :
Dans la zone SQL, on peut voir que la clause "DESC" a été ajoutée après le champ
à trier :
SELECT *
FROM lot
ORDER BY dateLivraison DESC
" DESC " nous permet de préciser que l’on souhaite effectuer un tri "décroissant", ce qui
revient à faire l’inverse de "ASC".
Le langage
d'interrogation
des données (LID)
Page 50 Dans la zone SQL, on peut voir que le tri porte d’abord sur "idRayon" (Sort Order = 1)
et ensuite sur "prix" (Sort Order = 2) :
SELECT *
FROM article
ORDER BY idRayon, prix
L’ordre de tri sera bien entendu croissant ("ASC"), rappelons-le puisque c’est l’action
par défaut de l’instruction "ORDER BY". La requête précédente peut donc s’écrire de la
manière suivante :
SELECT *
FROM article
ORDER BY idRayon ASC, prix ASC
8 2943 TG PA 00
Dans la zone SQL, on peut voir que le tri porte d’abord sur "distanceKm" et que
ce champ sera trié dans l’ordre décroissant ("DESC") et ensuite que le tri porte sur
"prix" et que ce champ sera trié par ordre croissant (par défaut) :
SELECT *
FROM fournisseur
ORDER BY distanceKm DESC, raisonSociale
Exercice 5
Réaliser les requêtes permettant d’obtenir les informations ci-dessous. Comme pour
les exercices précédents, essayez dans la mesure du possible de réaliser ces requêtes
directement en SQL. Si vous n’y arrivez pas, essayez ensuite en graphique :
tla liste des marques par ordre alphabétique ;
tla liste des articles en affichant les articles "bio" en premier ;
tla liste des marques avec les articles correspondants. Les noms de marques
doivent être triés par ordre alphabétique inverse et les libellés d’articles par
ordre alphabétique ;
Séquence 2
tla liste des lots avec le nom des fournisseurs et le libellé des articles en com-
mençant par la livraison la plus ancienne. Les articles seront triés par ordre Le langage
alphabétique. d'interrogation
des données (LID)
Page 51
8 2943 TG PA 00
– Pour cela, il faut commencer par faire la requête qui va nous permettre d’affi-
cher tous les articles "bio" sans restriction de prix :
– Nous allons ensuite appliquer une restriction sur le prix, mais, au lieu de
rajouter une condition, nous allons cliquer avec le bouton droit dans la cellule
"Criteria", choisir "Insert Sub-Query" (Insérer une sous-requête) et valider
avec la touche "Entrée":
Séquence 2
Le langage
d'interrogation
des données (LID)
– Par défaut, c’est le prédicat "IN" suivi de la sous-requête qui est proposé. Nous
allons donc remplacer "IN" par "<=" et ensuite appuyer sur le bouton aux
Page 52
3 points pour modifier la sous-requête. Après avoir appuyé, on peut remar-
quer que l’on est passé sur un nouvel onglet :
– La sous-requête est avant tout une requête, il faut donc agir comme pour une
requête "standard". Ici, on souhaite que cette requête retourne le prix moyen
des articles "bio":
– Dans la zone SQL, on peut voir que l’on a bien une première requête qui
retourne toutes les informations ("SELECT *") concernant les articles ("FROM
article") "bio" ("WHERE bio = TRUE") dont le prix est inférieur ou égal ("AND
prix <= ") au prix moyen ("SELECT AVG(prix)") d’un article ("FROM article")
"bio" ("WHERE bio = TRUE") :
8 2943 TG PA 00
SELECT *
FROM article
WHERE bio = TRUE
AND prix <= ( SELECT AVG(prix)11
FROM article
WHERE bio = TRUE )
11
– Ensuite, comme pour la requête précédente, nous allons ajouter une restric-
tion (champ "Criteria") sous la forme d’une sous-requête portant ici sur le
champ "idRayon":
Séquence 2
Le langage
d'interrogation
des données (LID)
Page 53
– Nous allons garder le prédicat "IN" et cliquer directement sur le bouton aux
3 points pour modifier la sous-requête :
Attention, ici, c’est bien un "OR" qu’il faut utiliser car si on utilisait un "AND", cela
signifierait que l’on veut l’article dont le libellé est à la fois "Maïs tendre" et "Café
moulu", ce qui n’est pas possible puisqu’un article ne possède qu’un libellé.
11. Bien que nous ayons pris l'habitude de renommer tous les calculs, ici, ce n'est pas nécessaire :
l'intitulé n'est pas utile à la réquête principale et n'apparaît pas dans le résultat final.
8 2943 TG PA 00
– Pour éviter une erreur liée à la difficulté "AND"/"OR", nous allons plutôt
effectuer la restriction avec le prédicat "IN":
– Si notre requête s’arrête là, nous aurons également dans le résultat les don-
nées qui nous ont servi dans notre sous-requête :
– Il faut donc les éliminer en ajoutant à notre requête principale une restriction
sur le champ "libelle" (d’article ici) qui indique que l’on ne veut ni l’article
"Maïs tendre", ni l’article "Café moulu" ("NOT IN ('Maïs tendre', 'Café
Séquence 2
moulu')") :
Le langage
d'interrogation
des données (LID)
Page 54
– Dans la zone SQL, on peut voir que l’on a bien une première requête qui
retourne toutes les informations ("SELECT *") concernant les articles ("FROM
article") dont l’identificateur de rayon (c’est-à-dire le rayon où se trouve
l’article) se trouve dans la liste ("WHERE idRayon IN") des identificateurs de
rayons ("SELECT idRayon") des articles ("FROM article") dont le libellé est
lui-même dans la liste ("WHERE libelle IN") suivante : "Maïs tendre" ; "Café
moulu". On souhaite toutefois ne conserver que les articles dont le libellé
n’est pas ("AND libelle NOT IN") dans la liste suivante : "Maïs tendre" ; "Café
moulu".
SELECT *
FROM article
WHERE idRayon IN ( SELECT idRayon
FROM article
WHERE libelle IN ('Maïs tendre',
'Café moulu')
)
AND libelle NOT IN ('Maïs tendre', 'Café moulu')
8 2943 TG PA 00
Expressions de sous-requêtes
On a vu "IN" qui, de par son rôle de prédicat de liste, est lui aussi une expression de sous-
requêtes. Mais il faut savoir qu’il y a également : "ANY 12" (que l’on retrouve également
sous le nom de "SOME 13"), "ALL 14" et "EXISTS" que l’on peut combiner à un prédicat de
comparaison pour évaluer le contenu d’une sous-requête.
"ANY/SOME": est vrai si au moins une des lignes retournées par la sous-requête vérifie
la condition exprimée par le prédicat de comparaison.
tPar exemple, si on cherche les marques qui ont au moins un article en magasin :
SELECT *
FROM marque
WHERE idMarque = ANY ( SELECT idMarque FROM article )
"ALL": Est vrai si toutes les lignes retournées par la sous-requête vérifient la condition
exprimée par le prédicat de comparaison.
tPar exemple, si on cherche les articles qui sont moins chers ou au même prix que
tous les articles déjà vendus :
SELECT *
FROM article
WHERE prix <= ALL ( SELECT prix
FROM article JOIN listeCourses
USING (idArticle)
) Séquence 2
"EXISTS": est vrai s’il existe au moins une ligne retournée par la sous-requête qui vérifie Le langage
d'interrogation
la condition exprimée dans la sous-requête. L’utilisation de "EXISTS" n’a de sens que si la des données (LID)
requête principale et la sous-requête sont liées par un champ.
tPar exemple, si on veut obtenir la liste des rayons qui n’ont aucun article : Page 55
SELECT *
FROM rayon AS r
WHERE NOT EXISTS ( SELECT *
FROM article AS a
WHERE r.idRayon = a.idArticle
)
On retrouve ici la structure de la jointure "classique" que l’on n’utilise plus, et, dans les
exemples précédents, vous avez dû vous rendre compte que vous étiez capable de proposer
une requête sans utiliser "ANY", "ALL" ou "EXISTS" avec une sous-requête munie d’une
fonction de calcul. Bien que peu utilisés, ils le restent toujours, c’est pourquoi il fallait
que vous l’ayez vu au moins une fois pour être capable de comprendre leur utilisation si
un jour vous y étiez confronté.
8 2943 TG PA 00
Exercice 6
Réaliser les requêtes permettant d’obtenir les informations ci-dessous. Comme
pour les exercices précédents, essayez, dans la mesure du possible, de réaliser ces
requêtes directement en SQL. Si vous n’y arrivez pas, essayez ensuite en graphique :
tle ou les articles les moins chers ;
tla liste des lots qui ont été livrés le même jour que le lot "L593078838";
tla liste des rayons qui ont été approvisionnés à la dernière livraison ;
tla liste des rayons qui ont été approvisionnés à l’avant-dernière livraison.
8. Les regroupements
Le regroupement est une opération qui nous permet de spécifier un ou plusieurs champs
qui déterminent l’appartenance à un groupe. En SQL, c’est l’instruction "GROUP BY" qui
effectue des regroupements de toutes les lignes dont la valeur du champ de groupe est
identique.
tPar exemple, nous souhaitons obtenir le nombre d’articles par rayon d’apparte-
nance (pour l’instant, il faut décocher la case "Grouping") :
Séquence 2
Le langage
d'interrogation 15
des données (LID)
15. La présence d'une fonction ne permet pas au moteur d'exécution SQL de réaliser la requête
sans GROUP BY
8 2943 TG PA 00
Avec regroupement : Résultat :
Dès lors que l’on souhaite afficher plusieurs champs dont un est composé d’une fonction
de calcul, il faut obligatoirement effectuer un regroupement en nommant clairement le
ou les champs sur lesquels on souhaite opérer ce regroupement.
8 2943 TG PA 00
Exercice 7
Réaliser les requêtes permettant d’obtenir les informations ci-dessous. Comme
pour les exercices précédents, essayez, dans la mesure du possible, de réaliser ces
requêtes directement en SQL. Si vous n’y arrivez pas, essayez ensuite en graphique :
tLe nombre d’articles par achat ;
tLe nombre d’articles par rayon ;
tLe nombre de lots livrés par fournisseur ;
tLa liste des articles avec le nombre de fois où ils ont été achetés en affichant les
plus "populaires" en premier ;
tLe prix moyen au kilo des articles par rayon.
Attention, il faut veiller à bien distinguer une restriction sur un champ existant dans la
base de données et une restriction sur un champ "créé" localement par la requête (ce qui
est le cas pour les fonctions, comme ici avec "COUNT(*)").
8 2943 TG PA 00
Exercice 8
Réaliser les requêtes permettant d’obtenir les informations suivantes :
tle nombre d’articles par achat avec uniquement les achats concernant moins de
5 articles ;
tle nombre d’articles par rayon avec uniquement les rayons avec 4 articles ;
tle nombre de lots livrés par fournisseur en ne gardant que les fournisseurs qui
ont livré au moins 10 lots ;
tla liste des articles avec le nombre de fois où ils ont été achetés en affichant
les plus "populaires" en premier et en ne conservant que les articles achetés
entre 2 et 5 fois.
10. La soustraction
Cette opération nous permet de comparer 2 tables et de ne retourner que les lignes qui
apparaîssent dans la première table mais pas dans la seconde.
Séquence 2
Le langage
d'interrogation
des données (LID)
Page 59
tOn souhaite obtenir la liste des articles qui n’ont jamais figuré sur une liste de
courses, on peut utiliser "NOT IN" de cette manière :
SELECT idArticle
FROM article
WHERE idArticle NOT IN ( SELECT DISTINCT 16 idArticle
FROM listeCourses
)
tOn peut également utiliser, depuis la norme SQL-92, l’opérateur relationnel
"EXCEPT" qui nous permet très simplement d’effectuer une soustraction :
– Pour cela, nous allons commencer par créer la table de gauche, c’est-à-dire
celle qui contient les données auxquelles on souhaite retirer les données pré-
sentes dans la table de droite (voir l’illustration ci-dessus) :
16. Conformément à nos règles de gestion, un article peut être sur plusieurs listes de courses, il
faut donc utiliser DISTINCT pour supprimer les doublons et ainsi "économiser" des ressources.
8 2943 TG PA 00
– Nous allons à présent créer une deuxième requête liée à la première. Pour
cela, il faut cliquer avec le bouton droit sur l’icône "Q" (présent en haut à
droite de la zone de requête graphique) et choisir "New Union Sub-Query":
– Par défaut, le type d’opération choisi est “Union”. Cliquez sur l’icone d’en-
semble présent entre les deux “Q” et choisissez “Except” pour effectuer une
opération de soustraction :
Séquence 2
Le langage
d'interrogation – Il nous suffit à présent de créer la requête de droite, c’est-à-dire celle dont les
des données (LID)
données vont être retirées à celle de gauche :
Page 60
17. Le "DISTINCT" dans la deuxième table n'est plus nécessaire car "EXCEPT" supprime automati-
quement les doublons.
8 2943 TG PA 00
En SQL, on retrouve bien notre soustraction dans la sous-requête :
SELECT *
FROM article
WHERE idArticle IN ( SELECT idArticle FROM article
EXCEPT
SELECT idArticle FROM listeCourses
) ;
tOu plus simplement, en utilisant une jointure "gauche":
Séquence 2
Le langage
d'interrogation
des données (LID)
Ce qui nous donne, en SQL :
SELECT * Page 61
FROM article LEFT JOIN listeCourses ON
(article.idArticle = listeCourses.idArticle)
WHERE listeCourses.idArticle IS NULL
Sur d’autres SGBDR, la soustraction est possible entre 2 opérandes n’ayant pas le même
nombre de champs. Il suffit pour cela d’indiquer le ou les champs "de correspondance".
Par exemple, sous Oracle, on peut utiliser la requête suivante :
SELECT * FROM article
EXCEPT CORRESPONDING BY (idArticle)
SELECT idArticle FROM listeCourses
L’instruction "CORRESPONDING BY" n’est pas supportée par PostgreSQL. Bien que
présente dans la norme SQL-92, cette instruction a été créée par Oracle qui en est donc
propriétaire. C’est donc apparemment pour des raisons politiques que PostgreSQL ne
la supporte pas.
Avec PostgreSQL, il faut donc obligatoirement que les 2 tables soient strictement iden-
tiques.
8 2943 TG PA 00
Exercice 9
Réaliser les requêtes permettant d’obtenir les informations ci-dessous. Comme
pour les exercices précédents, essayez, dans la mesure du possible, de réaliser ces
requêtes directement en SQL. Si vous n’y arrivez pas, essayez ensuite en graphique :
tla liste des marques qui n’ont aucun article en magasin ;
tla liste des fournisseurs qui n’ont pas effectué de livraisons.
11. La division
Cette opération consiste à trouver une table "résultat" telle que son produit cartésien
avec une table "diviseur" soit un sous-ensemble de la table "dividende".
Table "dividende"
Séquence 2
Le langage
d'interrogation
des données (LID)
Table "résultat"
Vous remarquez que seul le dernier enregistrement de la table de gauche (table "divi-
dende") est en relation avec tous les enregistrements de la table de droite (table "divi-
seur"). C’est pourquoi cette ligne est le seul résultat.
tOn souhaite avoir la liste des articles qui sont sur toutes les listes de courses. Pour
cela, on pose la table "listeCourses" en tant que table "dividende" et la table
"achat" en tant que table "diviseur":
8 2943 TG PA 00
Ce qui nous donne, en SQL :
SELECT idArticle
FROM listeCourses
GROUP BY idArticle
HAVING COUNT(*) = ( SELECT COUNT(*)
FROM achat )
tEt si on veut avoir plus d’informations concernant ces articles, il suffit de compléter
notre précédente requête :
Séquence 2
Le langage
d'interrogation
des données (LID)
Ce qui nous donne, en SQL :
Page 63
SELECT article.idArticle, libelle, prix
FROM listeCourses JOIN article ON
(listeCourse.idArticle = article.idArticle)
GROUP BY article.idArticle, libelle, prix
HAVING COUNT(*) = ( SELECT COUNT(*)
FROM achat
)
8 2943 TG PA 00
Ce qui nous donne, en SQL :
SELECT raisonSociale AS "Fournisseur",
dateLivraison AS "Date de livraison",
COUNT(*) AS "Nb lots livrés"
FROM fournisseur NATURAL JOIN lot
GROUP BY "Fournisseur","Date de livraison"
Résultat : Sous-requête
Fournisseur Date de livraison Nb lots livrés
Lavandes et parfums 2010-03-26 1
Séquence 2 Au bon blé 2010-03-23 2
Pains et gâteaux 2010-04-05 1
Le langage
d'interrogation Super boissons 2010-04-10 1
des données (LID)
Surgel'2000 2010-04-30 1
Lavandes et parfums 2010-04-05 1
Page 64
Super boissons 2010-04-06 1
Super boissons 2010-03-28 1
Super boissons 2010-03-24 3
… … …
tOn sait également que le résultat d’une requête est une nouvelle table. On va donc
se servir de cette nouvelle table dans le FROM :
8 2943 TG PA 00
Ce qui aurait pu nous donner en SQL :
SELECT "Fournisseur",
COUNT(*) AS "Nb livraison"
FROM "sousReq"
GROUP BY "Fournisseur"
Bien entendu, la requête précédente ne fonctionne pas car nous n’avons pas défini
la table "sousReq". C’est pourquoi l’intégralité de la requête "sousReq" doit être
recopiée dans le "FROM" comme si c’était une table :
SELECT "Fournisseur",
COUNT(*) AS "Nb livraisons"
FROM ( SELECT raisonSociale AS "Fournisseur",
dateLivraison AS "Date de livraison",
COUNT(*) AS "Nb lots livrés"
FROM fournisseur NATURAL JOIN lot
GROUP BY "Fournisseur","Date de livraison"
) AS "sousReq"
GROUP BY "Fournisseur"
tMaintenant que l’on sait utiliser des tables issues de sous-requêtes dans le "FROM",
on peut encore améliorer notre précédente requête pour afficher d’autres informa-
tions comme le nombre de lots livrés au total par fournisseur :
8 2943 TG PA 00
Ce qui nous donne en SQL :
SELECT "Fournisseur",
COUNT(*) AS "Nb livraisons",
SUM("Nb lots livrés") AS "Nb total lots"
FROM ( SELECT raisonSociale AS "Fournisseur",
dateLivraison AS "Date de livraison",
COUNT(*) AS "Nb lots livrés"
FROM fournisseur NATURAL JOIN lot
GROUP BY "Fournisseur","Date de livraison"
) AS "sousReq"
GROUP BY "Fournisseur"
Séquence 2
Faire des opérations entre requêtes n’est pas très difficile en soi. Mais, pour réussir, il
Le langage faut absolument traiter les problèmes séparément et ne pas se lancer directement dans
d'interrogation
des données (LID) la construction de la requête finale.
Page 66
Exercice 10
Réaliser les requêtes permettant d’obtenir les informations ci-dessous. Comme pour
les exercices précédents, essayez dans la mesure du possible de réaliser ces requêtes
directement en SQL. Si vous n’y arrivez pas, essayez ensuite en graphique :
tla liste des fournisseurs qui ont déjà livré plusieurs lots lors d’une livraison ;
tle numéro du ou des fournisseurs qui ont effectué le plus de livraisons ;
tle nom du ou des fournisseurs qui ont effectué le plus de livraisons.
TP 1
tTOUR DE FRANCE
8 2943 TG PA 00
Synthèse
Rappel : toutes ces fonctions ne prennent en compte que les lignes qui res-
pectent les conditions du "WHERE".
8 2943 TG PA 00
FROM : de quelle(s) table(s) a-t-on besoin ?
t AS : Facultatif, il permet de renommer une table ;
t Jointures :
– table1 JOIN table2 : effectue une jointure équivalente ;
– tableGauche LEFT JOIN tableDroite : effectue une jointure en conservant
également les lignes de la table de gauche sans lignes équivalentes dans
la table de droite ;
– tableGauche RIGHT JOIN tableDroite : effectue une jointure en conservant
également les lignes de la table de droite sans lignes équivalentes dans la
table de gauche ;
– NATURAL : effectue la jointure définie après "NATURAL" ("JOIN", "LEFT
JOIN" ou "RIGHT JOIN") en prenant comme champ de jointure les champs
portant le même nom dans les 2 tables ;
– Îà utiliser uniquement lorsque l’on est sûr qu’il n’y a que le couple clé
primaire / clé étrangère qui porte le même nom ;
– USING (champClé) : effectue une jointure en prenant comme champ de
jointure le champ défini entre parenthèses ;
– Î à utiliser uniquement lorsque l’on est sûr que le couple clé primaire / clé
étrangère porte le même nom ;
Séquence 2
– ON champClé1 = champClé2 : effectue une jointure en prenant comme
Le langage condition de jointure ce qui est placé après "ON".
d'interrogation
des données (LID) WHERE : quelles sont les conditions de sélection d’un enregistrement ?
t <, >, <=, >=, =, <> : opérateurs de comparaisons qui peuvent être utilisés avec
Page 68 des champs ou des valeurs.
t AND, OR, NOT : opérateurs logiques qui permettent de combiner plusieurs
conditions.
t BETWEEN : définit un intervalle.
syntaxe : nomChamp BETWEEN borne1 AND borne2
t IN : efectue une comparaison sur une liste de valeurs.
t LIKE : Effectue une comparaison partielle. Doit être utilisé obligatoirement
avec des caractères "jokers" (% ou _).
syntaxe : nomChamp LIKE 'chaîne%'
t IS NULL : permet de vérifier si une valeur est "nulle" ou pas (IS NOT NULL).
8 2943 TG PA 00
Séquence 3
Le langage de modification
des données : INSERT / UPDATE /
DELETE
Cette séquence présente la partie de SQL qui permet de mettre à jour une
base de données en insérant, en modifiant ou en supprimant des données.
Pour cette séquence, nous allons abandonner FlySpeed SQL Query, qui ne
nous est plus utile ici. Nous allons utiliser uniquement le code SQL, et, pour
cela, nous allons reprendre pgAdmin.
X Prérequis
Avoir compris le cours et les exercices de la séquence 2.
Synthèse ................................................................... 77
8 2943 TG PA 00
Le LDD en graphique, comment faire ?
Sous pgAdmin, l’ajout, la modification et la suppression d’enregistrement peuvent se
faire très simplement à l’aide de l’éditeur de données :
Éditeur de données
L’ajout
Pour ajouter des données, il suffit de remplir directement une nouvelle ligne :
La modification
Séquence 3
Pour modifier des données, il suffit de les modifier directement dans l’éditeur :
Le langage
de modification
des données (LMD)
Î
Page 70
La suppression
Pour supprimer des enregistrements, il suffit de cliquer avec le bouton droit sur la ligne
à supprimer et de choisir "Supprimer":
Même lorsque l’on a la possibilité d’utiliser un logiciel graphique pour effectuer des opé-
rations sur un SGBDR, il faut garder à l’esprit que tout ce que l’on fait "graphiquement"
est en réalité réalisé en "langage SQL". C’est pourquoi il est nécessaire de connaître le
langage, sans compter que l’on ne peut pas forcément "tout" faire graphiquement, alors
qu’en SQL, c'est le cas !
8 2943 TG PA 00
1. L’ajout d’un tuple avec "INSERT"
L’ajout simple
En SQL, l’ajout d’un nouvel enregistrement se fait avec l’instruction "INSERT".
tPar exemple, on veut ajouter une nouvelle marque :
INSERT INTO marque (idMarque,nom)
VALUES (31,'Kelona')
Les valeurs contenues après "VALUES" seront insérées dans l’ordre dans lequel les
champs sont déclarés après le nom de table. La déclaration des champs est facultative
et, lorsqu’ils ne sont pas présents, c’est l’ordre dans lequel ils ont été déclarés lors de la
création de la table qui est pris en compte. L’ordre des champs n’a pas d’importance à
partir du moment où il y a bien une cohérence entre l’ordre des champs et les valeurs
qui vont y être insérées.
tPour ajouter cette nouvelle marque, on peut également faire :
INSERT INTO marque
VALUES (31,'Kelona')
tOu encore :
INSERT INTO marque (nom,idMarque)
VALUES ('Kelona',31) Séquence 3
Le langage
Lors d’une insertion, il peut arriver qu’on ne souhaite pas remplir tous les champs18. de modification
tIl suffit pour cela de ne pas déclarer dans le "INSERT" le ou les champs à laisser sans des données (LMD)
contenu :
Page 71
INSERT INTO marque (idMarque)
VALUES (31)
tOu alors de stipuler clairement que l’on veut une valeur "nulle":
INSERT INTO marque (idMarque,nom)
VALUES (31,NULL)
Attention, la valeur NULL est différente d’une chaîne vide" (2 apostrophes simples). Ce
qui veut dire que :
"INSERT INTO marque VALUES (31,NULL)" n’aura pas du tout la même incidence
que
"INSERT INTO marque VALUES (31,").
18. Pour cela, il faut au préalable que la saisie n’ait pas été rendue obligatoire à la création de la
table (case "Non NULL" non cochée lors de l’ajout du champ).
8 2943 TG PA 00
On veut, par exemple, ajouter une nouvelle marque, mais on souhaite que son identi-
fiant soit automatique et non plus saisi 19.
tOn sait récupérer le dernier identifiant de marque. Il suffit donc de l’incrémenter
de 1 pour obtenir le nouveau :
SELECT MAX(idMarque)+1 AS "Prochain n° de marque"
FROM marque
tIl nous suffit donc d’ajouter le nom de la marque dans le "SELECT" pour obtenir une
table avec le nouvel identifiant de marque et son nom :
SELECT MAX(idMarque)+1 AS "Prochain n° de marque",
'Kelona' AS "Nouvelle marque"
FROM marque
"VALUES" a été remplacé par "SELECT" car, ici, nous n’ajoutons pas des "valeurs" mais
bien des "enregistrements" retournés par le "SELECT".
L’ajout multiple
Si l’on a plusieurs nouveaux enregistrements à ajouter, on peut bien évidemment multi-
plier les "INSERT" autant de fois que nécessaire. Toutefois, on peut également procéder
à l’ajout de plusieurs enregistrements avec un seul "INSERT":
tOn a, par exemple, 3 nouveaux rayons à ajouter :
INSERT INTO rayon
VALUES (16,'Confiserie'),
(17,'Informatique'),
(18,'Musique')
19. La plupart des SGBDR proposent un système d’incrémentation automatique qui est bien sûr
à privilégier, le but ici est de mettre en œuvre des sous-requêtes d’interrogation dans une
requête d’insertion.
8 2943 TG PA 00
tAdmettons maintenant que ces nouveaux rayons soient dans une table "nouveau-
xRayons":
Résultat : nouveauxRayons
idRayon libelle
16 Confiserie
17 Informatique
18 Musique
tNous allons donc indiquer à "INSERT" où aller récupérer les rayons à ajouter :
INSERT INTO rayon
SELECT *
FROM nouveauxRayons
tSi on ne veut ajouter que le n° 17, il nous suffit de modifier notre "SELECT" comme
on sait déjà le faire :
INSERT INTO rayon
SELECT *
FROM nouveauxRayons
WHERE idRayon = 17
Exercice 1 Séquence 3
20
20. La table "nouveauxArticles" n'existant pas dans notre base, la requête ne pourra pas être
testée avec pgAdmin.
8 2943 TG PA 00
2. La modification d’un tuple avec "UPDATE"
Les données présentes dans une base ne sont bien évidemment pas figées. Le SQL nous
permet de modifier les données d’une table grâce à l’instruction "UPDATE". On peut
également parler de mise à jour des données.
tOn souhaite, par exemple, dans le cadre d’une promotion, baisser de 5 % le prix de
tous les articles :
UPDATE article
SET prix = prix * 0.95
Cette requête modifie tous les enregistrements de la table "article" sans condition.
L’instruction "UPDATE" comme l’instruction "SELECT" peuvent recevoir en complément
l’instruction "WHERE" qui permet de définir une condition de mise à jour.
tOn souhaite, par exemple, dans le cadre d’une promotion, baisser de 15 % le prix
de tous les articles "bio":
UPDATE article
SET prix = prix * 0.85
WHERE bio = TRUE
Séquence 3
"UPDATE" n’est pas limité à la mise à jour d’un seul champ : lors d’une mise à jour, on
peut modifier le contenu de tous les champs désirés.
Le langage
de modification
des données (LMD)
tPrenons, par exemple, le cas du fournisseur n° 6 qui déménage "chemin du
Page 74 Rossignol" à "Châteauvallon" (83190). Sa raison sociale ne change pas, son numéro
de téléphone et son email non plus. Par contre, sa nouvelle distance est de 5,2 km :
UPDATE fournisseur
SET adresseRue = 'chemin du Rossignol',
adresseCP = '83190',
adresseVille = 'Châteauvallon',
distanceKm = 5.2
WHERE idFournisseur = 6
"UPDATE", dans sa définition d’origine, est limité à l’utilisation d’une seule table.
Mais, depuis SQL-92, on peut utiliser des sous-requêtes de la même manière qu’avec les
requêtes d’interrogations.
tOn souhaite, par exemple, déplacer tous les articles "bio" du rayon "Apéritifs" (on
ne connaît pas le numéro) dans le rayon n° 2. Au passage, on souhaite baisser le
prix de ces articles de 5% :
8 2943 TG PA 00
UPDATE article
SET idRayon = 2, prix = prix * 0.95
WHERE idRayon IN ( SELECT idRayon
FROM rayon
WHERE libelle = 'Apéritifs'
)
AND bio = TRUE
tOn peut même s’appuyer sur une sous-requête pour définir la nouvelle valeur d’un
champ. On veut, par exemple, déplacer tous les articles "bio" du rayon "Apéritifs"
dans le rayon "Boissons". Au passage, on souhaite baisser le prix des articles de 5 % :
UPDATE article
SET idRayon = ( SELECT idRayon
FROM rayon
WHERE libelle = 'Boissons'
),
prix = prix * 0.95
WHERE idRayon IN ( SELECT idRayon
FROM rayon
WHERE libelle = 'Apéritifs'
)
AND bio = TRUE
Séquence 3
Le langage
Exercice 2 de modification
des données (LMD)
Réaliser les requêtes permettant d’effectuer les mises à jour suivantes :
til y a une promotion, tous les articles du rayon "Surgelés" baissent de 10 % ; Page 75
tune autre promotion réduit le prix de tous les articles de la marque "Bonduil"
de 1 € ;
tune personne rapporte un paquet de "glaces chocolat en cornets" et désire
qu’on lui reprenne contre remboursement (ticket de caisse n° 1).
8 2943 TG PA 00
Comme avec "INSERT" et "UPDATE", on peut également utiliser une sous-requête pour
mieux cibler les enregistrements à supprimer.
tPar exemple, si l’on veut supprimer les fournisseurs que l’on a dans la base mais qui
n’ont jamais fait de livraison :
DELETE FROM fournisseur
WHERE idFournisseur NOT IN ( SELECT idFournisseur
FROM lot
)
Attention, lorsque vous concevez une requête de suppression, veillez à ce que votre requête
respecte bien les règles de gestion de votre base, sans quoi elle ne fonctionnera pas.
Cette requête seule ne pourra pas fonctionner car elle ne respecte pas la contrainte d’inté-
Séquence 3 grité référentielle suivante : la clé étrangère idRayon de la table "article" fait référence à
la clé primaire idRayon de la table "rayon". En effet, si on supprime ce rayon, les articles
Le langage qui y sont, feront référence à un rayon qui n’existe plus. C’est pourquoi, pour pouvoir
de modification supprimer ce rayon, il faut d’abord supprimer les références à ce rayon.
des données (LMD)
tOn commence par supprimer la référence au rayon "Apéritifs" dans article 21 :
Page 76
UPDATE article
SET idRayon = NULL
WHERE idRayon = ( SELECT idRayon
FROM rayon
WHERE libelle = 'Apéritifs'
)
tEt enfin, on peut supprimer le rayon :
DELETE FROM rayon
WHERE libelle = 'Apéritifs'
TP 2
tTOUR DE France - suite
21. Si on respecte strictement notre MCD, ça n’est pas non plus possible car les cardinalités entre
"article" et "rayon" nous informent qu’un article est placé dans un et un seul rayon.
8 2943 TG PA 00
Synthèse
t SET : permet de désigner les champs où opérer la mise à jour ainsi que les
Séquence 3
nouvelles valeurs à affecter.
syntaxe : UPDATE table Le langage
de modification
SET champ1 = valeur1 , champ2 = valeur2 , … , champN = valeurN des données (LMD)
8 2943 TG PA 00
Séquence 4
Le langage de description
des données : CREATE / ALTER /
DROP
Cette séquence présente la partie de SQL qui permet de créer, de modifier
et de supprimer des tables.
X Prérequis
Avoir compris le cours et les exercices des séquences précédentes.
X Contenu Séquence 4
...........................................................................................................
Synthèse 95
8 2943 TG PA 00
1. La création d’une table
Pour créer une table, on procède de la même manière qu’avec pgAdmin, c’est-à-dire que
l’on a besoin du dictionnaire des données pour avoir les informations sur chaque champ.
Ensuite, il nous suffit d’utiliser l’instruction de création "CREATE TABLE" que nous four-
nit le langage SQL.
Par exemple, on souhaite proposer à nos clients un système de points en fonction du
montant des achats. Ce système permettra à ceux qui le désirent de cumuler des points
qui, après un certain nombre donnent droit à un cadeau.
Pour pouvoir comptabiliser ce nombre de point, on va devoir créer une table qui contien-
dra les clients qui souhaitent participer à ce système. On profite d’effectuer ce référen-
cement pour proposer aux clients de s’abonner à une newsletter (lettre d’information
par email).
ACHAT CLIENT
idAchat
0,1 Effectuer 1,n idClient
dateAchat nom
montantTotal prenom
dateDeNaissance
email
newsletter
– Diagramme de classes :
ACHAT CLIENT
idAchat 1..* 0..1 idClient
dateAchat nom
montantTotal prenom
dateDeNaissance
email
newsletter
8 2943 TG PA 00
tOn va également devoir mettre à jour notre schéma relationnel des données :
ACHAT (idAchat, dateAchat, montantTotal, idClient)
idAchat : Clé primaire
idClient : Clé étrangère en référence à idClient de
client
CLIENT (idClient, nom, prenom, dateDeNaissance, email,
newsletter)
idClient : Clé primaire
tAinsi que notre dictionnaire des données :
Nom Type de données Longueur Précision
CLIENT
idClient numeric 4 0
nom character varying
prenom character varying
dateDeNaissance date
email character varying
newsletter boolean
Avec cette requête, on se rend encore une fois bien compte qu’en SQL il suffit d’indiquer
au système ce que l’on veut obtenir, pour l’obtenir.
8 2943 TG PA 00
2. Les clés primaires
La clé primaire d’une relation est l’attribut ou l’ensemble d’attributs qui permet de dis-
tinguer entre eux tous les tuples de la relation. Cette clé primaire (simple ou composée)
doit donc être unique et définie (non nulle).
tOn peut indiquer directement la clé primaire lors de la déclaration de la table en
ajoutant "PRIMARY KEY" à la définition du champ :
CREATE TABLE client
(
idClient numeric(4) PRIMARY KEY,
...
)
"PRIMARY KEY" permet d’indiquer que la valeur du champ doit être unique et qu’elle
ne peut pas être nulle. L’utilisation de "PRIMARY KEY" de cette manière ne fonctionne
qu’avec une clé primaire simple. Lorsqu’elle est composée, il faut déclarer explicitement
une contrainte sur la table.
tPar exemple, pour créer la table "listeCourses" qui contient une clé primaire com-
posée des champs "idAchat" et "idArticle", voici ce qu’on doit faire :
CREATE TABLE listecourses
Séquence 4
(
idAchat numeric(8) NOT NULL,
Le langage idArticle numeric(13) NOT NULL,
de description quantite numeric(3)
des données (LDD)
CONSTRAINT pk_listeC PRIMARY KEY (idAchat, idArticle)
)
Page 82
"PRIMARY KEY" est limité à une seule utilisation par table, ce qui revient à dire qu’une
table ne possède qu’une seule clé primaire (qui peut être composée de plusieurs champs).
Cela confirme qu’il faut bien parler d’une "clé primaire composée" et non pas de "clés
primaires". Cette syntaxe est plus claire fonctionne quelle que soit la composition de la
clé primaire et est, de toute façon, ce qui sera fait en réalité par le SGBDR.
tLorsque le SGBDR exécute cette requête :
CREATE TABLE client
(
idClient numeric(4) PRIMARY KEY,
...
)
tEn réalité, voici exactement ce que le SGBDR fait :
CREATE TABLE client
(
idClient numeric(4) NOT NULL,
...
CONSTRAINT pk_client PRIMARY KEY (idClient)
)
8 2943 TG PA 00
tOn le voit d’ailleurs également lorsqu’on le fait graphiquement avec pgAdmin.
Il faut en effet "ajouter" une "contrainte" de "clé primaire":
"FOREIGN KEY" indique que la clé étrangère idClient fait "REFERENCE" à la table
"client" et en particulier au champ idClient. On n’est pas obligé de créer les contraintes
en même temps que les tables. Dans la partie suivante, nous verrons comment faire.
On a vu comment déclarer une clé étrangère simple, mais on peut également être amené
à devoir créer une clé étrangère composée, comme ici, par exemple, si une contrainte
d’intégrité fonctionnelle pointe sur la table "lot" qui possède une clé primaire composée.
8 2943 TG PA 00
...
CONSTRAINT fk_lot FOREIGN KEY (idLot,idArticle)
REFERENCES lot (idLot,idArticle)
...
tSous pgAdmin, cela revient à créer une clé étrangère composée, qui pointe vers
une clé primaire composée :
Séquence 4
Le langage
de description
des données (LDD)
Page 84
Exercice 1
Réaliser les requêtes permettant de créer 22 les tables suivantes :
t"rayon", "article" et "marque".
22. Attention, les tables étant déjà créées, vous ne pourrez pas tester ces requêtes via pgAdmin.
8 2943 TG PA 00
4. La modification d’une table
Comme on vient de le voir, la structure d’une base de données peut être amenée à évo-
luer. Encore une fois, le langage SQL a tout prévu avec l’instruction "ALTER" qui permet
de modifier la structure d’une table existante.
tPar exemple, la table "achat" étant déjà créée, on veut juste lui adjoindre un
champ :
ALTER TABLE achat
ADD COLUMN idClient numeric(4)
8 2943 TG PA 00
Lorsque l’on veut supprimer un champ qui possède une contrainte, on peut supprimer le
champ directement avec un "DROP COLUMN" sans avoir besoin au préalable d’effectuer
un "DROP CONSTRAINT".
t"ALTER" nous permet également de renommer les champs. Par exemple, si on veut
"franciser" l’appellation de l’adresse électronique (mél) des clients :
ALTER TABLE client
RENAME COLUMN email TO mel
Séquence 4
Le langage
de description tDe la même façon, on peut renommer également le nom de la table :
des données (LDD)
ALTER TABLE client
Page 86 RENAME TO consommateur
Lorsque l’on renomme une table ou une clé primaire, on peut se poser la question des
références existantes à ces noms. Pas d’inquiétude, le SGBDR se charge de renommer les
cibles des références. Ainsi, dans la table "achat" :
8 2943 TG PA 00
...
CONSTRAINT fk_client FOREIGN KEY (idClient)
REFERENCES client (idClient)
...
Deviendra automatiquement :
...
CONSTRAINT fk_client FOREIGN KEY (idClient)
REFERENCES consommateur (idClient)
...
Attention, toutefois, lorsque l’on utilise "RENAME", aucune autre modification n’est combi-
nable. Il faudra obligatoirement passer par un autre "ALTER TABLE".
tOn peut également être amené à changer le type d’un champ. Par exemple, on veut
passer le champ "dateAchat" de la table "achat" en "chaîne de caractères" (character
varying) :
ALTER TABLE achat
ALTER COLUMN dateAchat TYPE character varying
C’est encore une preuve que la connaissance du langage SQL reste essentielle, au-delà
même d’un bon savoir-faire sur un logiciel graphique !
tOn peut également modifier les contraintes sur un champ. Admettons que l’on souhaite
supprimer le rôle de clé primaire 23 du champ "idClient" de la table "client" et que l’on
souhaite aussi supprimer la contrainte d’existence "NOT NULL":
ALTER TABLE client
DROP CONSTRAINT pk_client
23. Attention, cette opération ne sera possible que si aucune clé étrangère n’y fait référence.
8 2943 TG PA 00
Graphiquement, sous pgAdmin, il suffit de cliquer avec le
bouton droit sur la "Contrainte" ciblée dans l’organisation
graphique de la table puis de choisir "Supprimer":
Attention, supprimer le rôle de clé primaire n’est possible que si aucune référence au
champ visé n’existe dans la base.
Et si, au contraire, on veut contraindre un champ à être saisi, on utilisera "SET".
Sous pgAdmin, il faut décocher la case "non NULL" dans les propriétés du champ :
Page 88
Exercice 2
Réaliser les requêtes permettant d’effectuer les modifications suivantes :
tle champ "libelle" de la table "rayon" est renommé en "nomRayon";
tle champ "packaging" de la table "article" est supprimé ;
tle champ "raisonSociale" de la table "fournisseur" devient obligatoire.
8 2943 TG PA 00
5. La suppression d’une table
La suppression d’une table se fait grâce à l’instruction "DROP TABLE".
tPar exemple, on veut supprimer la table temporaire "nouveauxRayons":
DROP TABLE nouveauxRayons
Attention, lorsque l’on supprime une table, il faut obligatoirement qu’il n’y ait plus
aucune référence à cette table dans la base de données. Encore une fois, le respect de
l’intégrité référentielle est capital dans la gestion de bases de données.
Sous pgAdmin, il suffit de cliquer avec le bouton droit sur la table ciblée et de choisir
"Supprimer":
Séquence 4
Le langage
de description
des données (LDD)
tSi on veut, par exemple, supprimer la table "client", il faut d’abord supprimer la
contrainte de clé étrangère dans "achat": Page 89
ALTER TABLE achat
DROP CONSTRAINT fk_client
DROP TABLE client
Supprimer une contrainte ne supprime pas le champ contraint. Donc, si l’objectif est
de supprimer le champ, il faudra aussi effectuer un "DROP COLUMN" dans le "ALTER
TABLE". Ou alors, comme on l’a vu précédemment, on peut se contenter de supprimer le
champ, ce qui aura pour effet de supprimer le champ et sa contrainte.
Exercice 3
Réaliser les requêtes permettant de supprimer la table suivante :
t"nouveauxArticles" de l’exercice 1 de la séquence 3.
8 2943 TG PA 00
6. Les index
Le sommaire au début de ce cours vous permet d’accéder à une séquence directement,
sans avoir à parcourir toutes les pages pour la trouver. De la même manière, un index
dans une base de données sert à optimiser l’accès aux données afin qu’il soit le plus
"facile" possible en indexant certaines colonnes et ainsi optimiser les temps de traite-
ment.
Un index est une table "système" qui accompagne une table de données suivant la règle
selon laquelle, pour chaque enregistrement de la table de données, il existe une ligne
correspondante dans la table "index" (l’ordre des lignes étant différent dans la table
"index").
La gestion des index est utilisée par tous les SGBDR mais ne fait pas partie de la norme
SQL et, même dans sa dernière révision (SQL:2008) : on ne trouve pas la moindre trace
d’index. L’explication est simple, le SQL a été créé pour répondre à des problématiques
"logiques" de gestion des données, pas pour répondre aux problématiques "systèmes" des
administrateurs de SGBDR.
PostgreSQL crée automatiquement un index pour chaque clé primaire afin d’assurer
l’unicité. Il n’est donc pas nécessaire de créer un index spécifiquement pour les colonnes
de clés primaires.
Par défaut, les données que contient une table apparaîssent dans l’ordre dans lequel on
les a saisies. Cet ordre ne correspond pas toujours à celui dont on a besoin pour traiter
Séquence 4
les données.
Le langage
de description
des données (LDD)
Page 90
8 2943 TG PA 00
Comme avec la plupart des techniques d’optimisation des performances, il n’existe
pas de règles générales : par exemple, si notre application effectue principalement des
requêtes d’interrogation ("SELECT"), mettre en œuvre davantage d’index permet à nos
requêtes de s’exécuter plus rapidement. Mais si notre application effectue de nombreuses
opérations de manipulation de données ("INSERT", "UPDATE" et "DELETE"), on doit
alors limiter le nombre d’index créés pour ne pas ralentir ces opérations de manière
significative.
La mise en œuvre d’index implique une étude des requêtes les plus importantes, et plus
particulièrement celles dont les performances ont le plus d’impact sur les utilisateurs.
C’est pourquoi, après avoir créé un index, il faut réexécuter les requêtes que l’on a
étudiées et déterminer si les performances ont été améliorées. Si ce n’est pas le cas, il
faudra supprimer l’index.
Avec PostgreSQL (comme avec presque tous les SGBDR), si on veut créer un index, il suffit
d’utiliser l’instruction "CREATE INDEX" (qui, je le rappelle, ne fait pas partie de la norme
SQL).
tPar exemple, si notre application utilise beaucoup de requêtes portant sur les libel-
lés d’articles, on va créer un index sur cette colonne en triant les libellés par ordre
alphabétique :
CREATE INDEX idx_libelleArticle
ON article (libelle ASC)
8 2943 TG PA 00
On se rend bien compte du temps de traitement économisé lorsque l’on exécute cette
requête :
SELECT *
FROM article
ORDER BY libelle ASC
En effet, au lieu d’avoir à parcourir l’intégralité de la table article, le moteur d’exécution
va se contenter de parcourir la table index "idx_libelleArticle".
Attention, toutefois, à bien rester vigilant sur la mise en œuvre des index et à les utiliser
à bon escient car chaque index doit ensuite subir des opérations de maintenance par le
SGBDR. Ces opérations étant, elles, consommatrices de ressources.
Sous pgAdmin, la création d’un index se fait en cliquant avec le bouton droit sur "Index"
dans l’organisation graphique de la table ciblée puis en choisissant "Ajouter un index…".
Il suffit ensuite de nommer l’index et de choisir les colonnes :
Î Î
Séquence 4
Le langage
de description
des données (LDD)
Page 92
8 2943 TG PA 00
7. Les vues
La "vue" est comme un filtre permettant de voir uniquement les données qui nous inté-
ressent. C’est pour cette raison qu’on parle de visualiser ou de modifier des données "à
partir" d’une vue.
Une vue n’est rien d’autre qu’une table "virtuelle" s’appuyant sur une ou plusieurs tables
"réelles" appelées, pour l’occasion, "tables sous-jacentes à la vue".
Il faut commencer par créer cette vue grâce à l’instruction "CREATE VIEW".
tPar exemple, on veut en permanence avoir la liste des articles (libellés, prix, noms
de marques et libellés de rayons) ayant un prix inférieur à 1 € :
CREATE VIEW vue_articlesInf1Euro AS
SELECT a.libelle AS "Article",
prix AS "P.U",
nom AS "Marque",
r.libelle AS "Rayon"
FROM article AS a NATURAL JOIN marque
JOIN rayon AS r USING (idRayon)
WHERE prix < 1
ORDER BY prix ASC
tUne fois la vue créée, on l’utilise exactement de la même façon qu’une table
"réelle". Par exemple, ici, on ne veut que les articles dont le prix est inférieur à 1 € Séquence 4
mais tout de même supérieur ou égal à 0,50 € :
Le langage
SELECT * de description
des données (LDD)
FROM vue_articlesInf1Euro
WHERE "P.U" >= 0.5
Page 93
Bien évidemment, les conditions que l’on spécifie dans le "WHERE" viennent s’ajouter
à celles spécifiées dans la vue. La requête précédente est donc équivalente à :
...
FROM article AS a NATURAL JOIN marque
JOIN rayon AS r USING (idRayon)
WHERE prix >= 0.5
AND prix < 1
...
Résultat : vue_articlesinf1Euro
Article P.U. Marque Rayon
Ketchup nature 0,99 Amogla Condiments
Pain de mie nature 0,99 Sally's Pain
Eau minérale aromatisée 0,99 Vilvic Boissons
… … … …
Sous pgAdmin, la création d’une vue se fait en cliquant avec le bouton droit sur "Vues"
qui se trouve au même niveau que les tables et en choisissant "Ajouter une vue…". Il
suffit ensuite de nommer la vue et d’insérer la requête qui va définir la vue dans l’onglet
"Définition":
8 2943 TG PA 00
Î Î
Encore une fois, on voit ici la nécessité de connaître le langage SQL même lorsque l’on
utilise un logiciel graphique !
Attention, l’insertion ou la mise à jour "à partir" d’une vue est possible mais nécessite
d’être encadrée. L’instruction "WITH CHECK OPTION" ajoutée au "CREATE VIEW"
permet d’insérer ou de mettre à jour uniquement les enregistrements accessibles "à par-
tir" de la vue, c’est-à-dire satisfaisants aux conditions définies à la création de la vue.
Une vue a de multiples missions :
Séquence 4
– remplacer une requête complexe par une ou plusieurs requêtes simples ;
– assurer un semblant de confidentialité en ne rendant accessibles que certains
Le langage champs ;
de description – permettre d’avoir des noms de tables et de champs plus simples ;
des données (LDD) – pouvoir réutiliser un même ensemble de tuples pour plusieurs recherches.
Page 94 tLa suppression d’une vue se fera simplement avec "DROP VIEW":
DROP VIEW vue_articlesInf1Euro
TP 3
tTOUR DE France - suite
8 2943 TG PA 00
Synthèse
8 2943 TG PA 00
Séquence 5
Le langage de contrôle
de données
Cette séquence va nous permettre d’aborder des problématiques essen-
tiellement sécuritaires avec la gestion des utilisateurs, des accès concur-
rents et du maintien de l’intégrité de la base de données.
X Prérequis
Avoir acquis les connaissances liées aux trois premières parties du langage SQL
(LID, LMD, LDD).
X Contenu Séquence 5
..........................................................................................................
Synthèse 117
8 2943 TG PA 00
1. Contexte d’étude (évolution)
Nous allons continuer à étudier un commerce de proximité de type "supérette". Par
rapport aux séquences précédentes, son schéma a légèrement évolué car, d’une part la
supérette s’est agrandie et a ouvert des magasins à Nice et à Marseille (la supérette de
Toulon est donc devenue le siège social), et, d’autre part, elle propose désormais à ses
clients un catalogue de meubles qu’ils peuvent commander (l’achat en magasin n’est pas
possible).
0,n
0,n
Séquence 5 ACHAT
FOURNISSEUR ListeCourses 1,n
idAchat
Le langage
de contrôle idFournisseur quantite dateAchat
de données (LCD) raisonSociale montantTotal
adresseRue
Page 98 adresseCP Évolution du système d'information
adresseVille
email CLIENT 0,1
numeroTelephone idClient
distanceKm Effectuer
nom 1,n
prenom
dateDeNaissance
email
newsletter
ristourne VENDEUR
MEUBLE idVendeur
0,n
idMeuble nomV
descMeuble prenomV
Passer
prixMeuble 0,n
qteDispo
0,n 1,1
COMMANDE Prendre
LigneCde 1,1
1,n idCommande
qteCde dateComm
totalCde
8 2943 TG PA 00
Diagramme de classes de la base de données "magasin"
Le langage
1..* de contrôle
de données (LCD)
Évolution du système d'information
0..1
Page 99
VENDEUR CLIENT
idVendeur idClient
MEUBLE nomV nom
prenomV prenom
idMeuble dateDeNaissance
decsMeuble 1..* email
prixMeuble 1
newsletter
qteDispo ristourne
1
*
* COMMANDE
LIGNECDE idCommande
*
qteCde dateComm
totalCde
8 2943 TG PA 00
Schéma relationnel de la base de données "magasin"
FOURNISSEUR (idFournisseur, raisonSociale, adresseRue,
adresseCP,adresseVille, email, numeroTelephone,
distanceKm)
idFournisseur : Clé primaire
LOT (idLot, idArticle, dateFabrication, dateLivraison,
datePeremption, idFournisseur)
idLot, idArticle : Clé primaire
idArticle : Clé étrangère en référence à idArticle de article
idFournisseur : Clé étrangère en référence à idFournisseur de
fournisseur
ARTICLE (idArticle, libelle, prix, packaging, uniteMesure,
quantite, bio, idMarque, idRayon)
idArticle : Clé primaire
idMarque : Clé étrangère en référence à idMarque de marque
idRayon : Clé étrangère en référence à idRayon de rayon
RAYON (idRayon, libelle)
idRayon : Clé primaire
MARQUE (idMarque, nom)
Séquence 5
idMarque : Clé primaire
LISTECOURSES (idArticle, idAchat, quantite)
Le langage
de contrôle idArticle, idAchat : Clé primaire
de données (LCD) idArticle : Clé étrangère en référence à idArticle de article
idAchat : Clé étrangère en référence à idAchat de achat
Page 100
ACHAT (idAchat, dateAchat, montantTotal)
idAchat : Clé primaire
CLIENT (idClient, nom, prenom, dateDeNaissance, email,
ristourne)
idClient: Clé primaire
COMMANDE (idCommande, dateComm, totalCde, idVendeur, idClient)
idCommande: Clé primaire
idVendeur : Clé étrangère en référence à idVendeur de vendeur
idClient : Clé étrangère en référence à idClient de client
VENDEUR (idVendeur, nomV, prenomV)
idVendeur: Clé primaire
MEUBLE (idMeuble, descmeuble, prixMeuble, qteDispo)
idMeuble: Clé primaire
LIGNECDE (idMeuble, idCommande, qteCde)
idMeuble, idCommande : Clé primaire
idMeuble : Clé étrangère en référence à idMeuble de meuble
idCommande : Clé étrangère en référence à idCommande de
commande
8 2943 TG PA 00
2. Le contrôle des données dans les révisions de SQL
Dès la première version de la norme SQL, les problématiques de sécurité et de gestion
des utilisateurs ont été abordées, mais, au départ, la décision prise par l’ISO a été de
laisser la spécification des commandes définissant les utilisateurs aux concepteurs de
chaque SGBDR.
tSQL-89 : gestion de "privilèges" et attributions avec l’instruction "GRANT". À ce
niveau, SQL permet de limiter l’utilisation de certaines instructions (CREATE, SELECT,
INSERT, UPDATE, DELETE) à des utilisateurs sur l’intégralité du SGBDR, d’une base ou
d’une table spécifique. Toutefois, chaque attribution de privilèges ne peut porter
que sur un objet à la fois (une seule base, ou une seule table).
tSQL-92 : une nouvelle instruction "REVOKE" permet de retirer des privilèges, de
nouvelles instructions peuvent être limitées (DROP, ALTER) et l’on peut désormais
limiter plus finement certaines instructions (SELECT, INSERT, UPDATE) à une liste
restreinte de colonnes.
tSQL-99 : une nouvelle instruction permettant de limiter l’utilisation des clés étran-
gères fait son apparition (REFERENCES) ainsi qu’une instruction pour limiter la
création de déclencheur (TRIGGER). De plus, c’est à cette révision que l’on voit
apparaître des instructions normalisées de création de "rôles".
Les révisions suivantes n’apportent rien de plus, ce qui n’a pas empêché les éditeurs
d’implémenter davantage d’instructions (TRUNCATE, EXECUTE, CONNECT …).
Séquence 5
Le langage
3. La gestion des utilisateurs en SQL de contrôle
de données (LCD)
Comme on vient de le voir, jusqu’à la révision SQL-99, la gestion des utilisateurs reposait Page 101
entièrement sur les concepteurs de SGBDR. C’est pourquoi il est courant de trouver l’ins-
truction non normalisée "CREATE USER" en lieu et place de l’instruction "CREATE ROLE"
que certains éditeurs n’ont même pas encore intégrée dans leur produit.
La question que l’on peut se poser c’est : pourquoi proposer la notion de "rôle" plutôt
que celle d’"utilisateur"? Simplement parce que SQL considère que ce ne sont pas des
utilisateurs (au sens humain) qui vont se connecter au SGBDR, mais des applications
clientes avec des permissions bien définies.
Par exemple, une application qui sert à consulter le contenu d’une base de données doit-
elle utiliser un compte lui permettant de faire autre chose que du "SELECT"? La réponse
est, bien évidemment, non. En informatique, il ne faut jamais commettre l’imprudence
de réfléchir avec le vieil adage "Qui peut le plus, peut le moins": c’est une erreur ! Il faut
au contraire toujours préférer appliquer la politique du moindre privilège : un processus
ne dispose que des privilèges nécessaires à l’exécution d’un travail donné.
Bien que l’instruction "CREATE USER" n’existe pas dans la norme SQL, nous allons tout
de même nous en servir, car elle a le mérite d’exister chez quasiment tous les éditeurs de
SGBDR alors que l’instruction "CREATE ROLE", bien que normalisée, n’existe pas partout.
MySQL, par exemple, ne la prend pas en charge. PostgreSQL, de son côté, a transformé
l’instruction "CREATE USER" en alias de "CREATE ROLE", collant ainsi au plus près à la
norme SQL. Mais c’est le seul rapprochement, car la norme ne fournit pas toutes les
options rattachées à cette instruction (mot de passe, date d’expiration d’un compte …).
D’une manière générale, nous allons voir des instructions qui ne sont pas dans la norme,
8 2943 TG PA 00
car, encore une fois, la spécification des commandes liées aux utilisateurs a été volontai-
rement laissée aux éditeurs des SGBDR. La suite des instructions sera donc très "orientée
PostgreSQL".
En l’absence de ce logo, cela signifiera que les instructions ne sont pas dans la norme SQL
mais qu'elles sont propres à PostgreSQL, voire, lorsque c’est signalé, à un autre SGBDR.
4. Les rôles
Dans un projet d’informatisation qui inclut une base de données, les utilisateurs d’une
base de données sont identifiés lors de la phase d’analyse.
Les utilisateurs
Les utilisateurs, appelés "rôles de connexion" sous PostgreSQL, permettent de res-
treindre l’accès au SGBDR aux seuls utilisateurs déclarés.
tPrenons l’exemple du comptable, M. Luca Pacioli. Il doit pouvoir se connecter à la
base de données. Nous allons donc lui créer un compte :
Séquence 5 CREATE ROLE lpacioli
SQL LOGIN PASSWORD 'motdepasse'
Le langage
de contrôle
de données (LCD)
tSous PostgreSQL, on peut également utiliser la commande suivante :
Pour créer un utilisateur graphiquement sous pgAdmin, il nous suffit d’utiliser la gestion
des "rôles de connexion" présente dans l’organisation graphique :
Les rôles
Les rôles, appelés "rôles de groupe" sous PostgreSQL, permettent de regrouper des uti-
lisateurs amenés à partager les mêmes autorisations.
tImaginons, par exemple, que le comptable ait 2 assistants (Harry Cover et Lara
Tatouille) qui devront avoir les mêmes droits d’accès que lui. Nous allons donc créer
un rôle "compta" et y rattacher nos 3 utilisateurs (créés au préalable) :
8 2943 TG PA 00
CREATE ROLE compta
SQL
GRANT compta
TO lpacioli , hcover , ltatouille
Pour créer un "groupe" graphiquement sous pgAdmin, il nous suffit d’utiliser la gestion
des "rôles de groupe" présente dans l’organisation graphique :
Comme nous l’avons vu, les "rôles" n’ont fait leur apparition qu’à partir de SQL-99. Or,
avec une grande quantité d’utilisateurs, il était évident que les éditeurs se tourneraient
vers une gestion proche de celle que l’on trouve sur les systèmes d’exploitation, à savoir
une gestion par groupes, représentatifs de l’organisation de l’entreprise. Sans attendre
que la norme prenne en compte leurs besoins, les éditeurs de SGBDR ont alors intégré
la gestion de groupes. C’est pourquoi il est courant de trouver la commande "CREATE Séquence 5
GROUP", ainsi que la commande "ALTER GROUP … ADD USER" pour pouvoir ajouter
Le langage
des utilisateurs : de contrôle
de données (LCD)
CREATE GROUP compta
Page 103
ALTER GROUP compta
ADD USER lpacioli , hcover , ltatouille
La modification de rôle
La norme SQL fournit l’instruction de création (et de destruction, que nous verrons plus
loin), mais pas de modification. Les SGBDR intègrent tout de même une instruction per-
mettant d’effectuer les modifications suivantes :
tOn souhaite, par exemple, renommer le rôle "compta" en "compta_consult":
ALTER ROLE compta
RENAME TO compta_consult
tSi l’on souhaite changer le mot de passe du comptable :
ALTER ROLE lpacioli
WITH LOGIN PASSWORD 'nouveau_pass'
Tout ce qui touche à un rôle peut être modifié avec l’instruction "ALTER ROLE", à l’ex-
ception de la gestion des appartenances pour laquelle l’on devra utiliser les instructions
"GRANT" et "REVOKE" (que nous allons voir un peu plus loin).
8 2943 TG PA 00
Pour modifier un "rôle" graphiquement sous pgAdmin,
il nous suffit d’utiliser les propriétés du rôle ciblé (clic
droit sur le rôle, puis "Propriétés"). Par exemple, ici, il
suffira de saisir le nouveau mot de passe et sa confir-
mation :
Dès lors, les instructions suivantes seront réalisées sous l’identité du rôle "compta_mise-
jour". Nous venons de voir le cas classique où nous récupérons des droits supplémen-
24. Cette instruction, qui est l’acronyme anglais de "Substitute User DO", permet d’exécuter une opération en
substituant son identité à celle d’un autre utilisateur.
25. Pour rappel, la commande "rm" permet de supprimer des fichiers (ReMove) et le paramètre "-f", quant à
lui, permet de lancer une suppression sans demander de confirmation.
8 2943 TG PA 00
taires en substituant son identité à celle d’un rôle plus "privilégié". Il faut savoir que la
démarche inverse est également possible.
tSupposons que l’on se soit connecté avec le compte "postgres" (administrateur du
SGBDR PostgreSQL) et que l’on veuille vérifier ce que peut voir l’utilisateur "lpacio-
li". Il nous suffit d’exécuter la commande suivante pour récupérer provisoirement
l’identité de "lpacioli":
SET ROLE lpacioli
Pour pouvoir changer d’identité graphiquement sous pgAdmin, il faut nous déconnecter,
changer les propriétés de la connexion, puis nous reconnecter avec l’identité désirée. Et
recommencer ensuite pour retrouver son identité de départ :
Î Î
Séquence 5
Le langage
de contrôle
de données (LCD)
Page 105
Cet exemple démontre encore une fois que la connaissance du SQL peut représenter sans
aucun doute un formidable gain de temps !
Supprimer un rôle
Comme dans toute gestion d’utilisateur, il peut arriver que l’on ait à supprimer des
comptes. SQL-92 définit la suppression de rôle avec l’instruction "DROP ROLE".
tPrenons l’exemple d’une application de comptabilité remplacée par un nouveau
produit. Jusqu’alors, cette application utilisait les rôles "pgi_consult" et "pgi_misea-
jour" pour travailler avec une base de données de notre organisation. L’arrêt d’uti-
lisation de cette application entraîne également la suppression de ses rôles dont
l’existence n’est plus justifiée :
DROP ROLE pgi_consult
SQL
8 2943 TG PA 00
tSous PostgreSQL, on peut également supprimer plusieurs rôles dans la même com-
mande, ce que ne permet pas la norme SQL :
DROP ROLE pgi_consult , pgi_miseajour
8 2943 TG PA 00
tPar exemple, si l’on veut créer un rôle "stagiaire" qui expirera automatiquement le
1er juin 2012 :
CREATE ROLE stagiaire
WITH LOGIN PASSWORD 'motdepasse'
VALID UNTIL '2012-06-01'
Notons toutefois que passé la date d’expiration le compte n’est pas supprimé. La
connexion avec ce dernier est certes impossible, mais rien n’empêche son utilisation avec
la commande "SET ROLE".
Attention, d’une part la norme SQL recommande de n’avoir qu’un seul rôle d’admi-
nistrateur et d’autre part, comme on l’a vu précédemment, il est fortement déconseillé
de travailler en "superuser". C’est pourquoi une bonne pratique consiste à utiliser un
compte qui dispose des droits "CREATEDB" et "CREATEROLE", mais qui ne soit pas un
"superuser". Cela permet encore une fois de respecter la politique de sécurité du "moindre
privilège" et ainsi d’éviter les dangers encourus en travaillant avec un compte ne se limi-
tant pas aux privilèges nécessaires pour la réalisation d’une tâche donnée. Il vaut donc Séquence 5
mieux créer notre "admin_bis" avec la commande suivante :
Le langage
de contrôle
CREATE ROLE admin_bis de données (LCD)
WITH LOGIN PASSWORD 'motdepasse'
CREATEDB Page 107
CREATEROLE
5. Les privilèges
La création des utilisateurs nous a permis de gérer les connexions au SGBDR. Nous allons
maintenant voir comment gérer l’accès aux données.
8 2943 TG PA 00
SQL nous fournit le privilège "ALL PRIVILEGES" qui est censé regrouper tous les pri-
vilèges précédents. Seulement, il faut faire attention, car, encore une fois, les éditeurs
sont allés beaucoup plus loin en implémentant des privilèges et des objets recouvrant
toutes les problématiques du SGBDR (création de bases de données, création de rôles,
lancement de procédures …) :
GRANT ...
ON DATABASE
FUNCTIONS
LANGUAGE
...
En utilisant "ALL PRIVILEGES", le risque est donc de donner beaucoup plus de privi-
lèges que prévu, et, surtout, de donner des privilèges outrepassant la simple gestion de
tables ou de vues. Cela ne permet toutefois pas de donner le privilège de transmettre
des privilèges (voir ci-après).
SQL nous fournit également l’option "GRANT OPTION" qui se place à la fin de l’ins-
truction et qui permet à celui qui reçoit ce privilège de pouvoir le transmettre à son tour.
En d’autres termes, cela permet à un rôle de donner des privilèges à d’autres rôles sur
les mêmes objets. C’est le seul privilège qui ne soit pas inclus dans "ALL PRIVILEGES".
tNous allons, par exemple, autoriser le comptable à consulter et à mettre à jour les
tables "fournisseur" et "lot":
GRANT SELECT , UPDATE
Séquence 5 SQL ON fournisseur
TO lpacioli
Le langage
de contrôle
de données (LCD)
GRANT SELECT , UPDATE
ON lot
Page 108 TO lpacioli
SQL n’autorisant pas l’attribution de droits sur plus d’une table par commande, la mise
en place de privilèges sur un nombre important de tables peut rapidement se révéler fas-
tidieuse. L’ayant bien compris, les éditeurs de SGBDR ont rapidement conçu une parade
en étendant l’instruction "GRANT" pour lui permettre d’accepter l’attribution de droits
sur plusieurs tables simultanément. Les 2 commandes précédentes peuvent donc être
regroupées en une seule sur la plupart des SGBDR :
GRANT SELECT , UPDATE
ON fournisseur , lot
TO lpacioli
Comme on vient de le voir, les privilèges sont
attribués sur des tables. Graphiquement, ce
sont donc les propriétés des tables qu’il faudra
modifier pour pouvoir effectuer de l’attribu-
tion de privilèges :
8 2943 TG PA 00
Attention, pgAdmin ne permet pas d’attribuer des privilèges à des "rôles de connexion".
Il faut obligatoirement passer par un rôle de groupe, ou alors le faire en SQL !
SQL nous permet d’utiliser le rôle générique "PUBLIC" qui désigne tous les rôles du Séquence 5
SGBDR. Ce qui veut dire que l’on peut attribuer le droit en "lecture" sur la table "article"
Le langage
à tous les utilisateurs du SGBDR : de contrôle
de données (LCD)
GRANT SELECT
SQL ON article Page 109
TO PUBLIC
8 2943 TG PA 00
Accorder des privilèges sur des colonnes
Comme on l’a vu précédemment, bien que l’instruction "GRANT" existe depuis SQL-89,
ce n’est qu’avec l’arrivée de SQL-92 que l’on a pu restreindre des privilèges à une partie
d’une table ou d’une vue.
tPar exemple, si l’on souhaite autoriser le rôle "secretariat" à consulter l’intégralité
de la table "fournisseur", mais à ne pouvoir mettre à jour que les colonnes "email"
et "numeroTelephone":
GRANT SELECT , UPDATE (email , numeroTelephone)
SQL ON fournisseur
TO secretariat
Séquence 5
Attention, un rôle (ou un utilisateur, qui, rappelons-le, est également un rôle) possède :
Le langage s la somme des droits qui lui ont été donnés directement ;
de contrôle s la somme des droits qui ont été donnés à un rôle dont il est membre.
de données (LCD)
Ce qui veut dire qu’ici, si "lpacioli" est bien membre du rôle "compta", il continue de
bénéficier du privilège "UPDATE" sur la table "lot". Donc, ici, si l’on veut lui retirer le
Page 110 droit de mise à jour sur la table "lot", il faudra également le retirer du groupe "compta"
avec la commande suivante :
REVOKE compta
SQL FROM lpacioli
Après cela, il ne lui restera que les droits qui le concernent individuellement.
Exercice 1
À partir de l’explication suivante, mettre en place les rôles et privilèges nécessaires
pour prendre en compte tous les besoins :
t2 vendeurs "Alice" et "Bernard" qui doivent pouvoir prendre en compte des
commandes de meubles par des clients.
t3 comptables "lpacioli", "hcover" et "ltatouille" qui doivent pouvoir insérer de
nouveaux fournisseurs et mettre à jour les prix de tous les articles et meubles de
la base de données.
8 2943 TG PA 00
Exercice 2
Travail à faire
Écrire les ordres SQL permettant d’autoriser tous les utilisateurs de la base de don-
nées à consulter la table INTERVENTION et l’utilisateur d’identifiant RDeltour à faire
toute insertion, modification ou suppression de données sur cette même table.
8 2943 TG PA 00
Annexe 2 Schéma relationnel de la base de données des tournées
8 2943 TG PA 00
Exercice 3
Extrait du cas EPOKA (Métropole, 2004)
EPOKA PRESSE est une société de presse qui conçoit, réalise et publie des magazines
vendus sur tout le territoire français (métropole et DOM-TOM). Le dernier titre mis
sur le marché par EPOKA PRESSE est le magazine mensuel Savoir vendre. Ce maga-
zine très spécialisé vise un public de vendeurs qu’il a pour objectif de conseiller dans
l’exercice de leur métier.
EPOKA PRESSE souhaite se doter d’un intranet pour assurer une meilleure coopé-
ration et une communication plus rapide entre les différents acteurs (rédacteurs,
pigistes, maquettistes) participant à l’élaboration de ses publications. La revue Savoir
vendre a été choisie pour expérimenter cette nouvelle forme de travail. Vous avez
été recruté(e) afin de participer au développement de cet intranet ainsi qu’à celui de
plusieurs applications de gestion permettant de mieux exploiter la revue.
Vocabulaire utilisé :
tOn emploie indifféremment les termes "magazine" et "revue".
tUn(e) pigiste est une personne qui écrit des articles et qui est payée "à la pige",
c’est-à-dire à l’article.
tUn feuillet est un ensemble de 1 500 signes ou caractères alphanumériques. La
longueur d’un article s’exprime en nombre entier de feuillets (on arrondit au
nombre entier le plus proche).
Séquence 5
tLe chapeau d’un article est un texte court qui présente succinctement le conte-
nu de l’article. Le langage
de contrôle
tMettre en ligne un article sur l’intranet signifie le rendre accessible en lec- de données (LCD)
ture à tous les utilisateurs de l’intranet.
tPublier un article dans le magazine signifie insérer cet article dans un Page 113
numéro précis du magazine.
Les magazines édités par EPOKA PRESSE sont distribués par une entreprise de diffu-
sion qui assure aussi le retour des invendus.
EPOKA PRESSE gère les invendus à l’aide d’une base de données dont le schéma
relationnel est présenté en annexe 3. Un taux d’invendus (TI) est calculé pour chaque
point de vente à partir du nombre d’exemplaires reçus (NR) et du nombre d’exem-
plaires vendus (NV) par le point de vente.
TI = (NR-NV) / NR
Travail à faire
Écrire en langage SQL les requêtes permettant de supprimer tous les anciens droits
sur les tables NUMERO ET VENTE pour le compte utilisateur REDACT et donner à ce
compte les droits de suppression, d’insertion, de consultation, de mise à jour sur la
table NUMERO et uniquement le droit de consultation sur la table VENTE.
8 2943 TG PA 00
Annexe 3 Extrait du schéma relationnel de la base "Diffusion"
8 2943 TG PA 00
Exercice 4
Extrait du cas JMS (Métropole, 2002)
La société JMS est une unité d’entretien agréée par le Groupement de Sécurité de
l’Aviation Civile (GSAC), administration chargée, en France, de la sécurité dans le
domaine aéronautique. JMS assure la maintenance des avions pour le compte de
plusieurs aéro-clubs.
La société JMS emploie du personnel administratif et des mécaniciens. Elle dispose
d’un atelier où sont réceptionnés les avions acheminés là pour y subir leurs visites
d’entretien, programmées régulièrement. Un magasin jouxte l’atelier et permet aux
mécaniciens de disposer immédiatement des pièces détachées utiles à leurs interven-
tions.
Toutes les interventions sur les avions donnent lieu à la rédaction des documents
exigés par le GSAC.
On considère la base de données "AERO" où sont enregistrées les interventions réa-
lisées dans le cadre de l’entretien des avions. Elle a été conçue à partir des schémas
de relation suivants :
Travail à faire
Écrire en langage SQL les requêtes permettant d’autoriser la nouvelle secrétaire,
dont le compte vient d’être ouvert sous le nom d’utilisateur "MONIQUE", à autoriser
toutes les opérations sur la table SUBIR et, lui interdire toute intervention, sauf la
sélection sur les autres tables.
8 2943 TG PA 00
Exercice 5
Extrait du cas SECOLOG (Métropole, 2001)
SECOLOG (Société Européenne de Conception de Logiciel) est une SSII spécialisée
dans le développement d’applications de gestion. Solidement implantée au niveau
régional, elle regroupe une quinzaine de personnes occupant des bureaux situés
dans un immeuble récent. L’activité de l’entreprise est centrée autour de 3 pôles
d’activité :
tLe développement d’applications.
tLe support technique apporté aux clients.
tLa formation des utilisateurs.
L’entreprise emploie 6 développeurs, un commercial, 2 techniciens, une secrétaire
polyvalente et 2 formateurs. L’encadrement est assuré par 2 chefs de projet et le
directeur, fondateur de la société.
Concernant la gestion des formations proposées par SECOLOG à ses clients, une
étude a déjà été réalisée et a conduit à la production du schéma relationnel décrit
dans l’annexe 2.
Travail à faire
Rédiger en langage SQL les requêtes correspondant au besoin suivant : autoriser
Séquence 5 l’utilisateur DUPARC à insérer, mettre à jour et supprimer des lignes dans la table
SALARIÉ
Le langage
de contrôle
de données (LCD)
Annexe 2 Schéma relationnel du domaine "Gestion des formations"
Page 116
SALARIÉ (Matricule, NomSalarié, PrénomSalarié, Adr1Salarié, Adr2Salarié, CPSalarié,
VilleSalarié, DateEmbauche)
PRODUIT (CodeProduit, NomProduit)
SPÉCIALISER (Matricule#, CodeProduit#)
FORMATION (CodeForm, LibelléForm, NbMaxStagiaires, CodeProduit#)
SESSION (CodeForm#, NoSession, DateSession, Matricule#)
STAGIAIRE (NoStagiaire, NomStagiaire, PrénomStagiaire, NoClient#)
PARTICIPER (CodeForm#, NoSession#, NoStagiaire#)
CLIENT (NoClient, NomClient, Adr1Client, Adr2Client, CPClient, VilleClient)
Remarques :
tLes clés primaires sont soulignées et les clés étrangères sont suivies du carac-
tère #.
tNbMaxStagiaires désigne le nombre maximum de stagiaires pour une forma-
tion.
tLa clé étrangère Matricule# de la relation SESSION référence le formateur de la
session.
tLa relation CLIENT provient de l’entité CLIENT du domaine "Gestion des pro-
positions commerciales" et représente donc les organisations en relation avec
l’entreprise ; les stagiaires en formation sont issus de ces entreprises.
8 2943 TG PA 00
Synthèse
8 2943 TG PA 00
REVOKE privilège : retire un ou plusieurs privilèges ("SELECT", "INSERT",
"UPDATE", "DELETE", "REFERENCES", "TRIGGER")
t ON : spécifie un ou plusieurs objets sur lesquels portent les privilèges
(colonnes, tables, vues, bases de données, procédures stockées, langages …).
t FROM : spécifie un ou plusieurs rôles destinataires de ces privilèges.
syntaxe : REVOKE privilège
ON objet1 , objet2 , … , objetN
FROM rôle1 , rôle2 , … , rôleN
Séquence 5
Le langage
de contrôle
de données (LCD)
Page 118
8 2943 TG PA 00
Séquence 6
Le langage de contrôle
des transactions
À la séquence précédente, nous avons vu comment protéger un
SGBDR en restreignant son accès aux seuls utilisateurs autorisés,
et avec une liste de privilèges restreinte à leurs besoins. Nous al-
lons à présent voir comment veiller à ce que les manipulations
d’un utilisateur ne portent pas préjudice à un autre utilisateur.
Dans cette partie, nous verrons exclusivement du SQL car les différentes
instructions de contrôle des transactions ne sont pas réalisables en gra-
phique.
X Prérequis
Avoir acquis les connaissances liées aux quatre premières parties du langage
SQL (LID, LMD, LDD, LCD) et, de préférence, avoir quelques notions en adminis-
tration des systèmes d’information.
Séquence 6
X Contenu
1. Accès simultanés, quels sont les risques ? ....................................... 120
2. Les transactions ................................................................................ 123
.........................................................................................................
Synthèse 132
8 2943 TG PA 00
1. Accès simultanés, quels sont les risques ?
Dans la séquence 4, nous avons vu différents procédés nous permettant d’assurer la
cohérence des données (clé primaire avec "PRIMARY KEY", clé étrangère avec "FOREIGN
KEY", existence avec "NOT NULL").
Ces contraintes d’intégrité référentielle sont là pour veiller à ce que les données soient
cohérentes entre elles, mais, avec les accès simultanés aux bases de données par plusieurs
utilisateurs et / ou applications, ces procédés se révèlent insuffisants, car ils ne sont pas
capables d’identifier les incidences que peuvent avoir les manipulations d’un utilisateur
sur les manipulations d’un autre utilisateur.
Séquence 6 QteDispo
Temps26 Alice Bernard
(TBH007)
Le langage SELECT qteDispo
de contrôle
des transactions (LCT) T FROM meuble 3
WHERE idMeuble = 'TBH007'
Page 120 SELECT qteDispo
T+1 3 FROM meuble
WHERE idMeuble = 'TBH007'
UPDATE meuble
T+2 SET qteDispo = qteDispo - 3 0
WHERE idMeuble = 'TBH007'
UPDATE meuble
T+3 -1 SET qteDispo = qteDispo - 1
WHERE idMeuble = 'TBH007'
INSERT INTO commande
T+4 -1
VALUES ( '110901001' , '2011-09-01' , 89.7 )
INSERT INTO commande
T+5 -1
VALUES ( '110901002' , '2011-09-01' , 29.9 )
INSERT INTO ligneComm
T+6 -1
VALUES ( '110901001' , ' TBH007' , 3 )
INSERT INTO ligneComm
T+7 -1
VALUES ( '110901002' , ' TBH007' , 1 )
8 2943 TG PA 00
Le résultat ici est catastrophique, Bernard vient de prendre la commande d’un meuble
alors qu’il n’y en a plus de disponible !
Pour sa défense, le SGBDR ne dispose pas d’éléments qui lui permettent d’ordonner les
opérations, ou de prioriser des opérations par rapport à d’autres. C’est là qu’intervient
le langage de contrôle des transactions que nous allons étudier plus loin.
La lecture "fantôme"
Reprenons un autre cas avec nos deux vendeurs, "Alice" et "Bernard". Ils sont tous les
deux connectés au SGBDR et effectuent simultanément des commandes :
tAlice est avec un client qui souhaite commander une chaise en bois référencée
"CHB12". Après quelques hésitations, le client demande finalement à annuler sa
commande (événement qui survient à "T+6" ci-dessous).
tAu même moment, Bernard, qui est, lui aussi, avec un client, souhaite trouver tous
les modèles de chaises pour lesquels il en reste au moins 4 disponibles.
QteDispo
Temps Alice Bernard
(CBH12)
SELECT *
FROM meuble
T 4
WHERE descMeuble LIKE '%chaise%'
AND qteDispo >= 4
SELECT qteDispo
Séquence 6
T+1 FROM meuble 4
WHERE idMeuble = 'CBH12' Le langage
UPDATE meuble de contrôle
des transactions (LCT)
T+2 SET qteDispo = qteDispo - 1 3
WHERE idMeuble = 'CBH12'
Page 121
SELECT *
FROM meuble
T+3 3
WHERE descMeuble LIKE '%chaise%'
AND qteDispo >= 4
INSERT INTO commande
T+4 3
VALUES ( '110901025' , '2011-09-01' , 5.95 )
INSERT INTO ligneComm
T+5 3
VALUES ( '110901025' , 'CH12' , 1 )
DELETE FROM ligneComm
T+6 3
WHERE idComm = '110901025'
DELETE FROM commande
T+7 3
WHERE idComm = '110901025'
UPDATE meuble
T+8 SET qteDispo = qteDispo + 1 4
WHERE idMeuble = 'CBH12'
SELECT *
FROM meuble
T+9 4
WHERE descMeuble LIKE '%chaise%'
AND qteDispo >= 4
8 2943 TG PA 00
Si l’on se met à la place de Bernard, qu’a-t-il vu ?
tÀ la première recherche, la chaise "CBH12" apparaît dans les résultats.
tAu deuxième lancement, la chaise "CBH12" n’apparaît plus (il n’y alors plus que
3 unités disponibles, ce qui ne satisfait plus le critère de recherche).
tAu troisième lancement, la chaise "CBH12" réapparaît dans les résultats (c’est en
général à ce moment-là que les personnes devant l’écran froncent les sourcils…).
Ce phénomène d’apparition et de disparition d’enregistrements est appelé phénomène
de "lecture fantôme" dans le monde des SGBDR (Boooooh !).
La lecture "sale"
Cette fois-ci, le comptable et la vendeuse "Alice" travaillent simultanément sur la base
de données :
tLe comptable souhaite répercuter la hausse de 3,5 % des coûts de livraison (suite à
la hausse des coûts du carburant) sur le prix des meubles. Seulement, en mettant à
jour les prix, il se trompe et saisit 35 % au lieu de 3,5 %. S’apercevant de son erreur,
il effectue alors la correction en veillant à augmenter les prix d’uniquement 3,5 %.
tAu même moment, Alice, qui est avec un client, s’apprête à passer la commande
d’un meuble de salon (référencé "MS2") pour un client qui a été séduit par son prix
à 100 €.
prixMeuble
Temps Alice Le comptable
(MS2)
Séquence 6
SELECT *
T 100
Le langage FROM meuble
de contrôle
SELECT *
des transactions (LCT)
T+1 FROM meuble 100
Page 122 WHERE idMeuble = 'MS2'
UPDATE meuble
T+2 135
SET prixMeuble = prixMeuble * 1.35
UPDATE meuble
T+3 SET qteDispo = qteDispo - 1 135
WHERE idMeuble = 'MS2'
INSERT INTO commande
T+4 135
VALUES ( '110901041' , '2011-09-01' , 135 )
UPDATE meuble
T+5 103.50
SET prixMeuble = prixMeuble / 1.35 * 1.035
INSERT INTO ligneComm
T+6
VALUES ( '110901041' , 'MS2' , 1 )
On peut s’attendre à ce que le client d’Alice soit pour le moins surpris lorsqu’au moment
de payer on lui demandera 135 € au lieu des 100 prévus…
En toute logique, le SGBDR aurait dû attendre que le comptable termine sa série d’ins-
tructions avant de permettre à Alice de travailler sur les mêmes données. Ce phénomène
est ce que l’on appelle une “lecture sale”, qui représente le fait de lire des données à un
instant où elles ne sont peut-être pas définitives.
Mais, encore une fois, le SGBDR ne dispose pas d’éléments qui lui permettent d’ordonner
ou de prioriser des opérations par rapport à d’autres. Nous allons donc maintenant voir
le concept de transaction qui répond à ce besoin.
8 2943 TG PA 00
2. Les transactions
Arrivée avec SQL-92, la gestion des transactions est un concept fondamental qui met en
avant la prévention des incidents liés aux accès simultanés (car, comme on vient de le voir,
ils peuvent être nombreux) et la reprise après incident (panne logicielle ou matérielle).
Appelé "modèle ACID" en référence à l’acronyme des quatre objectifs à atteindre
(Atomicité, Cohérence, Isolation, Durabilité) 27, ce modèle fait partie des concepts les
plus anciens et les plus fondamentaux de la théorie des bases de données. C’est pour-
quoi un SGBDR qui ne satisfait pas à ces objectifs ne peut dès lors être considéré comme
"fiable 28".
Atomicité
Une transaction doit être considérée comme un assemblage de plusieurs étapes pour
former une opération "atomique" de type "tout ou rien":
Transaction T
Séquence 6
START TRANSACTION
SQL /* Modification du prix des meubles */
UPDATE meuble
SET prixMeuble = prixMeuble * 1.35
/* Annulation des modifications (retour à T-1) */
ROLLBACK
27. Acronyme présent dans SQL-92 (termes anglais) : Atomicity - Consistency - Isolation - Durability.
28. Ce qui est le cas pour "MyISAM", le moteur par défaut de MySQL auquel il faudra préférer "innoDB" si
l’on veut disposer du respect du modèle "ACID".
8 2943 TG PA 00
tAprès l’annulation, il recommence donc l’opération :
START TRANSACTION
SQL /* Modification du prix des meubles */
UPDATE meuble
SET prixMeuble = prixMeuble * 1.035
/* Validation des modifications (passage à T+1) */
COMMIT
Cohérence
Une transaction doit être "cohérente", c’est-à-dire qu’elle débute sur un état cohérent
de la base (T-1) et doit donc se terminer sur un nouvel état cohérent (T+1) :
tSi le SGBDR ne rencontre pas de problèmes et réussit à exécuter toutes les étapes
qui composent la transaction, les mises à jour peuvent être effectuées (passage à
l’état T+1).
tSi une seule violation des règles d’intégrité référentielle est rencontrée, c’est la
transaction dans son intégralité qui doit être annulée et aucune des étapes ne doit
affecter la base de données (retour à l’état T-1).
Isolation
Une transaction doit être "isolée" des autres transactions pour éviter de possibles
Séquence 6 interférences. Les états intermédiaires entre les étapes sont transparents pour les autres
transactions concurrentes. Bien entendu, le concept d’isolation ne remet pas en question
Le langage la concurrence des accès et des transactions. Deux mécanismes permettent d’isoler les
de contrôle
des transactions (LCT) transactions : le verrou et la sérialisation.
tLe verrou fait appel au concept d’"accès exclusif". C’est-à-dire que tant qu’une
Page 124 transaction accède à une donnée, aucune autre transaction ne peut y accéder. Les
transactions qui souhaiteraient accéder à cette donnée doivent attendre que la
transaction qui a verrouillé l’accès ait terminé. L’utilisation de verrous pose deux
grands problèmes :
– La famine : lorsqu’une transaction se termine et qu’un verrou est libéré, le
SGBDR choisit la transaction suivante "T" parmi les transactions en attente
et dont les ressources nécessaires sont disponibles. Ainsi, si une transaction a
besoin d’accéder à 2 données qui ne sont jamais "libres" en même temps, elle
peut se retrouver à passer son tour indéfiniment.
X
T T
X
8 2943 TG PA 00
verrouillée, va attendre sa libération. De son côté, "T2" va accéder à "tab1" et,
voyant qu’elle est verrouillée, va attendre sa libération également.
T1 T1 X T1
T2 T2 X T2
tLa sérialisation est une contrainte forte qui impose aux transactions concurrentes
de s’exécuter séquentiellement les unes après les autres. Il faut pour cela que l’exé-
cution des transactions se fasse en 2 étapes :
– Acquisition des verrous : la transaction commence par verrouiller toutes les
ressources dont elle a besoin ;
– Libération des verrous : une fois terminée ("validée" ou "annulée"), la tran-
saction libère tous les verrous.
L’acquisition de verrous se fait automatiquement sur la plupart des SGBDR qui le
gèrent plutôt bien. La norme SQL, quant à elle, ne nous parle pas explicitement de ver-
rous, ce concept est sous-entendu (c’est pourquoi de nombreux SGBDR ont implémenté
l’instruction "LOCK" qui permet de verrouiller l’accès à une table). SQL nous fournit
la commande "SET TRANSACTION" à laquelle nous pouvons adjoindre des niveaux
d’isolation en fonction des anomalies que l’on souhaite éviter :
Anomalies qui peuvent se produire
Lecture Lecture Lecture Séquence 6
Niveau d'isolation
"non renouvelable" "fantôme" "sale"
Le langage
0 – Read Uncommited X X X
de contrôle
1 – Read Commited X X des transactions (LCT)
2 – Repeatable Read X
3 – Serializable Page 125
La compréhension de ces mécanismes est fondamentale pour les développeurs qui sou-
haitent créer des solutions fiables et rapides de traitement des données. Les niveaux plus
hauts réduisent la possibilité de paralléliser les traitements. C’est pourquoi le choix d’un
niveau d’isolation est le choix du développeur en fonction de plusieurs critères : perfor-
mances, sécurité et / ou contraintes métiers.
8 2943 TG PA 00
Durabilité
L’effet d’une transaction doit être "durable", c’est-à-dire qu’une fois terminée les
modifications doivent persister. Cette persistance est assurée par l’utilisation conjointe
de sauvegardes et de journaux de transactions qui assurent le maintien des effets d’une
transaction même en cas de défaillance logicielle ou matérielle qui se produirait avant
la fin d’une transaction :
tSi c’est la transaction qui est à la cause du problème, il faudra que le SGBDR puisse
"défaire" ses effets. En prenant le nouvel état d’une donnée et les consignations
faites dans les journaux de transactions, le système est capable de restaurer l’état
antérieur à la panne (T-1).
Transaction T
T+x
Le langage
de contrôle tToutefois, si ce n’est pas la transaction qui est à l’origine de la défaillance, au
des transactions (LCT) redémarrage, le SGBDR va consulter les journaux de transaction pour restaurer
automatiquement les transactions incomplètes jusqu’au moment où il y a eu une
Page 126 défaillance (T+x).
Transaction T
T+x
Début Log
Défaillance Fin temps
SQL
8 2943 TG PA 00
Que seraient-ils devenus ? Eh bien, ils auraient également subi le "ROLLBACK" et notre
comptable aurait dû les ressaisir…
La norme SQL nous fournit l’instruction "SAVEPOINT" nous permettant d’effectuer
des sauvegardes en cours de transaction, ce qui permet de faire des "retours arrière"
partiels, sans avoir à annuler intégralement toutes les manipulations réalisées depuis le
début de la transaction.
tReprenons les manipulations de notre comptable, en admettant, cette fois-ci, qu’il
a procédé à l’insertion de 2 nouveaux fournisseurs avant de commettre son impair :
START TRANSACTION
SQL /* Ajout de deux nouveaux meubles */
COMMIT
8 2943 TG PA 00
Certains éditeurs de bases de données ont implémenté l’instruction "SET CONSTRAINTS"
pour permettre aux développeurs d’avoir le choix :
ts’ils souhaitent que les contraintes soient vérifiées immédiatement après chaque
instruction en utilisant la clause "IMMEDIATE";
tou s’ils souhaitent que la vérification des contraintes soit différée à la validation de
la transaction en utilisant la clause "DEFERRED".
Attention, certains éditeurs, comme PostgreSQL ou MySQL, ont choisi de faire l’inverse
des préconisations de SQL-92. C’est-à-dire qu’ils considèrent que, par défaut, la vérifi-
cation des contraintes est immédiate après chaque instruction et cela même si l’on se
trouve dans une transaction.
s Ils vont même plus loin, car, pour qu'une contrainte puisse être différée, elle doit
avoir été au préalable déclarée comme "DEFERRABLE", et ne doit pas porter sur un
champ ayant une contrainte "NOT NULL" :
CREATE TABLE article
(
idarticle numeric(13) NOT NULL,
...
idrayon numeric(2) NOT NULL,
idmarque numeric(3),
CONSTRAINT pk_article
PRIMARY KEY(idarticle),
Séquence 6 CONSTRAINT fk_rayon FOREIGN KEY (idrayon)
REFERENCES rayon (idrayon),
Le langage
de contrôle
CONSTRAINT fk_marque FOREIGN KEY (idmarque)
des transactions (LCT) REFERENCES marque (idmarque) DEFERRABLE
)
Page 128
s Et seulement ensuite, différer les vérifications de contraintes avec l’instruction "SET
CONSTRAINTS", car, par défaut, ces SGBDR considèrent que toutes les contraintes
sont "NOT DEFERRABLE":
– Le report des vérifications peut porter sur toutes les contraintes auxquelles la
transaction va avoir affaire :
START TRANSACTION
SET CONSTRAINTS ALL DEFERRED
...
COMMIT
START TRANSACTION
SET CONSTRAINTS fk_rayon DEFERRED
...
COMMIT
8 2943 TG PA 00
Exercice 1
Extrait du cas CREDAUTO (Métropole, 2006)
La société CREDAUTO est spécialisée dans le crédit automobile accordé aux particu-
liers. Elle agit en partenariat avec des garagistes, établissements commercialisant des
véhicules neufs ou d’occasion. Un prêt CREDAUTO est proposé à un particulier qui
souhaite acheter un véhicule et éprouve le besoin de financer tout ou partie de cet
achat.
En fin de mois, la secrétaire reçoit les demandes de remboursement de frais de repas
et de nuitée engagés par les intervenants lors de leurs déplacements. Les frais d’es-
sence et de péage sont réglés à l’aide d’une carte de société mise à leur disposition.
Un dossier mensuel de demandes de remboursement de frais est créé pour chaque
intervenant lors de la saisie de sa première demande du mois. Pour chaque demande,
la secrétaire enregistre autant de "notes de frais" qu’il y a de nuitées et de repas,
en précisant, pour chacune, la date, le montant déclaré ainsi que le type (nuitée ou
repas). Elle indique également la présence ou non d’un justificatif.
Si la secrétaire dispose de tous les justificatifs, le dossier mensuel de notes de frais
pourra être traité ; dans le cas contraire, elle réclame les justificatifs manquants à
l’intervenant. Celui-ci dispose de quinze jours pour les lui remettre.
Une analyse a permis l’élaboration d’un schéma entité-association (annexe 3A). Il est
accompagné de 2 règles de gestion R1 et R2 exprimées textuellement :
Séquence 6
tR1 : Un intervenant travaille obligatoirement soit sur une région, soit pour une
marque de véhicule, mais jamais pour les deux en même temps. Le langage
tR2 : Un intervenant ne peut déposer que des notes de frais dont le type lui est de contrôle
des transactions (LCT)
autorisé.
Un exemple de séquence d’ordres SQL exécutée lors de la saisie de notes de frais par Page 129
la secrétaire est présenté ci-après. On souhaite analyser l’impact d’un incident (panne
de courant, etc.) survenant au cours de l’exécution de cette séquence, en particulier
suite à l’exécution de la troisième requête INSERT.
Travail à faire
Dans le cas d’un incident survenant suite à l’exécution de la troisième requête
INSERT :
A. Indiquer quelles seront les lignes ajoutées dans les tables DOSSIERMENSUEL et
NOTEDEFRAIS pour l’intervenant de code "980045" en avril 2006. Justifier la
réponse.
8 2943 TG PA 00
B. Indiquer, en utilisant l’annexe 3A, la règle de gestion qui ne sera pas respectée
dans ce cas.
C. Proposer un réaménagement de la séquence d’ordres SQL figurant ci-dessus
afin de résoudre ce problème.
REGION ANNÉE
0,n Travaille région année
codeRégion
libelléRégion 0,n
0,1 Porte
(1,1)
INTERVENANT DOSSIER MENSUEL
Travaille marque
0,1 codeIntervenant 0,n dateRéception
Donne Concerne
nomIntervenant 0,n datePaiement (1,1)
prénomIntervenant montantTotalPayé
0,n 0,n 1,n
Séquence 6
MARQUE
Autorise Comporte 0,n
Le langage codeMarque MOIS
de contrôle libelléMarque
mois
des transactions (LCT) 0,n 0,n
TYPE NOTE DE FRAIS
Page 130 codeType
Correspond
numéroOrdre
libelléType 0,n 1,1
date
plafond montantNoteFrais
justificatif_O_N
8 2943 TG PA 00
Annexe 3B Extrait du schéma relationnel "Gestion des frais"
(Afin de ne pas alourdir le schéma, seules les tables utiles sont présentées)
Le langage
Remarques : de contrôle
des transactions (LCT)
tLe champ justificatif_O_N de la table NOTEDEFRAIS prend les valeurs true ou
false selon la présence ou l’absence de justificatif pour la note de frais. Page 131
tLe champ MontantTotalDu prend pour valeur le cumul de tous les rembourse-
ments plafonnés correspondant aux notes de frais déposées par un intervenant
pour le mois.
8 2943 TG PA 00
Synthèse
8 2943 TG PA 00
Corrigé des exercices
Vous trouverez ici le corrigé de tous les exercices du fascicule. Les exercices
étant numérotés par séquence, vous les retrouverez classés par séquence.
X Contenu
Conseils généraux ................................................................................. 133
Séquence 1 ............................................................................................. 134
Séquence 2 ............................................................................................. 139
Séquence 3 ............................................................................................. 151
Séquence 4 ............................................................................................. 153
Séquence 5 ............................................................................................. 155
Séquence 6 ............................................................................................. 159
Conseils généraux
Dès la fin de l’exercice 1, je vous invite à tester les requêtes du cours ainsi que les vôtres
directement sur PostgreSQL grâce à l’outil "Query" de pgAdmin (explication page 9).
tpgAdmin : c’est un outil graphique qui permet d’administrer des bases de données
PostgreSQL. Ce logiciel est livré avec l’installation et ne nécessite pas de pilote sup-
plémentaire pour communiquer avec PostgreSQL.
tFlySpeed SQL Query : ce logiciel permet d’interroger des bases de données en conce-
vant des requêtes graphiquement ou directement en SQL.
tPostgreSQL : c’est le système de gestion de bases de données relationnelles et objets
(SGBDRO). C’est le logiciel "serveur" qui stocke les bases de données.
Il est important pour vous de bien connaître le rôle de chaque logiciel que vous utilisez.
En effet, lors d’un oral, il est toujours mal perçu de dire que vous avez utilisé pgAdmin
comme SGBDR… N’oubliez pas que pgAdmin est juste une interface d’administration
du "SGBDR PostgreSQL".
8 2943 TG PA 00
Séquence 1
Exercice 1
On va donc poursuivre la création de nos tables. Soit on les crée dans l’ordre, qui permet
de respecter les contraintes d’intégrités (fonctionnelles et référentielles), soit on les créer
dans n’importe quel l’ordre, et on déclare les clés étrangères ensuite.
N’oubliez pas que, lorsque vous utilisez un outil d’administration comme pgAdmin, il
faut créer les tables et les colonnes en utilisant uniquement des minuscules.
8 2943 TG PA 00
tDans l’onglet "Colonnes", choisissez "idmarque" dans le menu déroulant "Colonne
locale" et "idmarque" dans le menu déroulant "Référence vers". Cliquez sur le
bouton "Ajouter".
tValidez l’ajout de cette clé en cliquant sur "OK".
8 2943 TG PA 00
tSaisissez le "Nom" de la clé étrangère (fk_lc_article), sélectionnez "article" dans le
menu déroulant "Références".
tDans l’onglet "Colonnes" choisissez "idarticle" dans le menu déroulant "Colonne
locale" et "idarticle" dans le menu déroulant "Référence vers". Cliquez sur le bou-
ton "Ajouter".
tValidez l’ajout de cette clé en cliquant sur "OK".
tCliquez avec le bouton droit sur "Contraintes", choisissez dans le menu contextuel
"Ajouter un objet" puis "Ajouter une clé étrangère".
tSaisissez le "Nom" de la clé étrangère (fk_lc_achat), sélectionnez "achat" dans le
menu déroulant "Références".
tDans l’onglet "Colonnes", choisissez "idachat" dans le menu déroulant "Colonne
locale" et "idachat" dans le menu déroulant "Référence vers". Cliquez sur le bou-
ton "Ajouter".
tValidez l’ajout de cette clé en cliquant sur "OK".
8 2943 TG PA 00
tSaisissez le "Nom" de la colonne (numerotelephone), le "Type de données" (charac-
ter varying) et validez par "OK".
tCliquez de nouveau sur "Ajouter".
tSaisissez le "Nom" de la colonne (distancekm), le "Type de données" (numeric), la
"Longueur" (4), la "Précision" (1) et validez par "OK".
tAllez maintenant dans l’onglet "Contraintes", choisissez "Clé primaire" dans le
menu déroulant et cliquez sur le bouton "Ajouter".
tSaisissez le "Nom" de la clé primaire (pk_fournisseur), dans l’onglet "Colonnes" choi-
sissez "idfournisseur" dans le menu déroulant et cliquez sur le bouton "Ajouter".
tValidez l’ajout de cette clé en cliquant sur "OK".
tValidez l’ajout de cette table en cliquant à nouveau sur "OK".
8 2943 TG PA 00
tChoisissez "Clé étrangère" dans le menu déroulant et cliquez sur le bouton
"Ajouter".
tSaisissez le "Nom" de la clé étrangère (fk_fournisseur), sélectionnez "fournisseur"
dans le menu déroulant "Références".
tDans l’onglet "Colonnes", choisissez "idfournisseur" dans le menu déroulant
"Colonne locale" et "idfournisseur" dans le menu déroulant "Référence vers".
Cliquez sur le bouton "Ajouter".
tValidez l’ajout de cette clé en cliquant sur "OK".
tValidez l’ajout de cette table en cliquant à nouveau sur "OK".
Page 138
8 2943 TG PA 00
Séquence 2
Exercice 1
tLa liste des fournisseurs ("n°F" doit apparaître à la place de "idFournisseur" et
"Nom" à la place de "raisonSociale":
SELECT idFournisseur AS "n°F", raisonSociale AS "Nom",
adresseRue, adresseCP, adresseVille, email,
numeroTelephone, distanceKm
FROM fournisseur
tLa liste des références d’articles qui ont déjà été sur des listes de courses ("Code
barre" doit apparaître à la place de "idArticle") :
SELECT DISTINCT idArticle AS "Code barre"
FROM listeCourses
tLa liste des marques ("m" doit être utilisé comme alias de la table "marque".
Utilisez également le préfixage des champs) :
SELECT m.idMarque, m.nom
FROM marque AS m
tLa liste des achats :
– "N°" doit apparaître à la place de "idAchat", "Date" à la place de "date
Achat" et "Prix à payer" à la place de "montantTotal".
– Utilisez "a" comme alias de la table "achat". Corrigé des exercices
– Utilisez le préfixage des champs :
SELECT a.idAchat AS "N°", a.dateAchat AS "Date", Page 139
a.montantTotal AS "Prix à payer"
FROM achat AS a
Exercice 2
tLa liste des fournisseurs dont la distance est de moins de 100 km :
SELECT *
FROM fournisseur
WHERE distanceKm < 100
tLa liste des fournisseurs qui se situent à plus de 10 km mais à moins de 100 km :
SELECT *
FROM fournisseur
WHERE distanceKm > 10
AND distanceKm < 100
Vous avez peut être été tentés d’écrire la requête avec "BETWEEN":
SELECT *
FROM fournisseur
WHERE distanceKm BETWEEN 10 AND 100
8 2943 TG PA 00
Attention, cette version n’est pas correcte. Rappelons-nous bien : "BETWEEN" inclut les
bornes dans l’intervalle, ce qui veut dire qu’il faut utiliser "10.1" et "99.9" (précision de 1
décimale lors de la création du champ distanceKm) pour qu’elle réponde à notre besoin :
SELECT *
FROM fournisseur
WHERE distanceKm BETWEEN 10.1 AND 99.9
tLa liste des fournisseurs ayant une adresse email chez "orange.fr":
SELECT *
FROM fournisseur
WHERE email LIKE '%@orange.fr'
N’oublions pas que lorsque, l’on utilise "LIKE", il faut absolument utiliser un caractère
"joker".
tLa liste des lots fabriqués avant le 23 mars 2010 et qui ont été livrés entre le 24 et
le 26 mars :
SELECT *
FROM lot
WHERE datefabrication < '23/03/2010'
AND datelivraison BETWEEN '24/03/2010'
AND '26/03/2010'
tLa liste des articles du rayon n° 12 dont le packaging ou l'unité de mesure n’a pas
Corrigé des exercices été renseigné :
SELECT *
Page 140
FROM article
WHERE ( packaging IS NULL OR unitemesure IS NULL )
AND idRayon = 12
Rappel : on ne peut pas écrire "= NULL" parce que NULL n’est pas " égal à " NULL
(la valeur NULL représente une valeur inconnue et il est impossible de dire si 2 valeurs
inconnues sont égales).
tLa liste des articles dont le packaging est "Par 3", "Par 6" ou "Par 12":
SELECT *
FROM article
WHERE packaging IN ('Par 3','Par 6','Par 12')
8 2943 TG PA 00
Exercice 3
tLa liste des articles ("idArticle", "libelle", "prix" que l’on renomme en "prix en €")
avec, en plus, les prix en livres sterling (on prend comme taux de change : 1 £ =
1,21 €) :
SELECT idArticle, libelle,
prix AS "Prix en €",
prix/1.21 AS "Prix en £"
FROM article
Cet exemple nous montre encore une fois la facilité avec laquelle on peut utiliser des
opérateurs mathématiques directement dans ce qu’on veut afficher.
On peut également utiliser la fonction "EXTRACT" (rapidement abordée dans le cours) Corrigé des exercices
permettant d’isoler les composantes d’une date :
SELECT SUM(montantTotal) AS "CA avril 2010" Page 141
FROM achat
WHERE EXTRACT(MONTH FROM dateAchat) = 4
AND EXTRACT(YEAR FROM dateAchat) = 2010
8 2943 TG PA 00
tLe prix moyen au kilo des articles dont l’unité de mesure est le gramme :
SELECT AVG(prix/quantite)*1000 AS "Prix moyen au Kg"
FROM article
WHERE uniteMesure='g'
Exercice 4
tLa liste des articles (références et libellés) qui ont été achetés :
SELECT DISTINCT lc.idArticle, libelle
FROM listeCourses AS lc, article AS a
WHERE lc.idArticle = a.idArticle
Cet exemple utilise la jointure "classique" qui est de moins en moins utilisée. Mémorisez-
la bien tout de même car il arrive encore qu’elle apparaîsse dans des sujets d’examen.
Mais, maintenant que l’on sait utiliser l’opérateur "JOIN" offert par SQL-92, il faut
l’utiliser :
SELECT DISTINCT lc.idArticle, libelle
FROM listeCourses AS lc JOIN article AS a
USING (idArticle)
Rappel : le mot-clé "AS" est facultatif, on peut donc écrire notre requête sans ce dernier :
SELECT DISTINCT lc.idArticle, libelle
FROM listeCourses lc JOIN article a
USING (idArticle)
tLa liste des articles (références et libellés) qui ont été achetés avec la date à laquelle
Corrigé des exercices
ils ont été achetés :
Lorsque l’on utilise des alias de tables, c’est parce qu’on va être amené à les utiliser.
Ici, il est inutile de créer un alias de "marque" car on ne l’utilisera pas, contrairement
aux alias de "article" et de "rayon".
tLa liste des articles (références, libellés et prix) avec le nom de la marque de
l’article et le libellé du rayon d’appartenance qui ont été achetés, ainsi que la date
à laquelle ils ont été achetés :
8 2943 TG PA 00
SELECT lc.idArticle, a.libelle, prix, nom, r.libelle,
dateAchat
FROM article a JOIN marque USING (idMarque)
JOIN rayon r USING (idRayon)
JOIN listeCourses lc USING (idArticle)
JOIN achat USING (idAchat)
Gardez bien à l’esprit que l’on peut mélanger à loisir différents types de jointures. Il
est évident que, dans une même requête, on peut trouver tous les types de jointures, à
condition, bien sûr, que cela soit justifié et cohérent.
tReprenez la requête précédente et utilisez des alias de champs pour chaque champ
utilisé :
– idArticle Î "Référence"; – nom Î "Marque";
– libelle Î "Produit"; – libelle Î "Rayon";
Corrigé des exercices
– prix Î "P.U"; – dateAchat Î "Date".
Page 143
SELECT lc.idArticle AS "Référence",
a.libelle AS "Produit",
prix AS "P.U",
nom AS "Marque",
r.libelle AS "Rayon",
dateAchat AS "Date"
FROM article a JOIN marque USING (idMarque)
JOIN rayon r USING (idRayon)
JOIN listeCourses lc USING (idArticle)
JOIN achat USING (idAchat)
Comme pour la déclaration d’un alias de table, le "AS" permettant de déclarer un alias
de colonne est également facultatif, ce qui veut dire que l’on peut écrire notre requête
de la manière ci-dessous. En règle générale, bien que facultatif, essayez toujours de le
mettre à l’écrit, certains correcteurs d’examen y étant très attachés :
8 2943 TG PA 00
SELECT lc.idArticle "Référence",
a.libelle "Produit",
prix "P.U",
nom "Marque",
r.libelle "Rayon",
dateAchat "Date"
FROM ...
tLa liste des fournisseurs qui n’ont pas encore effectué de livraison :
SELECT DISTINCT f.*
FROM fournisseur f LEFT JOIN lot USING (idFournisseur)
WHERE lot.idFournisseur IS NULL
La jointure gauche nous permet de conserver les lignes de la table de gauche qui n’ont
pas de lignes équivalentes dans la table de droite.
Bien que peut abordée, j’imagine que vous avez bien compris ce que signifiait la nota-
tion "nomTable.*" : cela signifie simplement tous les champs de la table "nomTable".
Si on met uniquement "*", on aura tous les champs, de toutes les tables, ce qui nous
donnera ici tous les champs de "fournisseur" et tous les champs de "lot".
Notons ici que la jointure gauche, peut également être naturelle :
SELECT DISTINCT f.*
FROM fournisseur f NATURAL LEFT JOIN lot
WHERE lot.idFournisseur IS NULL
On peut également ne pas utiliser de jointure avec "NOT IN":
Corrigé des exercices
SELECT *
Page 144 FROM fournisseur
WHERE idFournisseur NOT IN
( SELECT idFournisseur
FROM lot
)
tLa liste des rayons qui n’ont aucun article attribué :
SELECT r.libelle "Rayon sans articles"
FROM article RIGHT JOIN rayon r USING (idRayon)
WHERE idArticle IS NULL
L’utilisation d’une jointure droite nous permet de conserver les lignes de la table de
droite qui n’ont pas de lignes équivalentes dans la table de gauche.
La jointure naturelle, ici, n’est pas possible car il y a le champ "libelle" qui existe dans
les 2 tables et qui n’a rien à voir dans une table et dans l’autre.
Mais, grâce à "NOT IN", si on veut, on peut encore une fois se passer de jointure :
SELECT libelle "Rayon sans articles"
FROM rayon
WHERE idRayon NOT IN ( SELECT idRayon
FROM article
)
8 2943 TG PA 00
Exercice 5
tLa liste des marques par ordre alphabétique :
SELECT *
FROM marque
ORDER BY nom ASC
tLa liste des articles en affichant les articles "bio" en premier :
SELECT *
FROM article
ORDER BY bio DESC
tLa liste des marques avec les articles correspondants. Les noms de marques doivent
être triés par ordre alphabétique inverse et les libellés d’articles par ordre alphabé-
tique :
SELECT nom, libelle
FROM article NATURAL JOIN marque
ORDER BY nom DESC, libelle ASC
tLa liste des lots avec le nom des fournisseurs et le libellé des articles en commençant
par la livraison la plus ancienne. Chaque article sera, lui, trié par ordre alphabé-
tique :
SELECT raisonSociale, dateLivraison, idLot, libelle
FROM fournisseur NATURAL JOIN lot NATURAL JOIN article
ORDER BY dateLivraison DESC, libelle ASC
Corrigé des exercices
8 2943 TG PA 00
Pourquoi, ici, avoir écarté volontairement notre lot de la sélection ? Tout simplement
parce qu’il ne serait pas cohérent de dire que ce lot a été livré le même jour que lui-
même… Il vaut donc mieux l’écarter de notre résultat.
tLa liste des rayons qui ont été approvisionnés à la dernière livraison :
SELECT idRayon, r.libelle, dateLivraison
FROM rayon r JOIN article USING (idRayon)
NATURAL JOIN lot
WHERE dateLivraison = ( SELECT MAX(dateLivraison)
FROM lot )
tLa liste des rayons qui ont été approvisionnés à l’avant-dernière livraison :
SELECT idRayon, r.libelle, dateLivraison
FROM rayon r JOIN article USING (idRayon)
NATURAL JOIN lot
WHERE dateLivraison = ( SELECT MAX(dateLivraison)
FROM lot
WHERE dateLivraison <>
( SELECT MAX(dateLivraison)
FROM lot
)
)
Page 146
Exercice 7
Si on avait utilisé une jointure équivalente, on aurait perdu une information essentielle, à savoir
les rayons vides (Nb. art. = 0).
8 2943 TG PA 00
tLe nombre de lots livrés par fournisseur :
SELECT raisonSociale,
COUNT(*) AS "Nb lots livrés"
FROM fournisseur NATURAL JOIN lot
GROUP BY raisonSociale
tLa liste des articles avec le nombre de fois où ils ont été achetés en affichant les plus
"populaires" en premier :
SELECT article.idArticle AS "Article",
SUM(listeCourses.quantite) AS "Quantité achetée"
FROM article LEFT JOIN listeCourses USING (idArticle)
GROUP BY "Article"
ORDER BY "Quantité achetée" DESC
Avec une jointure gauche, on a également les articles qui n’ont jamais été achetés. Mais
un article acheté 0 fois, peut-on dire qu’il a déjà été acheté ?
Il est clair que non. Il vaut donc mieux, ici, utiliser une jointure équivalente.
Exercice 8
tLe nombre d’articles par achat avec uniquement les achats concernant moins de
5 articles :
SELECT idAchat, COUNT(*) AS "Nb art. achetés"
FROM listeCourses
GROUP BY idAchat
HAVING COUNT(*) < 5
tLe nombre d’articles par rayon avec uniquement les rayons avec 4 articles :
SELECT r.libelle "Rayon avec 4 art."
FROM article RIGHT JOIN rayon r USING (idRayon)
GROUP BY r.libelle
HAVING COUNT(idArticle) = 4
8 2943 TG PA 00
tLe nombre de lots livrés par fournisseur en ne gardant que les fournisseurs qui ont
livré au moins 10 lots :
SELECT raisonSociale,
COUNT(*) AS "Nb lots livrés"
FROM fournisseur NATURAL JOIN lot
GROUP BY raisonSociale
HAVING COUNT(*) >= 10
tLa liste des articles avec le nombre de fois où ils ont été achetés en affichant les
plus "populaires" en premier et en ne conservant que les articles achetés entre 2 et
5 fois :
SELECT article.idArticle AS "Article",
SUM(listeCourses.quantite) AS "Quantité achetée"
FROM article JOIN listeCourses USING (idArticle)
GROUP BY article.idArticle
HAVING SUM(listeCourses.quantite) BETWEEN 2 AND 5
ORDER BY SUM(listeCourses.quantite) DESC
Exercice 9
8 2943 TG PA 00
On peut également faire une soustraction avec "EXCEPT":
SELECT raisonSociale
FROM fournisseur
WHERE idFournisseur IN ( SELECT idFournisseur
FROM fournisseur
EXCEPT
SELECT idFournisseur
FROM lot
)
Ou encore utiliser une jointure gauche, jointure qui, ici, peut également être "naturelle":
SELECT raisonSociale
FROM fournisseur NATURAL LEFT JOIN lot
WHERE idLot IS NULL
Exercice 10
tLa liste des fournisseurs qui ont déjà livré plusieurs lots lors d’une livraison :
SELECT "Fournisseur",
COUNT("Date de livraison") AS "Nb livraisons",
SUM("Nb lots livrés") AS "Nb total lots"
FROM ( SELECT raisonSociale AS "Fournisseur",
dateLivraison AS "Date de livraison",
COUNT(idLot) AS "Nb lots livrés"
FROM fournisseur NATURAL JOIN lot Corrigé des exercices
GROUP BY "Fournisseur", "Date de livraison"
) AS "Sous-requête" Page 149
GROUP BY "Fournisseur"
HAVING COUNT("Date de livraison") <>
SUM("Nb lots livrés")
Bien qu’elle puisse paraître impressionnante, n’oubliez pas qu’une grande requête est
souvent décomposable en requêtes plus petites. N’hésitez donc pas à prendre le temps de
décomposer la requête pour mieux la comprendre.
D’ailleurs, il y a une petite astuce dans l’outil "Query" de pgAdmin : il vous suffit de
mettre en surbrillance une partie de la requête pour n’exécuter que cette partie.
tLe numéro du ou des fournisseurs qui ont effectué le plus de livraisons :
SELECT idFournisseur AS "Fournisseur(s) le + actif"
FROM ( SELECT COUNT(*) AS nbLivraisons, idFournisseur
FROM lot
GROUP BY idFournisseur
) AS req
WHERE nbLivraisons =
( SELECT MAX(nbLivraisons)
FROM ( SELECT COUNT(*) AS nbLivraisons
FROM lot
GROUP BY idFournisseur
) AS req
)
8 2943 TG PA 00
tLe nom du ou des fournisseurs qui ont effectué le plus de livraisons :
SELECT raisonSociale AS "Fournisseur(s) le + actif"
FROM ( SELECT COUNT(*) AS nbLivraisons, raisonSociale
FROM lot NATURAL JOIN fournisseur
GROUP BY raisonSociale
) AS req
WHERE nbLivraisons =
( SELECT MAX(nbLivraisons)
FROM ( SELECT COUNT(*) AS nbLivraisons
FROM lot
GROUP BY idfournisseur
) AS req
)
Il suffisait, ici, d’améliorer une partie de la requête précédente pour pouvoir aller chercher
le champ "raisonSociale" dans la table fournisseur.
Petit à petit, on est capable de faire croître une requête. Vous devez maintenant vous
rendre compte que les "grandes" requêtes ne sont pas si impressionnantes que ça.
Page 150
8 2943 TG PA 00
Séquence 3
Exercice 1
tInsertion du nouveau fournisseur n°12 "Zap 83", se situant au "916 rue Pourquoi
pas" à Toulon (83000) soit à 4,2 km :
INSERT INTO fournisseur (idFournisseur, raisonSociale,
adresseRue, adresseCP,
adresseVille, distanceKm)
VALUES (12,'Zap 83','916 rue Pourquoi pas','83000',
'Toulon',4.2)
Exercice 2
tIl y a une promotion, tous les articles du rayon "Surgelés" baissent de 10% :
UPDATE article
SET prix = prix * 0.9
WHERE idRayon IN ( SELECT idRayon
FROM rayon
WHERE libelle = 'Surgelés'
)
29. La table "nouveauxArticles" n’existant pas dans notre base, la requête ne pourra pas être testée avec
pgAdmin.
8 2943 TG PA 00
tUne autre promotion réduit le prix de tous les articles de la marque "Bonduil" de
1€ :
UPDATE article
SET prix = prix - 1
WHERE idMarque IN ( SELECT idMarque
FROM marque
WHERE nom = 'Bonduil'
)
tUne personne rapporte un paquet de "glaces chocolat en cornets" et désire qu’on
lui reprenne contre remboursement (ticket de caisse n° 1) :
UPDATE listeCourses
SET quantite = quantite - 1
WHERE idAchat = 1
AND idArticle = ( SELECT idArticle
FROM article
WHERE libelle =
'Glaces chocolat en cornets'
)
On a mis à jour la table "listeCourses", mais il ne faut pas oublier de mettre à jour le
montant total de l’achat correspondant. Encore une fois, il faut toujours bien garder à
l’esprit le contexte dans lequel on travaille pour être sûr de ne rien oublier :
UPDATE achat
SET montantTotal = montantTotal –
Corrigé des exercices
( SELECT prix
Page 152
FROM article
WHERE libelle =
'Glaces chocolat en cornets'
)
WHERE idAchat = 1
8 2943 TG PA 00
Séquence 4
Exercice 1
Attention à l’ordre de création des tables. Par exemple, on ne peut pas créer la table
"article" avant les tables "rayon" et "marque". On verra plus tard qu’on peut créer les
tables dans n’importe quel ordre en ajoutant les contraintes après les créations, mais
nous n’y sommes pas encore.
tCréation 30 de la table "rayon" :
CREATE TABLE "rayon"
(
idRayon numeric(2) NOT NULL,
libelle character varying,
CONSTRAINT pk_rayon PRIMARY KEY(idRayon)
)
tCréation de la table "marque" :
CREATE TABLE marque
(
idMarque numeric(3) NOT NULL,
nom character varying,
CONSTRAINT pk_marque PRIMARY KEY(idMarque)
)
Corrigé des exercices
tCréation de la table "article" :
CREATE TABLE "article" Page 153
(
idArticle numeric(13) NOT NULL,
libelle character varying,
prix numeric(6,2),
packaging character varying,
uniteMesure character varying,
quantite numeric(8,3),
bio boolean,
idRayon numeric(2) NOT NULL,
idMarque numeric(3) NOT NULL,
CONSTRAINT pk_article PRIMARY KEY(idArticle),
CONSTRAINT fk_rayon FOREIGN KEY (idRayon)
REFERENCES rayon (idRayon),
CONSTRAINT fk_marque FOREIGN KEY (idMarque)
REFERENCES marque (idMarque)
)
30. Attention, les tables étant déjà créées, vous ne pourrez pas tester ces requêtes via pgAdmin.
8 2943 TG PA 00
Exercice 2
Exercice 3
Page 154
31. La table "nouveauxArticles" n’existant pas dans notre base, la requête ne pourra pas être testée avec
pgAdmin.
8 2943 TG PA 00
Séquence 5
Dans ce domaine, les questions sont généralement simplistes. Ce qui pose le plus de dif-
ficultés réside bien dans la compréhension du sujet et des questions posées. Veillez donc
bien à relire plusieurs fois les questions posées afin de faire au mieux ce qui est demandé.
Exercice 1
t2 vendeurs, "Alice" et "Bernard", qui doivent pouvoir prendre en compte des com-
mandes de meubles par des clients.
– On commence par créer les rôles :
CREATE ROLE alice
LOGIN PASSWORD 'motdepassealice'
CREATE ROLE bernard
LOGIN PASSWORD 'motdepassebernard'
CREATE ROLE vendeur
8 2943 TG PA 00
CREATE ROLE ltatouille
LOGIN PASSWORD 'motdepasseltatouille'
CREATE ROLE compta
Exercice 2
GRANT SELECT
ON intervention
TO PUBLIC
Corrigé des exercices
GRANT INSERT, DELETE, UPDATE
ON intervention
Page 156
TO RDeltour
Exercice 3
tOn commence par supprimer tous les anciens droits de "redact" sur la table
"numero":
REVOKE ALL
ON numero
FROM redact
tOn lui donne ensuite les droits de suppression, d’insertion, de consultation et de
mise à jour sur la table "numero":
GRANT DELETE, INSERT, SELECT, UPDATE
ON numero
TO redact
tOn retire ensuite tous les anciens droits de "redact" sur la table "vente":
REVOKE ALL
ON vente
FROM redact
8 2943 TG PA 00
tOn donne ensuite uniquement le droit de consultation à "redact" sur la table
"vente":
GRANT SELECT
ON vente
TO redact
L’ordre suivant est accepté bien que cet ordre ne soit pas strictement équivalent à l’énu-
mération des 4 permissions :
GRANT ALL
ON numero
TO redact
En effet, "ALL" inclut également la permission "REFERENCES", moins usitée que les
4 autres. Dans la plupart des SGBDR, on rencontre également les permissions ALTER et
INDEX pour une table.
L’ordre suivant était pénalisé :
REVOKE ALL
ON numero, vente
TO redact
Une des particularités des ordres "GRANT" et "REVOKE" étant que l’attribution et le
retrait de permission portent sur un seul objet.
8 2943 TG PA 00
On considère que la secrétaire "Monique" ne possède aucun droit au départ sur les tables
(en tant que nouvelle employée). Dans le cas contraire, il aurait fallu utiliser au préa-
lable la requête "REVOKE" pour lui supprimer tous les droits qu’elle pouvait posséder
sur toutes les tables.
L’absence de la clause "WITH GRANT OPTION" pour la dernière instruction est péna-
lisée.
Exercice 5
tBien que 4 instructions soient acceptées, on pouvait tout faire avec une seule :
GRANT SELECT, INSERT, UPDATE, DELETE
ON salarié
TO duparc
Page 158
8 2943 TG PA 00
Séquence 6
Exercice 1
A. La ligne ('980045', 2006, 'avril', '02/04/2006', NULL, NULL) est ajoutée dans la table
"dossiermensuel". En revanche, aucune ligne ne sera ajoutée dans la table "notede-
frais"; en effet, seule l’instruction validée par le premier commit est effective.
B. Dans le dossier, on précise que "Un dossier mensuel de notes de frais est alors créé par
intervenant lors de la saisie de la première note de frais du mois pour l’intervenant" et,
sur le schéma conceptuel des données, le rôle joué par l’entité "dossiermensuel" dans
l’association "comporte" possède une cardinalité minimale égale à 1 : pour un dossier,
il y a toujours au moins une note de frais ; c’est cette règle de gestion qui ne sera donc
pas respectée.
C. Gérer une seule transaction : elle débutera avant l’insertion du dossier mensuel et
sera validée après l’insertion de toutes les notes de frais. Il faut donc supprimer les ins-
tructions "COMMIT" et "BEGIN" se trouvant après l’insertion de la ligne dans "dossier".
8 2943 TG PA 00