0% ont trouvé ce document utile (0 vote)
11 vues64 pages

Introduction au langage SQL et Access

Transféré par

louistshialu0
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats DOC, PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
11 vues64 pages

Introduction au langage SQL et Access

Transféré par

louistshialu0
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats DOC, PDF, TXT ou lisez en ligne sur Scribd

1

SQL

Les bases de données


relationnelles
Chapitre 1 : les tables en SQL
1 - Introduction à SQL
Le sigle SQL signifie "Structured Query Language", soit en français "Langage
de recherche structuré". SQL est un langage de gestion des bases de données relationnelles
que presque tous les SGBD comprennent. Il a été développé par IBM dans le courant des
années 70, et son nom actuel (il s'appelait initialement SEQUEL) date du début des années 80.

SQL a été normalisé par l'ANSI (American National Standards Institute) et par
l'ISO (International Organization for Standardization). Voici les principales étapes de ce
processus :
première norme ANSI en 1986 ;
première norme ISO (SQL1) en 1987, révisée en 1989 ;
deuxième norme ISO (SQL2) en 1992 ;
troisième norme (SQL3) en cours de rédaction depuis 1999 par l'ANSI et l'ISO, après
une très longue gestation, et avec beaucoup de retard sur l'événement.

Malgré la normalisation ISO, l'implémentation du SQL par les différents


éditeurs de SGBD comporte des différences plus ou moins marquées concernant :
les détails de la syntaxe ;
l'écriture des commandes ;
le fonctionnement exact des commandes ;
l'implémentation de nouveaux types de données (images, animations, vidéos, liens
hypertexte, etc.).

Bref, il n'y a qu'un seul langage SQL, mais chaque éditeur de SGBD
implémente son propre dialecte. Le "dictionnaire" qui permet de passer d'un dialecte à l'autre
s'appelle ODBC (Open Data Base Connectivity). Il a été imaginé par Microsoft, et mis sur le
marché en 1993.
Contrairement à ce que son nom indique, SQL ne sert pas qu'à écrire des
requêtes. C'est un langage complet, qui permet de créer des BDD, des tables, de saisir des
données et de les corriger, de créer des vues, des index et des états (parfois baptisés
"rapports", par francisation de l'anglais "reports"). Sauf erreur de notre part, il ne permet pas
de créer des formulaires, parce qu'il a été conçu à une époque ou l'interface graphique
n'existait pas sur ordinateur, et parce qu'un formulaire sans interface graphique n'a guère
d'intérêt.
Par contre, dans les SGBD sans interface graphique, le recours à SQL est
obligatoire pour toutes les opérations, y compris la création de la BDD, celle des tables, et la
saisie des données. La tentation est donc forte, pour un professeur qui ignore à quels SGBD
ses étudiants seront confrontés lorsqu'ils entreront dans la vie active, de faire dans son
enseignement une large part à SQL, qui représente l'outil universel de manipulation des
données. Ceci dit, l'interface graphique est tellement entrée dans les moeurs, qu'il parait
difficile qu'à terme tous les SGBD n'en soient pas dotés. En attendant, nous avons adopté une

© TIBB imbwangatroptard@[Link]
2
SQL
position mixte, en commençant par l'interface graphique, plus facile à appréhender, et en
rajoutant à ce tutoriel quatre chapitres consacrés au langage SQL.
Selon notre habitude, nous utiliserons le SGBD Access comme support pratique
de ce tutoriel (ou tutorial, ou cours en ligne). A l'occasion, nous comparerons
l'implémentation du SQL d'Access à celle d'Oracle. Comme nous ne disposons pas d'une base
Oracle (nos moyens ne nous le permettent pas...), nous nous inspirerons d'un manuel de
formation à la version 8 (l'avant-dernière).

2 - Le langage SQL dans Access


Dans Access, le langage SQL est utilisé par le moteur du SGBD pour traduire en
commandes exécutables les instructions que donne l'utilisateur à travers l'interface graphique.
Mais l'utilisateur n'a pas accès à ce code, sauf pour la conception des requêtes, où il peut
passer facilement du mode graphique au mode SQL et vice versa. Nous utiliserons largement
cette possibilité dans les trois chapitres suivants.
Pour les tables, la situation est nettement moins satisfaisante. L'utilisateur qui se
sert de l'interface graphique pour créer une table n'a pas accès au code SQL correspondant.
Par contre, il dispose d'un éditeur de SQL qui reconnaît les principales commandes
concernant la création et la modification des tables, et la saisie des données.
Cet éditeur, cependant, ne doit pas faire illusion, car il est loin d'être complet. Il
ne permet pas de régler dans le détail les propriétés des champs, comme on peut le faire dans
l'interface graphique. Il ne permet pas non plus de créer des listes. Il rend donc des services
limités. Il présente cependant de l'intérêt dans les deux cas suivants :
l'apprentissage initial du SQL, pour lequel il n'est pas utile d'entrer immédiatement
dans les moindres détails ;
l'automatisation (via les macros) de certaines opérations relatives aux tables. En effet,
le code SQL que nous allons écrire sera enregistré sous forme de requête par le SGBD, et il
est très facile de lancer une requête à partir d'une macro.

Évidemment, il est beaucoup plus facile de créer, remplir, modifier, et supprimer


une table dans l'interface graphique d'Access qu'en utilisant des commandes SQL. Mais tous
les SGBD ne sont pas dotés d'une interface graphique, et il est bon de savoir se débrouiller
sans elle le cas échéant.

3 - La procédure
Pour gérer les tables en langage SQL dans Access, il nous faut opérer de la
manière suivante. Dans la fenêtre "Base de données", nous sélectionnons l'objet
"Requêtes". Nous effectuons un double clic sur "Créer une requête en mode création", nous
refermons la fenêtre "Afficher la table" sans introduire de table et, dans le menu, nous suivons
le chemin suivant :
Requête --> Spécifique SQL --> Définition des données
S'ouvre alors une fenêtre intitulée "Requête1 : Requête Définition des données",
dans laquelle nous pouvons écrire du code SQL.
Pour exécuter ce code, nous cliquons sur l'icône "Exécuter". Pour l'enregistrer,
nous cliquons sur "Enregistrer". Nous constatons alors que le SGBD Access traite notre
code comme une requête.

© TIBB imbwangatroptard@[Link]
3
SQL
Pour modifier le code SQL, nous sélectionnons la requête enregistrée
précédemment, et nous cliquons sur l'icône "Modifier". La fenêtre "Requête Définition des
données" s'ouvre à nouveau.
Tous les exemples cités dans ce chapitre ont été transportés (par copier/coller)
dans Access 2002, et nous avons vérifié leur bon fonctionnement. Vous ne devriez donc pas
rencontrer de difficulté pour les reproduire.

4 - La création et la suppression d'une table


Dans la fenêtre ouverte grâce à la procédure précédente, nous écrivons notre
première commande (ou instruction) SQL, contenant la clause CREATE TABLE, pour créer
la table "Personnes" (nous notons qu'un point-virgule marque la fin de la commande) :
CREATE TABLE Personnes
(Nom CHAR(20),
Prénom CHAR(20));

Nous exécutons cette commande en cliquant sur l'icône "Exécuter". Le fait


qu'aucun message ne soit émis signifie que tout s'est bien passé. Nous sélectionnons l'objet
"Table", et nous constatons que :
la table "Personnes" est effectivement créée ;
qu'elle possède deux champs de type texte (de 20 caractères au maximum) ;
qu'ils sont intitulés "Nom" et "Prénom".

Si nous enregistrons cette commande en cliquant sur l'icône "Enregistrer", le


SGBD Access la traite comme une requête. Devant son nom, il place une icône particulière (
, à ne pas confondre avec l'icône "Modifier") pour rappeler qu'il s'agit d'une commande
SQL liée à la manipulation des tables.
Bien entendu, si nous n'exécutons pas la requête, la table "Personnes" ne sera
pas créée. Par contre, si la table "Personnes" existe déjà, la commande ne s'exécute pas (la
table existante n'est pas écrasée), et le SGBD affiche le message suivant :

Attention ! Si l'objet "Table" est sélectionné quand vous lancez l'exécution de la


commande SQL, la table "Personnes" n'apparaîtra pas (c'est l'éternel problème de la
synchronisation dans Access). Il suffit de cliquer, dans le menu, sur "Affichage", puis sur
"Actualiser", pour que le nom de la table apparaisse.
Les commandes SQL s'expriment en format libre. Nous pouvons écrire les
clauses en minuscules, et nous ne sommes pas tenus d'aller à la ligne pour détailler les
champs. Bien que la précédente présentation (sur trois lignes) soit considérée comme plus
lisible, l'expression suivante est parfaitement exacte et s'exécute normalement :

© TIBB imbwangatroptard@[Link]
4
SQL
create table Personnes (Nom char(20),Prénom char(20));

Les conventions relatives aux noms des tables et des champs varient quelque
peu d'un SGBD à l'autre. En ce qui concerne plus particulièrement les champs :
le nombre de
caractères ne doit pas être trop grand (64 dans Access, 18 à 30 dans d'autres SGBD) ;
seuls les lettres, les nombres et le caractère de soulignement sont autorisés. Access
admet les caractères accentués. Il admet aussi l'espace, mais le nom du champ doit alors être
écrit entre crochets ;
certains SGBD requièrent que le nom d'un champ commence par une lettre, mais ce
n'est pas le cas d'Access ;
les termes faisant partie du vocabulaire du langage SQL sont interdits ("date" par
exemple). Ce sont les mots réservés.

Les types de données sont définis dans le DDL (Data Definition Language) de
chaque SGBD, et ils varient beaucoup d'un logiciel à l'autre. Dans Access, les mêmes termes
ne sont pas toujours utilisés dans l'interface graphique, en VBA et en SQL. Voici un
échantillon représentatif des différentes façons d'exprimer un type de données lors de la
création d'une table en SQL dans Access :
Booléen : BIT ;
Nombre entier : SHORT (entier), SMALLINT (entier), LONG (entier long),
INTEGER (entier long), BYTE (octet) ;
Nombre réel : SINGLE (réel simple), DOUBLE (réel double), NUMERIC (réel
double) ;
Monétaire : CURRENCY, MONEY ;
Date/Heure : DATE, TIME, DATETIME ;
Texte : VARCHAR (255 caractères), CHAR(n) ou TEXT(n) (n caractères),
LONGTEXT (mémo, 32K max.) ;
Fichier binaire : LONGBINARY (Objet OLE) ;
Compteur : COUNTER (NuméroAuto).

On notera qu'il n'est pas possible de créer un champ de type hypertexte via une
commande SQL dans Access. Même remarque en ce qui concerne les listes de choix.
Pour supprimer une table, on utilise la clause DROP TABLE, comme le montre
l'exemple suivant :
DROP TABLE Personnes;

Attention ! Si l'objet "Table" est sélectionné dans la fenêtre "Base de données"


quand vous lancez l'exécution de la commande SQL de suppression, la table "Personnes" ne
disparaîtra pas (c'est l'éternel problème de la synchronisation dans Access). Il suffit de cliquer,
dans le menu, sur "Affichage", puis sur "Actualiser", pour que le nom de la table disparaisse.
Si nous enregistrons la commande de suppression de table, Access place devant
son nom l'icône spécifique des requêtes SQL liées à la création de tables.

5 - La modification d'une table

© TIBB imbwangatroptard@[Link]
5
SQL
Il est possible de modifier une table existante. Les exemples les plus classiques
concernent l'addition d'une nouvelle colonne et la suppression d'une colonne existante. La
commande :
ALTER TABLE Personnes
ADD Naissance DATE;

permet, lorsqu'on l'exécute, d'ajouter le champ intitulé "Naissance", de type


Date/Heure, à la table "Personnes". La variante suivante fonctionne également :
ALTER TABLE Personnes
ADD COLUMN Naissance DATE;

La clause INIT, qui permet de donner une valeur initiale aux champs ainsi créés,
ne fonctionne pas dans Access. Par défaut, cette valeur initiale est Null. Pour la modifier, il
faut utiliser une commande UPDATE (dont nous parlerons au paragraphe 9 ci-dessous).
Pour supprimer la colonne que nous venons de créer, nous utilisons la
commande suivante :
ALTER TABLE Personnes
DROP Naissance;

ou sa variante :
ALTER TABLE Personnes
DROP COLUMN Naissance;

En SQL standard, la commande ALTER TABLE peut aussi être utilisée pour
modifier les propriétés d'une colonne existante. Exemple :
ALTER TABLE Personnes
MODIFY Nom CHAR(40);

mais la clause MODIFY n'est pas reconnue par Access, et l'exécution de la


commande ci-dessus entraîne un message d'erreur. L'ignorance de la clause MODIFY enlève
à la commande ALTER TABLE une bonne partie de son intérêt dans Access, et l'on se
demande pourquoi l'éditeur a fait les choses à moitié.
Nous verrons cependant au paragraphe 8 que la commande ALTER TABLE
admet la clause ADD CONSTRAINT, ce qui permet de rajouter une clé ou de créer une
relation.

6 - Les propriétés des champs


Le langage SQL est doté de clauses permettant de définir les propriétés des
champs lors de la création d'une table. Mais le moteur d'Access ne les reconnaît pas toutes,
loin de là.
Pour empêcher un champ de rester vide, nous utilisons la clause NOT NULL,
comme le montre l'exemple suivant :
CREATE TABLE Personnes
(Nom CHAR(20) NOT NULL,
Prénom CHAR(20));

© TIBB imbwangatroptard@[Link]
6
SQL
Après avoir exécuté la commande nous vérifions, dans le propriétés de la table
"Personnes" ainsi créée, que le Null est interdit dans le champ "Nom".
Pour qu'un champ soit indexé sans doublons, nous utilisons la clause UNIQUE,
comme le montre l'exemple suivant :
CREATE TABLE Personnes
(Nom CHAR(20) UNIQUE,
Prénom CHAR(20));

Après avoir exécuté la commande, nous ouvrons la table "Personnes" en mode


modification, nous cliquons sur le champ "Nom", et nous vérifions que la propriété "Indexé :"
vaut "Oui - Sans doublons". En fait, cette clause possède un intérêt limité pour deux raisons :
nous ne pouvons pas donner de nom à l'index. Ceci nous interdit de supprimer l'index
via une commande SQL ;
nous ne pouvons pas créer d'index multi-champ de cette façon.

Il est donc souvent préférable d'utiliser la commande de création d'index que


nous présenterons au paragraphe suivant.
Pour poser une clé primaire sur un champ, nous utilisons la clause PRIMARY
KEY, comme le montre l'exemple suivant :
CREATE TABLE Personnes
(Nom CHAR(20) PRIMARY KEY,
Prénom CHAR(20));
Après avoir exécuté la commande, nous ouvrons la table "Personnes" en mode
modification, nous cliquons sur le champ "Nom", et nous vérifions qu'il est effectivement doté
de la clé. Cette commande possède les deux mêmes défauts que la précédente : nous ne
sommes pas maîtres du nom de la clé (le système l'appellera Index_976A9AC0_494C_41C1,
par exemple...), et nous ne pouvons pas appliquer la clé à plusieurs champs simultanément. Le
premier défaut peut être corrigé grâce à la commande suivante :
CREATE TABLE Personnes
(Nom CHAR(20) CONSTRAINT clé_primaire PRIMARY KEY,
Prénom CHAR(20));

qui permet d'attribuer le nom "clé_primaire" à la clé ainsi créée. Nous verrons au
paragraphe suivant comment placer une clé sur plusieurs champs.
Les autres clauses permettant de définir les propriétés des champs ne
fonctionnent pas dans Access. Il en est ainsi de DEFAULT, qui permet de fixer la valeur par
défaut d'un champ, ainsi que de CHECK, qui permet de fixer des contraintes sur le contenu
d'un champ (propriété "Valide si").

7 - La clé primaire et l'index


Pour placer une clé primaire sur un champ, nous pouvons utiliser la clause
CONSTRAINT, qui est obligatoirement suivie d'un nom d'index, et que nous avons déjà
rencontrée au paragraphe précédent. Créons, par exemple, la table "Personnes" avec une clé
primaire (intitulée clé_primaire) sur le champ "Nom". La commande s'écrit :
CREATE TABLE Personnes
(Nom CHAR(20) NOT NULL,

© TIBB imbwangatroptard@[Link]
7
SQL
Prénom CHAR(20),
CONSTRAINT clé_primaire PRIMARY KEY(Nom));

L'objet "Table" étant sélectionné, nous cliquons sur l'icône "Index", et la


fenêtre du même nom s'ouvre. Nous vérifions que la clé est bien nommée "clé_primaire",
comme le montre la figure suivante :

Pour appliquer la clé à deux champs, nous utilisons la syntaxe suivante :


CREATE TABLE Personnes
(Nom CHAR(20),
Prénom CHAR(20),
CONSTRAINT essai_index PRIMARY KEY(Nom, Prénom));

La création d'un index peut s'effectuer alors que la table existe déjà, mais cela
requiert l'usage d'une syntaxe différente. Créons par exemple un index sur le champ "Nom" de
la table "Personnes" :
CREATE UNIQUE INDEX essai_index
ON Personnes (Nom);

Dans le cas d'un index sur deux champs, cette syntaxe devient :
CREATE UNIQUE INDEX essai_index
ON Personnes (Nom, Prénom);

Pour supprimer un index, la syntaxe SQL standard s'écrit :


DROP INDEX Personnes.essai_index;

Mais cette syntaxe standard ne fonctionne pas dans Access. Il faut utiliser la
variante suivante :
DROP INDEX essai_index ON Personnes;

8 - La création et la suppression d'une relation


Pour montrer comment on crée une relation 1-n entre deux tables, nous avons
décomposé les opérations en quatre étapes. Dans un premier temps, nous créons la table
"Personnes", avec un champ "Nom", un champ "Prénom", et un champ "Code_Ville" (entier
long), en exécutant la commande suivante :

© TIBB imbwangatroptard@[Link]
8
SQL
CREATE TABLE Personnes
(Nom TEXT(30),
Prénom TEXT(30),
Code_Ville LONG);

Dans un deuxième temps, nous créons la table "Villes", avec un champ


"Code_Ville" (NuméroAuto) et un champ "Ville". Cette table servira de liste externe pour la
table "Personnes". Nous exécutons la commande suivante :
CREATE TABLE Villes
(Code_Ville COUNTER,
Ville TEXT(30));

Dans un troisième temps, nous modifions la table "Villes" en plaçant une clé
primaire sur le champ "Code_Ville", qui servira de côté 1 à la future relation. Pour ce faire,
nous exécutons la commande suivante :
ALTER TABLE Villes
ADD CONSTRAINT clé_primaire PRIMARY KEY(Code_Ville);

Notons que, si nous ne désirons pas donner un nom à la clé (ici "clé_primaire"),
nous pouvons simplifier la commande précédente en l'écrivant ainsi :
ALTER TABLE Villes
ADD PRIMARY KEY(Code_Ville);

Dans un quatrième temps, nous modifions la table "Personnes" en plaçant une


clé étrangère, nommée "relation_ville", sur le champ "Code_Ville" de la table "Personnes"
(on parle de clé étrangère pour le côté n de la relation), en précisant que le côté 1 de la
relation est le champ "Code_Ville" de la table "Villes". Nous exécutons donc la commande
suivante :
ALTER TABLE Personnes
ADD CONSTRAINT relation_ville FOREIGN KEY (Code_Ville) REFERENCES Villes
(Code_Ville);

Notons que :
si nous ne désirons pas donner un nom à la relation (ici "relation_ville"), et
s'il n'y a pas d'ambiguïté sur le champ qui est du côté 1 de la relation (ici "Code_Ville
de la table "Villes")

nous pouvons simplifier la commande précédente en l'écrivant ainsi :


ALTER TABLE Personnes
ADD FOREIGN KEY (Code_Ville) REFERENCES Villes;

Nous vérifions dans la fenêtre "Relations" qu'une relation 1-n a bien été créée
entre les deux tables, avec application de l'intégrité référentielle.
Nous aurions pu être plus directs, en installant les clés (clé primaire et clé
étrangère) dès la création des tables. Pour la table ville, la commande s'écrit :

© TIBB imbwangatroptard@[Link]
9
SQL
CREATE TABLE Villes
(Code_Ville COUNTER PRIMARY KEY,
Ville TEXT(30));

Pour la table "Personnes", la commande s'écrit :


CREATE TABLE Personnes
(Nom TEXT(30),
Prénom TEXT(30),
Code_Ville LONG,
CONSTRAINT relation_ville FOREIGN KEY (Code_Ville) REFERENCES Villes);

Ces deux commandes étant exécutées, nous vérifions dans la fenêtre "Relations"
que les deux tables sont présentes avec tous leurs champs, et liées par une relation 1-n.
La suppression de cette relation s'obtient à l'aide de la commande ALTER
TABLE. Dans le cas de la table "Personnes", côté n de la relation "relation_ville" créée
précédemment, la commande s'écrit :
ALTER TABLE Personnes
DROP CONSTRAINT relation_ville;

On notera que les options "Mettre à jour en cascade les champs correspondants"
et "Supprimer en cascade les enregistrements correspondants" ne sont pas disponibles.
En conclusion, la création et la suppression d'une relation sont réalisées grâce à
la clause CONSTRAINT appliquée à la table située du côté n de la relation.

9 - La saisie et la correction des données


Pour saisir des données dans la table "Personnes", la commande SQL utilise la
clause INSERT INTO. Les données en mode texte doivent être placées entre guillemets.
Exemple :
INSERT INTO Personnes
VALUES
("Machin","Pierre");

Nous vérifions, après exécution de la commande, que Pierre Machin a bien été
introduit dans la table "Personnes". Si nous enregistrons la commande, le SGBD la fait
précéder de l'icône , qui symbolise les requêtes de type "Ajout". Cependant, si nous
essayons de basculer en "Mode création" (le mode graphique), le SGBD Access nous oppose
le message suivant :

En bon français, notre commande ressemble à une requête ajout, elle possède
l'icône d'une requête ajout, elle utilise la clause INSERT comme une requête ajout, mais ce
n'est pas une requête ajout. Qu'on se le dise !
Si le Null n'est pas interdit dans les champs de la table "Personnes", nous
pouvons introduire un nom sans le prénom correspondant, en opérant de la manière suivante :

© TIBB imbwangatroptard@[Link]
10
SQL
INSERT INTO Personnes (Nom)
VALUES
("Truc");

Pour modifier un enregistrement existant, nous faisons appel à la clause


UPDATE (qui signifie "mise à jour" en anglais). Si, par exemple, nous voulons doter M. Truc
de son prénom, nous écrirons :
UPDATE Personnes
SET Prénom="Henri"
WHERE Nom="Truc";

Si nous enregistrons cette commande, le SGBD Access lui attribue l'icône


caractéristique des requêtes de mise à jour. C'en est effectivement une, comme nous pouvons
le constater en basculant en mode graphique. Nous reparlerons de ce type de requête au
chapitre 22.
Pour supprimer une ligne, nous utilisons la commande basée sur la clause
DELETE :
DELETE FROM Personnes
WHERE Nom="Truc";

Lorsque la clause WHERE est absente, le SGBD supprime tous les


enregistrements, laissant la table vide (mais ne la supprimant pas) :
DELETE FROM Personnes;

Si nous enregistrons ces deux commandes, le SGBD Access fait précéder leur
nom de l'icône caractéristique des requêtes suppression. Cependant, si nous créons la
requête suppression correspondante en mode graphique, et si nous basculons en mode SQL,
nous obtenons une syntaxe légèrement différente. Nous reviendrons sur ce point au
chapitre 22.
Dans certaines implémentations du langage SQL (mais pas dans Access), on
peut omettre la clause FROM qui suit la clause DELETE.

10 - Conclusion
La création d'une table en SQL n'est pas une travail bien ardu, même s'il est
certain qu'une bonne interface graphique simplifie fortement l'opération. La saisie des
informations en SQL, par contre, est une tâche quasi désespérante. A moins que les données
ne soient importées, l'usage d'une interface graphique s'impose.
En ce qui concerne les tables, l'interface graphique du SGBD Access est
beaucoup plus développée que son interface SQL. Nous verrons dans les chapitres suivants
que la situation est très différente, et nettement plus équilibrée, pour les requêtes.

Chapitre 2: la sélection simple en SQL


1 - Introduction

© TIBB imbwangatroptard@[Link]
11
SQL
Nous avons vu au chapitre précédent qu'il était possible, dans le SGBD Access,
de manipuler les tables en langage SQL. Cependant, les commandes correspondantes sont
considérées comme des requêtes, et il n'est pas possible de basculer entre le mode graphique
et le mode SQL. En effet, le mode graphique s'obtient lorsque l'objet "Tables" est sélectionné,
alors que le mode SQL requiert que l'objet "Requêtes" soit actif.
En ce qui concerne les requêtes, la situation est nettement plus satisfaisante. La
plupart des commandes SQL relatives aux requêtes sont connues du moteur d'Access, et on
bascule sans problème du mode graphique au mode SQL (l'objet "Requêtes" étant
sélectionné).
Il existe cependant quelques exceptions, que nous étudierons au chapitre 21. Il
s'agit des opérations ensemblistes, pour lesquelles il n'existe pas d'interface graphique. Ces
trois opérations sont :
l'union de deux tables, pour laquelle l'opérateur UNION fonctionne ;
l'intersection de deux tables, pour laquelle l'opérateur INTERSECT ne fonctionne
pas ;
la différence de deux tables, pour laquelle les opérateurs EXCEPT et MINUS ne
fonctionnent pas.

Selon notre habitude, nous utiliserons le SGBD Access comme support pratique
de ce tutoriel (ou tutorial, ou cours en ligne).

2 - La sélection simple
Créons, dans l'interface graphique, la requête qui extrait de la table "Personnes"
(contenant une liste de personnes) les deux champs "Nom" et "Prénom". Cliquons sur la petite
flèche située à droite de l'outil "Affichage", et dans la liste déroulante, choisissons
"Mode SQL". La commande (ou instruction) suivante s'affiche :
SELECT [Link], [Link]énom
FROM Personnes;

La requête simple commence par la clause "SELECT", suivie du nom des


champs, puis continue avec la clause "FROM", suivie du nom de la table à laquelle
appartiennent les champs. Le point-virgule marque la fin de la commande.
La syntaxe relative aux noms des champs consiste à écrire le nom de la table,
suivi d'un point et du nom du champ. Cette façon de procéder s'appelle la qualification. Dans
le cas présent, cette qualification est redondante, et nous pouvons très bien écrire :
SELECT Nom, Prénom FROM Personnes;

La politique la plus raisonnable consiste à qualifier les champs chaque fois


qu'une ambiguïté existe (même nom de champ dans deux tables différentes, lors d'une requête
multi-table), et de ne pas les qualifier dans le cas contraire.
Nous avons vu au chapitre précédent qu'il existait des restrictions sévères sur les
noms des tables et des champs en SQL. Pour s'en affranchir, il faut mettre les noms des
champs, et celui de la table, entre crochets pour éviter les ennuis. Les expressions :
SELECT [Personnes].[Nom], [Personnes].[Prénom] FROM [Personnes];
SELECT [Nom], [Prénom] FROM [Personnes];

© TIBB imbwangatroptard@[Link]
12
SQL
sont parfaitement valables. Par prudence, certains professionnels utilisant les
SGBD préfèrent s'abstenir de tout caractère accentué, remplacent systématiquement l'espace
par le caractère de soulignement, et évitent d'utiliser les termes réservés. Rappelons que
l'implémentation de SQL par Access accepte les caractères accentués pour les noms des
champs et des tables.
Attention aux détails de syntaxe ! Comme tous les langages informatiques, SQL
a ses petites manies qui empoisonnent les utilisateurs. L'interface graphique a ceci de bon
qu'elle nous débarrasse de ces problèmes stupides -- en plus du fait qu'elle nous permet de
créer des requêtes plus simplement et plus rapidement. On notera que, dans Access, le point-
virgule qui marque la fin d'une commande n'est pas indispensable.
3 - La requête avec création de table
Récupérons la requête précédente dans l'interface graphique, faisons en sorte
qu'elle crée une table appelée "Essai", puis basculons en mode SQL. Nous obtenons :
SELECT [Link], [Link]énom INTO Essai
FROM Personnes;

Nous voyons que la création de la table est effectuée grâce à la clause INTO,
suivi du nom de la table. En SQL version Oracle, on écrirait plutôt :
INSERT INTO Essai
SELECT [Link], [Link]énom
FROM Personnes;

Dans Access, cette syntaxe fonctionne à condition que la table "Essai" préexiste,
et contienne au moins les champs "Nom" et "Prénom" avec les mêmes propriétés que dans la
table "Personnes". Access effectue alors une requête ajout des deux premières colonnes de la
table "Personnes" à la table "Essai".

4 - Le tri simple ou multiple


Nous pouvons demander que le résultat de la requête soit trié sur un ou plusieurs
champs. Récupérons la requête précédente dans l'interface graphique, faisons en sorte que le
résultat soit trié sur les noms d'abord, sur les prénoms ensuite, et basculons en mode SQL.
Nous obtenons :
SELECT [Link], [Link]énom
FROM Personnes
ORDER BY [Link], [Link]énom;

Nous voyons que le tri (dans l'ordre croissant) s'obtient grâce à la clause ORDER
BY, suivi des noms des champs. Le tri multiple est effectué dans l'ordre d'énumération des
champs.
Le tri d'un champ dans l'ordre décroissant s'obtient en faisant suivre le nom de ce
champ par l'opérateur DESC. L'exemple suivant effectue un tri croissant sur les noms, suivi
d'un tri décroissant sur les prénoms :
SELECT [Link], [Link]énom
FROM Personnes
ORDER BY [Link], [Link]énom DESC;

© TIBB imbwangatroptard@[Link]
13
SQL
5 - L'élimination des doublons
Comme nous l'avons vu au chapitre 8, la requête simple peut créer des doublons,
et il est possible de remédier de façon simple à cette situation en jouant sur les propriétés de la
requête. Créons dans l'interface graphique une requête de sélection simple qui concerne le
seul champ "Nom" de la table "Personnes". Modifions la propriété "Valeurs distinctes" de
"Non" à "Oui", puis basculons en mode SQL. Nous obtenons :
SELECT DISTINCT [Link]
FROM Personnes;

Nous voyons que l'élimination des doublons s'obtient à l'aide de l'opérateur


DISTINCT placé juste après la clause SELECT. Une syntaxe plus ancienne est également
comprise par Access, mais elle ne semble plus guère utilisée :
SELECT DISTINCT(Nom)
FROM Personnes;

Pour éviter de créer des doublons sur deux champs, la commande SQL s'écrit :
SELECT DISTINCT [Link], [Link]énom
FROM Personnes;

6 - La requête avec création de champ


Reprenons l'exemple déjà traité au chapitre 8, lequel consiste à concaténer le
nom avec le prénom, en les séparant par un espace. Appelons "Nom_complet" le nouveau
champ. En mode SQL, nous obtenons :
SELECT [Nom] & " " & [Prénom] AS Nom_complet
FROM Personnes;

La façon d'extraire le contenu des champs et d'exprimer la concaténation varient


d'un SGBD à l'autre. Cependant, la possibilité de créer un nouveau champ (et d'en définir le
contenu à partir de champs existants) se retrouve dans tous les SGBD dignes de ce nom.

7 - La requête multi-fonctionnelle
En définitive, nous pouvons regrouper toutes les opérations précédentes (requête
simple, création de table, création de champ, tri et élimination des doublons) en une seule
requête, dont voici le code SQL (en version Access) :
SELECT DISTINCT [Nom] & " " & [Prénom] AS Nom_complet INTO Liste_de_noms
FROM Personnes
ORDER BY [Nom] & " " & [Prénom];

8 - Les requêtes emboîtées


Nous avons vu au chapitre 8 qu'il est possible de créer dans Access une requête à
partir du résultat d'une autre requête, à condition que cette dernière ne crée pas de table. En
mode SQL, la commande s'écrit :

© TIBB imbwangatroptard@[Link]
14
SQL
SELECT Requê[Link]
FROM Requête1;

On ne peut pas rêver plus simple pour emboîter deux requêtes ! Cette belle
simplicité ne se retrouve pas en SQL pur et dur, où l'emboîtement de deux requêtes est d'une
écriture plutôt complexe. Que l'on en juge :
si la première requête (encore appelée sous-requête, ou sous-interrogation) ramène
une valeur numérique unique (résultat d'une opération du type comptage, sommation, calcul
de moyenne, etc.), on utilise les opérateurs arithmétiques usuels : =, <, >, >=, <= et <> ;
si la première requête ramène une seule ligne, on utilise les opérateurs IN, ALL, ou
ANY suivant les cas ;
si la première requête est susceptible de ramener plusieurs lignes, on utilise EXISTS
ou NON EXISTS.

Bonjour les erreurs !

9 - Conclusion
Le chapitre 11 est consacré à la sélection simple, mise en oeuvre à l'aide de
l'interface graphique d'Access. Le présent chapitre 19 suit pratiquement le même plan, mais
utilise le langage SQL. La comparaison entre ces deux chapitres nous amène à faire une
double constatation :
le langage SQL est d'un usage assez facile, sauf en ce qui concerne l'emboîtement des
requêtes. Pour réaliser l'emboîtement, l'utilisation de l'interface graphique d'Access est
beaucoup plus simple. Cette situation résulte du fait que le SQL mis en oeuvre par Access
permet d'évoquer une requête par son nom, ce qui n'est pas le cas du SQL usuel ;
Access fournit un moyen didactique commode pour aborder l'étude du langage SQL.

© TIBB imbwangatroptard@[Link]
15
SQL

Les bases de données


relationnelles
Chapitre 20 : la sélection en SQL
1 - Introduction
Nous connaissons désormais l'allure des commandes SQL, dans le cadre de la
sélection simple. Il est temps que nous abordions :
la sélection avec un ou plusieurs critères s'appliquant à un ou plusieurs champs ;
la sélection multi-table, avec les jointures ;
le regroupement.

Comme pour les autres chapitres, nous utilisons le SGBD Access comme
support pratique de ce tutoriel (ou tutorial, ou cours en ligne).
Chaque fois que cela sera possible, nous ferons écrire le code SQL par le SGBD,
en partant de l'interface graphique de définition des requêtes avant de basculer en mode SQL.

2 - La sélection en SQL
La sélection permet d'extraire d'une table (ou de plusieurs tables liées par des
relations) les enregistrements répondant à un ou plusieurs critères. Notons au passage qu'un
critère peut aussi être appelé une condition. Rappelons que l'ensemble des critères définit un
filtre.
A titre de premier exemple, cherchons dans la table "Personnes" (qui contient
des noms, des prénoms, des adresses, etc.) les personnes dont le nom commence par la lettre
"c" (majuscule ou minuscule, la casse n'importe pas). Dans la grille de création de la requête,
nous exprimons la condition sous la forme :
Comme "c*"
Si nous basculons en mode SQL, nous obtenons le code suivant :
SELECT [Link], [Link]énom
FROM Personnes
WHERE ((([Link]) Like "c*"));

Nous voyons que la condition s'exprime à l'aide de la clause WHERE, suivie du


nom du champ et de la condition. L'opérateur LIKE correspond au français "Comme".
La clause WHERE est suivie d'un parenthèsage aussi impressionnant qu'inutile.
De plus, la qualification est superflue. Si nous écrivons la requête sous la forme :
SELECT Nom, Prénom
FROM Personnes
WHERE Nom Like "c*";

elle fonctionne tout aussi bien, et le SGBD Access ne tente de rétablir ni les
parenthèses, ni la qualification.

© TIBB imbwangatroptard@[Link]
16
SQL
Rajoutons un champ de type date dans la table "Personnes", et sélectionnons les
enregistrements relatifs à l'année 2002 seule. Dans l'interface graphique, nous écrivons le
critère sous la forme :
>#31/12/2001# ET <#01/01/2003#
Si nous basculons en mode SQL, nous obtenons le code suivant, après
élimination des parenthèses et de la qualification :
SELECT Nom, Prénom, Date
FROM Personnes
WHERE Date>#12/31/2001# And Date<#1/1/2003#;

Nous pourrions faire des expériences analogues avec un champ numérique


(opérateurs arithmétiques), ou un champ booléen. Les conditions sur le "Null" (champ non
renseigné dans un enregistrement donné) s'écrivent à l'aide des expressions "Is Null" et "Is
Not Null", dont la traduction française dans Access est "Est Null" ou "Est Pas Null". On peut
combiner plusieurs conditions à l'aide des opérateurs logiques "And", "Or" et "Not", dont la
traduction française dans Access est "Et", "Ou" et "Pas". Enfin, une condition peut
comprendre des opérateurs arithmétiques ou des fonctions mathématiques (si elle porte sur
des nombres) ou des opérateurs de chaînes (si elle porte sur du texte).
Remarque : notre façon de sélectionner l'année 2002 est d'un usage très général,
mais elle semble un peu lourde. L'utilisation de la fonction "Year()" est plus élégante, mais
cette fonction est spécifique de VBA (Visual Basic for Applications, le langage de
programmation lié à Office). Voici le code SQL correspondant :
SELECT Nom, Prénom, Date
FROM Personnes
WHERE Year([Date])=2002;

Nous constatons que la requête fonctionne toujours si nous éliminons les


crochets entourant l'argument "Date" dans la fonction "Year". Mais, dans l'interface
graphique, la définition de la requête a changé ! Access a créé un nouveau champ intitulé
"Année([Date])" et inscrit la valeur "2002"sur la ligne "Critères :". Notons au passage que l'on
peut franciser "Year" en "Année" dans l'interface graphique d'Access, mais pas dans la
programmation d'un module VBA ou l'écriture d'une commande SQL.

3 - Les jointures
Effectuons maintenant une requête sur deux tables ("Personne" et "Communes")
liées par une relation (appliquée aux champs "code_commune"). La requête SQL s'écrit :
SELECT [Link], [Link]énom, [Link], [Link],
Communes.[code postal]
FROM Communes INNER JOIN Personnes ON Communes.code_commune =
Personnes.code_commune;

Cette fois, la qualification est obligatoire pour les champs "code_commune", car
il faut préciser de quelle table provient chaque champ. Mais la qualification est inutile pour
les autres champs, car il ne peut y avoir d'ambiguïté. Enfin, les crochets sont obligatoires pour
évoquer le champ "code postal", dont le nom contient un espace (ils ne le sont pas pour
"Prénom", parce que Access tolère les caractères accentués). La requête SQL ainsi simplifiée
s'écrit :

© TIBB imbwangatroptard@[Link]
17
SQL
SELECT Nom, Prénom, Adresse, commune, [code postal]
FROM Communes INNER JOIN Personnes ON Communes.code_commune =
Personnes.Code_commune;

Nous voyons que "INNER JOIN" traduit l'existence d'une relation entre les deux
tables, et que "ON" précise quels sont les champs mis en relation.
En SQL1, la commande précédente s'écrit différemment. La clause INNER JOIN
disparaît au profit d'une simple virgule, et la traduction de la mise en relation des tables
s'exprime à l'aide de la clause WHERE :
SELECT Nom, Prénom, Adresse, commune, [code postal]
FROM Communes, Personnes
WHERE Communes.code_commune = Personnes.code_commune;

Le SGBD Access accepte cette syntaxe mais, si nous revenons dans l'interface
graphique, nous constatons que cette dernière a changé : la relation entre les deux tables a
disparu ! Elle est remplacée par la condition d'égalité de contenu entre les champs
"code_commune" des deux tables (condition exprimée en utilisant la syntaxe du SQL),
comme le montre la figure ci-dessous -- une façon élémentaire, mais parfaitement exacte, de
créer une relation entre deux tables. On notera que la relation normale entre les deux tables
n'est pas supprimée, mais simplement éliminée de la fenêtre de création de la requête.

La clause INNER JOIN a fait son apparition avec la version 2 de SQL, parce que
le besoin s'était fait sentir de préciser à quel type de jointure appartenait une relation. Plus
précisément, on distingue :
la jointure interne, qui utilise INNER JOIN. Ne sont incluses dans le résultat final
que les lignes qui se correspondent dans les deux tables. Ce cas est celui que nous avons traité
précédemment ;
la jointure externe gauche, dans laquelle INNER JOIN est remplacé par LEFT
OUTER JOIN. Toutes les lignes de la première table sont incluses dans le résultat de la
requête, même s'il n'existe pas de ligne correspondante dans la seconde table ;
la jointure externe droite, dans laquelle INNER JOIN est remplacé par RIGHT
OUTER JOIN. Toutes les lignes de la seconde table sont incluses dans le résultat de la
requête, même s'il n'existe pas de ligne correspondante dans la première table.

© TIBB imbwangatroptard@[Link]
18
SQL

Dans Access, la syntaxe des jointures gauche et droite est simplifiée en LEFT
JOIN et RIGHT JOIN, comme le montrent les deux exemples suivants :
SELECT Nom, Prénom, Adresse, commune, [code postal]
FROM Personnes LEFT JOIN Communes ON Communes.code_commune =
Personnes.Code_commune;
SELECT Nom, Prénom, Adresse, commune, [code postal]
FROM Personnes RIGHT JOIN Communes ON Communes.code_commune =
Personnes.Code_commune;

La jointure peut également être précisée dans la fenêtre graphique de définition


d'une requête, comme nous l'avons vu au chapitre 13.

4 - Le regroupement
Nous avons étudié le regroupement au chapitre 14. Nous réutilisons la même
table, intitulée "Résultats" et représentée ci-dessous.

Date Agence CA
06/01/2003 Nord 927,02 €
06/01/2003 Sud 1 098,46 €
06/01/2003 Est 561,29 €
07/01/2003 Nord 1 385,55 €
07/01/2003 Est 681,09 €
07/01/2003 Sud 1 401,56 €

Nous effectuons le regroupement par date et nous sommons sur le CA. Nous
obtenons le code SQL suivant :
SELECT Date, Sum(CA) AS CA_total
FROM Résultats
GROUP BY Date;

dans lequel le regroupement est exprimé par la clause GROUP BY. La requête
fournit le résultat suivant :

Date CA_total
06/01/2003 2 586,77 €
07/01/2003 3 468,20 €

Nous avons vu au chapitre 14 qu'une requête avec regroupement peut être filtrée
avant ou après regroupement. Nous créons un exemple de filtrage avant regroupement en
éliminant l'agence Est. Nous obtenons le code SQL suivant :
SELECT Date, Sum(CA) AS CA_total
FROM Résultats
WHERE Agence Not Like "Est"
GROUP BY Date;

© TIBB imbwangatroptard@[Link]
19
SQL
Nous reconnaissons une requête de sélection classique (dans les trois premières
lignes), suivie d'un regroupement. La requête fournit le résultat suivant :

Date CA_total
06/01/2003 2 025,48 €
07/01/2003 2 787,11 €

Nous rajoutons ensuite un filtrage après regroupement en ne retenant que les CA


supérieurs à 2500 €. Nous obtenons le code SQL suivant :
SELECT Date, Sum(CA) AS CA_total
FROM Résultats
WHERE Agence Not Like "Est"
GROUP BY Date
HAVING Sum(CA)>2500;

dans lequel le filtrage après regroupement utilise la clause HAVING. La requête


fournit le résultat suivant :

Date CA_total
07/01/2003 2 787,11 €

D'une manière générale, une requête avec regroupement s'écrit en SQL :


SELECT .........
FROM ...........
WHERE ............
GROUP BY ...........
HAVING ............;

5 - Le comptage et les doublons


Nous avons étudié les doublons au chapitre 15, en utilisant la table "Résultats",
dans laquelle nous avons effacé une des valeurs du champ CA.

Date Agence CA
06/01/2003 Nord 927,02 €
06/01/2003 Sud 1 098,46 €
06/01/2003 Est 561,29 €
07/01/2003 Nord 1 385,55 €
07/01/2003 Est
07/01/2003 Sud 1 401,56 €

Nous créons une requête effectuant un regroupement sur le champ "Date", et un


comptage sur le champ "CA". Le code SQL s'écrit :
SELECT Date, Count(CA) AS Nombre_CA
FROM Résultats
GROUP BY Date;

© TIBB imbwangatroptard@[Link]
20
SQL
Nous voyons que le comptage est effectué par la fonction Count(). Le résultat de
la requête est le suivant (la fonction de comptage ignore les Null) :

Date Nombre_CA
06/01/2003 3
07/01/2003 2

Si nous appliquons la fonction "Count" au champ de regroupement lui-même,


nous effectuons un comptage des doublons sur ce champ. Le code SQL correspondant s'écrit :
SELECT Date, Count(Date) AS Doublons_date
FROM Résultats
GROUP BY Date;

La requête fournit le résultat suivant :

Date Doublons_Date
06/01/2003 3
07/01/2003 3

Si nous prenons le terme "doublon" au sens strict, nous devons éliminer du


résultat les comptages égaux à l'unité, en pratiquant un filtrage après regroupement. Le code
SQL s'écrit alors :
SELECT Date, Count(Date) AS Doublons_date
FROM Résultats
GROUP BY Date
HAVING Count(Date)>1;

Le comptage des doublons sur deux champs s'écrit ainsi :


SELECT Date, Agence, Count(*) AS Doublons
FROM Résultats
GROUP BY Date, Agence;

On notera que les deux champs doivent figurer dans la clause de regroupement.
On notera également que l'argument de la fonction Count() devient l'astérisque, ce qui signifie
que l'on compte les lignes sans se référer à une colonne particulière. Le code ci-dessus fournit
le résultat suivant (il n'y a pas de doublons) :

Date Agence Doublons


06/01/2003 Nord 1
06/01/2003 Sud 1
06/01/2003 Est 1
07/01/2003 Nord 1
07/01/2003 Est 1
07/01/2003 Sud 1

© TIBB imbwangatroptard@[Link]
21
SQL
Le regroupement sans comptage nous permet d'éliminer les doublons. Si nous
effectuons l'opération sur la colonne "Agence", nous obtenons la liste des agences. Le code
SQL s'écrit :
SELECT Agence
FROM Résultats
GROUP BY Agence;

La requête fournit le résultat suivant (les agences sont triées par ordre
alphabétique) :

Agence
Est
Nord
Sud

Terminons par le comptage sans regroupement, qui permet d'obtenir le nombre


d'enregistrements d'une table. Le code SQL s'écrit :
SELECT Count(*) AS Comptage
FROM Résultats;

La requête fournit le résultat suivant :

Comptage

5 - Conclusion
Comme dans le chapitre précédent, le langage SQL ne nous a pas permis
d'effectuer des requêtes qui eussent été impossibles dans l'interface graphique d'Access. Il
nous a cependant permis de simplifier la recherche des doublons (Cf le chapitre 15). Une
commande SQL plus simple s'exécute plus vite, et la différence de temps devient sensible
lorsqu'on traite un grand volume de données.

Chapitre 3: les opérations ensemblistes en SQL


1 - Introduction
Le langage SQL permet de réaliser sur un groupe de deux tables les trois
opérations de base de la théorie des ensembles, c'est à dire :
l'union
l'intersection
la différence

De ces trois opérations, seule l'union présente vraiment de l'intérêt. Si, dans les
exposés relatifs à SQL, on regroupe généralement les trois opérations ensemblistes, c'est pour
se conformer à une logique mathématicienne. Comme nous le verrons dans la suite de ce
chapitre, l'intersection et la différence sont en fait des requêtes multi-tables particulières, que

© TIBB imbwangatroptard@[Link]
22
SQL
l'on peut réaliser même si l'on ne dispose pas d'une commande spécifique -- ce qui est
effectivement le cas lorsqu'on utilise le SGBD Access.
La requête union, par contre, est quasi irremplaçable : elle seule permet de
mettre deux tables bout à bout en leur faisant jouer des rôles identiques, et en éliminant
systématiquement les doublons. Certes, la requête ajout permet d'ajouter une table à une autre,
mais dans ce cas les deux tables ne jouent pas le même rôle, et l'élimination des doublons -- si
elle s'avère nécessaire -- requiert soit la création d'un index multi-champ, soit un traitement
ultérieur (regroupement).
A ce chapitre nous rajouterons un paragraphe concernant le produit cartésien de
deux tables, requête qui n'est utilisée que très rarement et dans des cas très spécifiques.
Comme pour les autres chapitres de ce tutoriel (ou tutorial, ou cours en ligne),
nous utiliserons le SGBD Access comme support pratique.

2 - L'union de deux tables


L'union de deux tables est une une feuille de données (ou une table) contenant
chaque ligne de la première table et chaque ligne de la seconde table. Les lignes communes
aux deux tables ne sont conservées qu'en un seul exemplaire, c'est à dire que l'opération
d'union élimine les doublons. Les champs que l'on fait correspondre dans les deux tables n'ont
pas besoin de porter les mêmes noms ni de se présenter dans le même ordre -- ni même de
posséder le même type de donnée si la transposition est possible (une date en texte, par
exemple).
Exemple 1. La figure ci-dessous illustre l'opération d'union dans le cas simple
où les champs portent le même nom, possèdent les mêmes propriétés, et sont situés dans le
même ordre.

nom prénom
Chose Jules
Machin Pierre
Truc Patrick
union nom prénom
Pouf Jean
Chose Jules
= nomprénom
Chose Jules
Machin Pierre
Pouf Jean
Truc Patrick

Table1 Table2 Résultat

Il n'existe pas dans Access d'interface graphique permettant de créer une requête
Union. Il faut donc écrire soi-même le code SQL requis. Pour ouvrir l'éditeur de requêtes
SQL, nous sélectionnons l'objet "Requêtes" dans la fenêtre "Base de données", nous
n'introduisons aucune table dans l'interface graphique de définition des requêtes, et nous
basculons en mode SQL.

© TIBB imbwangatroptard@[Link]
23
SQL
Si notre base contient les deux tables précitées, nous pouvons exécuter la requête
SQL suivante, contenant l'opérateur UNION :
SELECT nom, prénom
FROM Table1
UNION
SELECT nom, prénom
FROM Table2;

A l'exécution de la requête, nous constatons qu'une feuille de données est créée,


qui rassemble le contenu des deux tables, et en élimine les doublons. Si nous enregistrons la
requête (sa structure, pas son contenu), Access fait précéder son nom de l'icône pour
rappeler qu'il s'agit d'une requête de type "Union".
Exemple 2. Les champs mis en correspondance n'ont pas besoin de porter le
même nom, comme le montre l'exemple suivant, dans lequel nous avons modifié les intitulés
des champs de la table "Table2" :
nom prénom
Chose Jules
Machin Pierre
Truc Patrick
union last-name first-name
Pouf Jean
Chose Jules
= nomprénom
Chose Jules
Machin Pierre
Pouf Jean
Truc Patrick

Table1 Table2 Résultat

La requête union correspondante est représentée ci-dessous. Le SGBD sait que


"last-name" correspond à "nom", et "first-name" à "prénom", parce que les champs sont cités
dans cet ordre dans les deux clauses SELECT. La feuille de données résultante emprunte les
noms de ses champs à la première table. La présence des crochets traduit le fait que SQL ne
tolère pas le tiret dans les noms des tables ni dans ceux des champs (caractère non autorisé).
SELECT nom, prénom
FROM Table1
UNION
SELECT [last-name], [first-name]
FROM Table2;

Exemple 3. Nous pouvons faire en sorte d'imposer les noms des champs dans la
feuille de données résultante pour obtenir, par exemple, le résultat suivant :
nom prénom
Chose Jules
Machin Pierre

© TIBB imbwangatroptard@[Link]
24
SQL
Truc Patrick
union nom prénom
Pouf Jean
Chose Jules
= Col1Col2
Chose Jules
Machin Pierre
Pouf Jean
Truc Patrick

Table1 Table2 Résultat

En SQL, la requête s'écrit ainsi :


SELECT nom AS Col1, prénom AS Col2
FROM Table1
UNION
SELECT nom AS Col1, prénom AS Col2
FROM Table2;

Exemple 4. Nous pouvons appliquer des critères de sélection (clause WHERE)


aux enregistrements de chacune des deux tables que nous voulons réunir. Il faut cependant
que nous fassions bien attention à bien définir le même critère dans les deux clauses SELECT.
Ainsi, pour exclure les noms commençant par A, B ou C dans le résultat final :
nom prénom
Chose Jules
Machin Pierre
Truc Patrick
union nom prénom
Pouf Jean
Chose Jules
= nomprénom
Machin Pierre
Pouf Jean
Truc Patrick

Table1 Table2 Résultat (avec critères)

nous utilisons la requête union suivante :


SELECT nom, prénom
FROM Table1
WHERE nom>"D"
UNION
SELECT nom, prénom
FROM Table2
WHERE nom>"D";

© TIBB imbwangatroptard@[Link]
25
SQL
Exemple 5. Pour faire en sorte que la requête union n'élimine pas les doublons,
nous rajoutons l'opérateur ALL après UNION, comme le montre la requête ci-dessous :
SELECT nom, prénom
FROM Table1
UNION ALL
SELECT nom, prénom
FROM Table2;

La feuille de données obtenue résulte de la simple mise bout à bout des deux
tables, sans tri ni élimination des doublons :
nom prénom
Chose Jules
Machin Pierre
Truc Patrick
union all nom prénom
Pouf Jean
Chose Jules
= Col1Col2
Chose Jules
Machin Pierre
Truc Patrick
Pouf Jean
Chose Jules

Table1 Table2 Résultat

Exemple 6. Comment faire en sorte que la requête Union crée une table ? Une
des techniques possibles consiste à emboîter la requête union dans une commande d'insertion.
Le code SQL suivant :
INSERT INTO Table3
SELECT *
FROM (SELECT nom, prénom
FROM Table1
UNION SELECT [last-name], [first-name]
FROM Table2);

peut être exécuté à condition que la table "Table3" ait été préalablement créée
(vide) -- mais cette condition n'est pas requise pour observer le résultat de la requête en mode
feuille de données. La requête ci-dessus est reconnue par le SGBD Access comme une requête
"Ajout" (à cause de la clause INSERT) et, si nous l'enregistrons, son nom apparaît précédé de
l'icône correspondante. Le code ci-dessus nous offre un exemple d'emboîtement en SQL.
Cet aspect didactique mis à part, il est plus simple, quand on opère dans le
SGBD Access, de réaliser d'abord la requête union, puis de réutiliser son résultat dans une
requête de sélection simple, à laquelle on demande de créer une table.

© TIBB imbwangatroptard@[Link]
26
SQL
Remarque. Si nous tentons de réaliser l'union de deux tables contenant un
champ (nommé "essai") de type Mémo, Objet OLE ou Lien hypertexte, nous obtenons le
message suivant (rédigé dans le jargon franglais des informaticiens) :

Cela signifie que, dans le SGBD Access, la requête Union ne fonctionne pas sur
les champs de type Mémo, Objet OLE et Lien hypertexte. Pour réunir deux tables comportant
des champs de ce type sans les perdre, il faut utiliser la requête Ajout.
La requête Union présente un autre défaut : elle est lente à l'exécution, aussi bien
programmée soit-elle. Cela provient du fait qu'elle trie et dédoublonne, alors que la requête
Ajout se contente de compléter une table avec les données d'une autre. A titre d'exemple, sur
un PC de qualité standard, il faut environ plusieurs minutes (3-4) pour réaliser l'union de
10.000 enregistrements avec 300.000 autres.

3 - L'intersection de deux tables


L'intersection de deux tables est une une feuille de données (ou une table)
contenant seulement les lignes communes aux deux tables. Les conditions sont les mêmes que
pour l'union. La figure ci-dessous illustre l'opération intersection :

nom prénom
Chose Jules
Machin Pierre
Truc Patrick
inter nom prénom
Pouf Jean
Chose Jules
= nom prénom
Chose Jules

Le code SQL correspondant dépend de la version utilisée. En SQL1, il s'écrit :


SELECT nom, prénom
FROM Table1
WHERE [Link] IN (SELECT nom FROM Table2) AND [Link]énom IN (SELECT
prénom FROM Table2);

Cette syntaxe, qui fait appel à l'emboîtement autant de fois qu'il y a de colonnes,
a été simplifiée par l'introduction de l'opérateur INTERSECT en SQL2. Le nouveau code
s'écrit :
SELECT nom, prénom
FROM Table1
INTERSECT

© TIBB imbwangatroptard@[Link]
27
SQL
SELECT nom, prénom
FROM Table2;

Mais... le SGBD Access ne reconnaît pas l'opérateur INTERSECT. Il affiche un


message d'erreur qui, bien entendu, ne correspond pas à la situation (une habitude bien ancrée
en informatique). Seule reste en lice la première syntaxe, qui apparaît de la manière suivante
dans l'interface graphique :

Comme on peut le constater, il est possible d'utiliser des critères écrits en code
SQL dans l'interface graphique. Ma foi, autant utiliser la fenêtre SQL directement !
Que l'opérateur INTERSECT ne soit pas reconnu par Access n'est pas un drame.
Outre les deux commandes SQL déjà citées, nous en imaginer une troisième, qui résulte
directement de la définition de l'intersection :
SELECT DISTINCT [Link], [Link]énom
FROM Table1, Table2
WHERE [Link]=[Link] AND [Link]énom=[Link]énom;

La présence de l'opérateur DISTINCT est indispensable, sinon tous les


enregistrements de l'intersection figurent en double dans la feuille de données. Le SGBD les
écrit deux fois parce qu'il les trouve une fois dans la première table, et une autre fois dans la
seconde.
Le code ci-dessus est représenté ainsi dans l'interface graphique (on vérifie en
outre que la propriété "Valeurs distinctes" de la requête vaut "Oui") :

Nous pouvons encore traduire l'intersection en utilisant des relations (ou


jointures) entre les champs des deux tables. Rappelons qu'une relation créée dans la fenêtre
graphique de définition des requêtes possède une existence éphémère, ce que prouve le fait
qu'elle n'apparaît pas dans la fenêtre "Relations". Pour traduire qu'un enregistrement de la

© TIBB imbwangatroptard@[Link]
28
SQL
seconde table est identique à celui de la première table, nous utilisons l'opérateur "Est Pas
Null". Dans l'interface graphique, la requête apparaît comme le montre la figure ci-dessous.

La version SQL de cette requête s'écrit :


SELECT [Link], [Link]énom
FROM Table1 INNER JOIN Table2 ON [Link] = [Link] AND [Link]énom =
[Link]énom
WHERE [Link] Is Not Null AND [Link]énom Is Not Null;

4 - La différence de deux tables


La différence de deux tables est une une feuille de données (ou une table)
contenant les enregistrements de la première table qu'on ne retrouve pas dans la seconde. Les
conditions sont les mêmes que pour l'union. La figure ci-dessous illustre l'opération
différence :

nom prénom
Chose Jules
Machin Pierre
Truc Patrick
diff nom prénom
Pouf Jean
Chose Jules
= nomprénom
Machin Pierre
Truc Patrick

Le code SQL correspondant dépend de la version du langage utilisée. En SQL1,


il s'écrit comme pour l'intersection, à ceci près que IN est remplacé par NOT IN :
SELECT nom, prénom
FROM Table1

© TIBB imbwangatroptard@[Link]
29
SQL
WHERE [Link] NOT IN (SELECT nom FROM Table2) AND [Link]énom NOT IN
(SELECT prénom FROM Table2);

(dans l'interface graphique de définition des requêtes, "Not In" devient "Pas In"
-- un joyeux mélange de français et d'anglais).
La syntaxe précédente, qui fait appel à l'emboîtement autant de fois qu'il y a de
colonnes, a été simplifiée par l'introduction de l'opérateur EXCEPT dans SQL2 (MINUS dans
le SGBD Oracle). Le nouveau code s'écrit :
SELECT nom, prénom
FROM Table1
EXCEPT
SELECT nom, prénom
FROM Table2;

Le SGBD Access ne reconnaît ni l'opérateur INTERSECT, ni l'opérateur


MINUS, et il affiche un message d'erreur. On peut bien sûr s'en tirer comme pour
l'intersection, mais il faut cette fois utiliser la jointure gauche. Voici comment apparaît la
requête dans l'interface graphique (où la jointure gauche est représentée par une flèche allant
de la première vers la seconde table) :

Le code SQL correspondant s'écrit :


SELECT [Link], [Link]énom
FROM Table1 LEFT JOIN Table2 ON [Link]énom = [Link]énom AND [Link] =
[Link]
WHERE [Link] Is Null AND [Link]énom Is Null;

La jointure gauche est nécessaire parce qu'il faut que le SGBD, lors de
l'exécution de la requête, utilise tous les enregistrements de la première table, qu'ils soient ou
non présents dans la seconde. Si nous utilisions la jointure interne, le SGBD n'examinerait que
les enregistrements communs, et n'en retiendrait évidemment aucun. Si nous utilisions la
jointure droite, le SGBD utiliserait tous les enregistrements de la deuxième table, mais
seulement ceux de la première table qui sont communs, et le résultat serait de nouveau vide.
Le choix du type de jointure vous pose problème ? Essayez les trois types sur un
exemple simple, vous trouverez ainsi quel est celui qui donne la réponse juste.

© TIBB imbwangatroptard@[Link]
30
SQL

5 - Le produit cartésien de deux tables


Le produit cartésien de deux tables est une feuille de données (ou une table)
obtenue en associant tous les enregistrements de la seconde table à chacun des
enregistrements de la première.
Si chacune des deux tables contient un grand nombre d'enregistrements, le
résultat du produit est gigantesque. De plus, il ne présente généralement pas d'intérêt. En
général, le produit cartésien résulte d'une étourderie (oubli d'une relation dans une requête
multi-table). La figure ci-dessous illustre l'opération de produit cartésien :

nom
Chose
Machin
X prénom
Jean
Jules
= nomprénom
Chose Jean
Chose Jules
Machin Jean
Machin Jules

Le code SQL correspondant s'écrit :


SELECT [Link], [Link]énom
FROM Table1, Table2;

En mode graphique, on introduit les deux tables dans la fenêtre "Requête


sélection" en veillant bien à ce qu'il n'y ait pas de relation entre elles. Puis on introduit dans la
grille le champ "nom" de la première table, et le champ "prénom" de la seconde.
Le produit cartésien rend service quand il faut rassembler dans une même table
(à une seule ligne) diverses tables ou feuilles de données comportant une seule ligne. Le
produit cartésien fournit alors une table ne comportant qu'une seule ligne. Les tables à une
seule ligne résultent généralement de calculs effectués verticalement, tels que comptage du
nombre d'enregistrements ou opérations diverses (somme, moyenne, fonctions statistiques)
sur les champs numériques ou monétaires.

6 - Conclusion
Il est clair que les concepteurs du SGBD Access n'aimaient pas les ensembles.
Car si l'opérateur UNION est reconnu (mais inutilisable dans l'interface graphique) par le
logiciel, les opérateurs INTERCEPT et EXCEPT (ou MINUS) sont ignorés. Pour réaliser une
intersection ou une différence dans Access, la solution la plus simple consiste à utiliser les
jointures (sans se tromper), associées à des conditions sur le Null. Il faut cependant
reconnaître que, des trois opérations ensemblistes, seule la requête Union a vraiment de
l'importance.
Rappelons pour terminer que, dans une requête Union, les deux tables jouent le
même rôle, contrairement à ce qui se passe dans la requête "Ajout". De plus, aucune des deux
tables n'est modifiée par l'exécution de la requête, et les doublons sont automatiquement

© TIBB imbwangatroptard@[Link]
31
SQL
éliminés, à moins que nous ne demandions à les conserver. La requête union mérite à elle
seule que l'on se familiarise un peu avec le SQL.

Chapitre 22 : les autres requêtes en SQL


1 - Introduction
Nous avons déjà consacré quatre chapitres au langage SQL. Il nous reste à traiter
trois types de requête :
la suppression
la mise à jour
l'ajout

Pour créer des exemples, nous utiliserons la table suivante, intitulée "Table1" :
Nom Prénom
Chose Jules
Machin Pierre
Truc Patrick
Pouf Renée

Attention ! Toutes les requêtes que nous allons utiliser modifient les tables
auxquelles elles s'appliquent. Il est donc vivement recommandé de créer une copie de la table
avant d'exécuter la requête.
Comme pour les autres chapitres de ce tutoriel (ou tutorial, ou cours en ligne),
nous utiliserons le SGBD Access comme support pratique.

2 - La suppression
Rappelons qu'une requête de suppression opère sur une table, dont elle supprime
les enregistrements (ou lignes) répondant à un ou plusieurs critères.
En SQL, c'est la commande DELETE qui permet de supprimer des lignes dans
une table. La clause WHERE permet d'exprimer les conditions (critères) de cette suppression.
Pour supprimer la dernière ligne de la table "Table1", nous créons la requête
SQL suivante :
DELETE Table1
WHERE Nom="Pouf";

Mais le SGBD Access n'accepte pas cette syntaxe. Si nous créons la requête de
suppression dans l'interface graphique, sa traduction en SQL donne :
DELETE Nom
FROM Table1
WHERE Nom="Pouf";

Cette syntaxe fonctionne. L'enregistrement relatif à Renée Pouf disparaît


effectivement de la table "Table1" quand nous exécutons la requête SQL ci-dessus, comme le
montre la figure suivante :
Nom Prénom
Chose Jules

© TIBB imbwangatroptard@[Link]
32
SQL
Machin Pierre
Truc Patrick
Pouf Renée
-- Suppression --> Nom Prénom
Chose Jules
Machin Pierre
Truc Patrick

Table initiale Table modifiée

Mais cette syntaxe manque de logique. Ce n'est pas dans le seul champ "Nom"
que nous opérons une suppression, c'est toute la ligne comportant le nom "Pouf" qui disparait.
C'est probablement pour faciliter la correspondance avec l'interface graphique que l'éditeur
Microsoft a pris des libertés avec la syntaxe de la requête suppression en SQL, ce qui est
regrettable.
Tout ce que nous avons dit sur l'expression des critères dans les requêtes de
sélection s'applique aux requêtes de suppression. En résumé, la syntaxe d'une requête de
suppression est :
SQL normalisé DELETE nom de la table
WHERE critères des suppressions;

SQL Access DELETE nom de champ


FROM nom de table
WHERE critères des suppressions;

Attention ! dans le SGBD Access, l'opération de suppression est irréversible. La


commande ROLLBACK, que l'on trouve dans certains SGBD, et qui annule l'effet d'une
requête de mise à jour (tant qu'une commande COMMIT n'a pas rendu cet effet définitif), ne
fonctionne pas ici. Il est donc fortement recommandé de créer une sauvegarde de la table
avant de la modifier.

3 - La mise à jour
Rappelons qu'une requête de mise à jour modifie le contenu d'une colonne dans
une table donnée. Cette modification peut être soumises à des critères, de telle sorte qu'elle ne
s'applique pas à toutes les lignes.
En SQL, c'est la commande UPDATE qui permet de modifier (ou mettre à jour)
les données d'une table. La clause SET est utilisée pour préciser la modification demandée, et
la clause WHERE les conditions d'application (critères) de cette modification.
Supposons par exemple que, dans la table "Table1", nous ayons commis une
erreur en saisissant le prénom de M. Chose. Pour remplacer "Jules" par "Henri", dans la
colonne "Prénom", sur la ligne relative à M. Chose, nous utilisons la requête SQL suivante :
UPDATE Table1
SET Prénom = "Henri"
WHERE Nom="Chose";

© TIBB imbwangatroptard@[Link]
33
SQL
L'exécution de cette requête modifie la table "Table1" comme suit :
Nom Prénom
Chose Jules
Machin Pierre
Truc Patrick
-- Mise à jour --> Nom Prénom
Chose Henri
Machin Pierre
Truc Patrick

Table initiale Table modifiée

Attention ! dans le SGBD Access, l'opération de mise à jour est irréversible. Il


est donc fortement recommandé de créer une sauvegarde de la table avant de la modifier.
Tout ce que nous avons dit sur l'expression des critères dans les requêtes de
sélection s'applique aux requêtes de mise à jour. La syntaxe générale d'une requête de mise à
jour est :
UPDATE nom de la table
SET nom de la colonne = nouvelle valeur
WHERE critères de la modification;

Exemple : pour augmenter de 20 % tous les prix contenus dans la colonne "Prix"
d'une table intitulée "Table2", nous utilisons la requête ci-dessous. On notera qu'il n'est pas
nécessaire, pour évoquer le contenu du champ "Prix", de placer son nom entre crochets.
UPDATE Table2
SET Prix = Prix*1.2;

La requête de mise à jour permet aussi d'effacer le contenu d'une ou plusieurs


cellules, par utilisation de la valeur Null. Par exemple, la requête SQL suivante efface le
prénom (Patrick) de M. Truc :
UPDATE Table1
SET Prénom = Null
WHERE Nom="Truc";

Remarque : si nous supprimons la clause WHERE dans la requête précédente, et


si nous l'exécutons, tous les prénoms sont effacés, et non plus seulement celui de M. Truc.

4 - L'ajout (ou insertion)


Rappelons qu'une requête ajout permet d'insérer (totalement ou sélectivement)
une table dans une autre. En SQL, c'est la commande INSERT INTO qui est utilisée.
Pour bâtir un exemple, nous créons la table "Table3" avec les deux champs
suivants (du type de données "texte") :
Col1 Col2
Titi Noëlle

En SQL, l'insertion de la table "Table1" dans la table "Table3" s'écrit :

© TIBB imbwangatroptard@[Link]
34
SQL
INSERT INTO Table3 ( Col1, Col2 )
SELECT Nom, Prénom
FROM Table1;

Grâce à cette syntaxe, le SGBD sait que les données du champ "Nom" de la table
"Table1" vont dans le champ "Col1" de la table "Table3", et les données du champ "Prénom"
de la table "Table1" dans le champ "Col2" de la table "Table3". Il faut bien sûr que les types
de données soient compatibles. Par exemple, on peut introduire une date dans un champ texte,
mais l'inverse est généralement impossible. Il faut aussi faire attention à la façon dont on fait
correspondre les champs. Il n'est pas nécessaire qu'ils se présentent dans le même ordre dans
les deux tables, pourvu que la commande SQL indique clairement comment on les met en
correspondance. Il n'est pas nécessaire non plus que les champs qui se correspondent portent
le même nom.
La requête précitée réalise l'opération suivante :
Nom Prénom
Chose Henri
Machin Pierre
Truc Patrick

+ Col1 Col2
Titi Noëlle
= Col1Col2
Titi Noëlle
Chose Henri
Machin Pierre
Truc Patrick

Table ajoutée Table réceptrice Résultat

Si par contre on rédige la commande ainsi :


INSERT INTO Table3 ( Col1, Col2 )
SELECT Prénom, Nom
FROM Table1;
ou ainsi : INSERT INTO Table3 ( Col2, Col1)
SELECT Nom, Prénom
FROM Table1;

les prénoms iront dans la colonne "Col1" et les noms dans la colonne "Col2".
On peut rajouter un ou plusieurs critères (via la clause WHERE) permettant de
sélectionner les enregistrements à ajouter. La requête ci-dessous, par exemple, ajoutera
seulement Chose Henri à la table "Table3".
INSERT INTO Table3 ( Col1, Col2 )
SELECT Nom, Prénom
FROM Table1
WHERE Nom<"d";

© TIBB imbwangatroptard@[Link]
35
SQL

5 - Conclusion
Nous avons appris à créer des requêtes de suppression, de mise à jour et d'ajout
en SQL. Dans le cas particulier du SGBD Access, la syntaxe de la requête de suppression
n'est pas très claire. Les requêtes de mise à jour et d'ajout ont par contre une syntaxe qui
respecte le SQL normalisé.
Certains utilisateurs pourront donc trouver utile de basculer en mode SQL pour
vérifier, avant exécution, si la requête de mise à jour ou d'ajout qu'ils viennent de créer dans
l'interface graphique répond bien à leurs desiderata.

Chapitre 23 : les états (1)


1 - Introduction
Dans une base de données, l'objet état est utilisé pour mettre en forme les
données destinées à être imprimées. Lorsque la matérialisation de données issue d'un SGBD
présente un caractère répétitif, et plus encore lorsqu'il est envisagé d'automatiser cette
opération, le recours à un état constitue la meilleure solution. A ce titre, l'état constitue donc
le troisième objet des SGBD par ordre d'importance décroissante, après les tables et les
requêtes.
Mais la création d'un état qui présente correctement les données imprimées est
souvent une opération longue et quelque peu fastidieuse. C'est pourquoi l'état n'est pas
toujours considéré comme indispensable, et il existe deux façons de s'en passer.
Première solution. Nous pouvons imprimer directement une table ou une feuille
de données, à condition de limiter considérablement nos ambitions en matière de présentation.
Nous sommes maîtres de la largeur des colonnes (ne pas lésiner sur ce point, sinon
l'information risque d'être tronquée), de la couleur de fond de cellule, de la taille et du type de
la police, et c'est à peu près tout. Le SGBD pagine, affiche la date et le nom de la table (ou de
la feuille de données), et met en page à sa façon -- c'est à dire qu'il commence en haut et à
gauche, tout simplement. Imprimer directement une table ou une feuille de données est une
solution de dépannage, mais ce n'est pas vraiment le moyen de réaliser un document bien
présenté.
Deuxième solution. Une table créée dans Access et dans d'autres SGBD
fonctionnant sous le système d'exploitation Windows peut facilement être exportée vers un
tableur, et en particulier vers Excel qui est le plus utilisé. Dans un tableur, la mise en page
avant impression est facile et intuitive, et nous disposons là d'un bon moyen pour obtenir un
imprimé correctement présenté. L'exportation vers Excel des résultats d'une requête constitue
une technique de plus en plus utilisée, non seulement pour mettre en forme des données avant
impression, mais aussi pour profiter des diverses fonctions qu'offre le tableur. L'opération est
particulièrement facile si nous nous trouvons dans Access : la table à analyser ou à imprimer
étant sélectionnée, nous cliquons dans le menu sur "Outils", puis sur "Liaisons Office"et enfin
sur "Analyse avec Microsoft Excel". Le tableur s'ouvre, et la table y est aussitôt exportée. De
plus, un fichier au format Excel est enregistré sur le bureau.
Un état est pratiquement toujours construit sur le résultat d'une requête, et ce
pour les raisons suivantes :

© TIBB imbwangatroptard@[Link]
36
SQL
les bases de données contiennent souvent des quantités considérables d'information, et
il n'est pas question de tout imprimer. Il faut donc commencer par sélectionner l'information
particulière que l'on veut reproduire avant d'imprimer ;
dans une BDD relationnelle, l'information est répartie dans des tables multiples, et il
faut la rassembler avant de l'imprimer. On peut, cependant, introduire dans un même état des
champs provenant de plusieurs tables, à condition que ces dernières soient liées par des
relations ;
on peut désirer que l'information imprimée se présente dans un certain ordre. Il faut
donc opérer un tri plus ou moins complexe avant d'imprimer. Ceci dit, on peut également
demander un tri complexe (jusqu'à quatre niveaux) lors de la création de l'état.

Bien qu'il ne soit pas question, en général, d'imprimer la totalité du contenu


d'une BDD, un état s'étale souvent sur plusieurs pages. C'est le SGBD qui se charge de gérer
les sauts de page (si l'utilisateur ne donne pas d'instructions particulières à ce sujet),
d'imprimer l'en-tête et le pied de chaque page. L'en-tête de la première page, et la fin de la
dernière page, sont généralement différents de ceux des autres pages.
Comme pour les autres chapitres de ce tutoriel (ou tutorial, ou cours en ligne),
nous utiliserons le SGBD Access comme support pratique. Nous prévenons cependant le
lecteur que la mise en forme d'un état dans Access est une tâche quelque peu pénible, parce
que l'outil mis à notre disposition par le SGBD est malcommode. Pour une impression
occasionnelle, nous recommandons donc d'utiliser plutôt Excel.
Signalons au passage que, si vous utilisez Access 2002 comme SGBD, Windows
XP comme système d'exploitation, et si vous n'êtes pas administrateur de votre machine, un
bug peut faire capoter la création de l'état en fin d'opération. Si vous vous trouvez dans ce cas,
prévenez l'administrateur de votre service informatique, et priez le ciel pour qu'il résolve le
problème.

2 - Les préliminaires
La finalité de l'état étant la réalisation d'une sortie imprimée, il est indispensable
d'indiquer au SGBD :
l'imprimante utilisée ;
la taille de la zone imprimable, c'est à dire celle du papier, diminuée de celle des
marges.

Nous rencontrons ici l'une des différences importantes qui existent entre l'état et
le formulaire : le premier opère dans une zone imprimable, le second dans une fenêtre de
l'écran du moniteur.
L'imprimante. Le SGBD construit l'état en fonction des caractéristiques de
l'imprimante par défaut. Si vous utilisez un poste de travail sur lequel aucune imprimante n'a
été déclarée, vous allez au-devant de bien des ennuis (lenteur, plantage...). Vérifiez donc ce
point avant d'entreprendre la création d'un état.
La zone imprimable. Ensuite, le SGBD tient compte des options que vous avez
choisies -- ou, plus généralement, conservées par défaut -- en ce qui concerne la taille du
papier (A4, sauf exception) et les marges d'impression. Si vous manquez de place en largeur
-- ce qui est souvent le cas lorsqu'un état est présenté en colonnes -- vous avez intérêt à
réduire les marges à gauche et à droite. Mais attention ! vous devez effectuer cette opération

© TIBB imbwangatroptard@[Link]
37
SQL
avant de commencer à construire votre état. Une fois ce dernier créé, les changements de
marge que vous effectuez sont sans effet sur lui.
Dans Access, pour régler les marges, cliquez dans le menu sur "Outils", puis
"Options..." : la fenêtre "Options" s'ouvre. Choisissez l'onglet "Général" : les quatre marges
sont réglées par défaut à un pouce (2,54 cm). En pratique, 2 cm à gauche et 1 cm à droite
suffisent largement. Quelles que soient les valeurs que vous choisissez, elles resteront
valables quelle que soit la BDD dans laquelle vous travaillez, tant que vous ne les modifierez
pas à nouveau.
La sélection des données. Mettez au point la (ou les) requête(s) qui vous
permettent de sélectionner les données à imprimer. Si vous avez besoin d'un tri, incorporez-le
à ce stade, car les tris que l'on demande au niveau des états ne fonctionnent pas toujours très
bien. Enfin, vous n'êtes pas obligé de créer une table, un état pouvant être construit
directement sur le résultat d'une requête.
La présentation des données. Il existe deux modes de présentation d'un état :
la présentation tabulaire : les données sont disposées dans des colonnes verticales,
comme dans une table. Le nom des colonnes (l'étiquette) figure une seule fois par page. Cette
présentation, qui convient particulièrement bien aux données numériques, économise de la
place ;
la présentation verticale : les données relatives à chaque champ sont imprimées les
unes en dessous des autres, le nom du champ étant rappelé à chaque fois. Cette présentation
est la seule possible lorsque le contenu de certains champs est volumineux. Elle peut faire
l'objet d'un regroupement sur une colonne donnée, si cette dernière contient de nombreux
doublons. Elle présente l'inconvénient de requérir beaucoup de place.

Il est bon de réfléchir à la présentation avant de commencer à créer l'état.


Les barres d'outils. Il en existe deux qui sont spécifiques des états. Elles
s'appellent respectivement "Créer un état" et "Mise en forme (Formulaire/État)", et certaines
de leurs icônes nous seront indispensables. Pour faire apparaître ces deux barres, nous
cliquons sur "Affichage" dans le menu, puis sur "Barres d'outils", et nous cochons le nom de
la barre désirée. Par la même occasion, nous demandons l'affichage de la boîte à outils.

3 - La création de l'état
Ouvrons une BDD contenant au moins une table pourvue de données et, dans la
fenêtre "Base de données", sélectionnons l'objet "États". Deux options nous sont présentées :
Créer un état en mode Création
Créer un état à l'aide de l'Assistant

Les manuels, en général, conseillent d'utiliser l'assistant en toutes circonstances,


car créer un état à partir de rien est assez fastidieux. Mais, dans le cas où l'on choisit la
présentation tabulaire, et où il y a de nombreux champs, l'assistant conduit à un mauvais
résultat, qu'il est ensuite difficile de corriger complètement. Dans ce cas, il faut confier à
l'assistant le soin de créer une partie des champs seulement (en particulier ceux sur lesquels
on envisage un regroupement), et utiliser ensuite la fonction "Modifier" pour introduire les
autres champs au fur et à mesure que la mise en forme de l'état progresse. Obtenir un bon
résultat lors de l'impression demande une bonne dose de patience.
Il existe aussi une icône "Nouveau", qui redonne le mode création et
l'assistant, mais propose de plus des fonctions dont l'intérêt est plutôt mince :

© TIBB imbwangatroptard@[Link]
38
SQL
État instantané : Colonnes. Cette fonction crée un état en présentation verticale dès
que nous lui fournissons le nom de la table ou de la requête. Nous ne sommes pas maître des
paramètres, et le résultat est sommaire ;
État instantané : Tableau. Cette fonction opère comme la précédente, mais en
présentation tabulaire ;
Assistant graphique. Cette fonction permet de créer des graphiques, mais leur qualité
est très mauvaise. Pour créer un graphique correct, il faut exporter les données vers un
tableur ;
Assistant étiquette. Comme son nom l'indique, cette fonction permet d'imprimer des
étiquettes.

Lançons l'assistant, choisissons une table ("Personnes", avec les champs "Nom"
et "Prénom"), sélectionnons ses deux champs, ignorons le regroupement et le tri, adoptons la
disposition tabulaire, l'orientation portrait et le style "Informel" (valeurs par défaut), donnons
un titre à l'état ("Liste des personnes"), et cliquons sur "Terminer". Nous obtenons un état qu'il
est souhaitable d'améliorer.

4 - La structure de l'état
L'état que nous venons de créer apparaît dans la fenêtre "Base de données"
(l'objet "État" étant sélectionné). Nous le sélectionnons, puis nous cliquons sur l'icône
"Modifier". Une fenêtre s'ouvre, qui nous permet de modifier l'état.
Procédons d'abord à une petite vérification. Notre imprimante utilise du papier
A4 de 21 cm de large, et nous avons choisi des marges gauche et droite importantes (5 cm)
afin de limiter la taille de la figure ci-dessous. Nous vérifions que la largeur utile de l'état (la
partie claire et quadrillée) mesure effectivement 11 cm, comme le montre la figure. Même si
nous modifions par la suite les marges dans la fenêtre "Options", celles de notre nouvel état ne
varieront pas.

Nous observons que l'état est divisé en cinq zones :

© TIBB imbwangatroptard@[Link]
39
SQL
En-tête d'état. Cette zone est imprimée en haut de la première page uniquement ;
En-tête de page. Cette zone est imprimée en haut de toutes les pages (à condition
qu'elle contienne de l'information) ;
Détail. Ce terme désigne la zone qui s'étend entre l'en-tête et le pied de page. Cette
zone permet d'imprimer le contenu de la table (ou de la feuille de données) sous-jacente ;
Pied de page. Cette zone est imprimée en bas de chaque page ;
Pied d'état. Cette zone s'imprime uniquement sur la dernière page, après le détail et
avant le pied de page. Par défaut, l'assistant lui attribue une hauteur nulle.

De manière quelque peu schématique, on peut dire que les diverses zones sont
utilisées de la manière suivante :
la première zone (en-tête d'état) contient le titre, de telle sorte qu'il n'apparaisse qu'une
seule fois, et qu'il se trouve en tête de l'état ;
dans une présentation tabulaire, les noms des champs (on les appelle les "étiquettes")
sont placés dans la seconde zone (en-tête de page), de manière à être reproduits en haut de
chaque page. Dans une présentation verticale, les étiquettes sont regroupées avec les champs
correspondants dans la zone "Détail", et l'assistant ne prévoit pas d'utiliser l'en-tête de page ;
les champs (on les appelle "zones de texte", ou parfois "contrôles" comme dans les
formulaires) sont placés dans la troisième zone (détail) ; leurs valeurs sont imprimées ligne
après ligne, tant qu'il reste de la place entre l'en-tête et le pied de chaque page. Le SGBD
passe ensuite à la page suivante, et le processus recommence ;
dans la quatrième zone (pied de page), le système pagine et inscrit la date. Ces
informations apparaissent donc en bas de chaque page.
la cinquième zone (pied d'état) contient les résultats de calculs éventuels, ou un
message de fin d'état.

Dans la fenêtre graphique de modification de l'état, les zones de texte et les


étiquettes apparaissent comme des rectangles contenant du texte.
On distingue trois catégories de zone de texte :
La zone de texte dépendante. Son contenu provient soit d'un champ de la table ou de
la requête sous-jacente, soit d'une instruction SQL. Les zones de texte dépendantes se
trouvent généralement dans la zone "Détail" de l'état ;
La zone de texte indépendante. Son contenu ne provient pas d'un objet de la BDD.
On l'utilise pour afficher un texte informatif (exemple : le titre de l'état), une image
(exemple : le logo de l'entreprise), ou des éléments de décoration, principalement dans l'en-
tête de l'état ;
la zone de texte calculée. Elle contient le résultat d'un calcul (exemples : somme,
moyenne, fonctions statistiques, date, page, etc.). Ce résultat est remis à jour chaque fois que
les données utilisées dans le calcul sont modifiées. Les zones de texte calculées se trouvent
généralement dans les pieds de page ou dans le pied de l'état.

Tout en haut à gauche de la fenêtre de l'application se trouve une liste déroulante


baptisée "État". Elle contient la liste des 15 objets qui se trouvent dans la fenêtre de
modification de l'état (tableau ci-dessous). La sélection de l'un de ces objets dans la liste
entraîne sa sélection dans la page et vice versa.

Objet Type Contenu

© TIBB imbwangatroptard@[Link]
40
SQL
Détail Zone 3
En-têteÉtat Zone 1
État
Étiquette4 Zone de texte indépendante Titre de l'état
Nom Zone de texte dépendante Contenu du champ "Nom"
Nom_étiquette Étiquette Étiquette du champ "Nom"
Pied État Zone 5
Prénom Zone de texte dépendante Contenu du champ "Prénom"
Prénom_étiquette Étiquette Étiquette du champ "Prénom"
Texte5 Zone de texte calculée Affiche la date du jour
Texte6 Zone de texte calculée Affiche la pagination
Trait7 Zone de texte indépendante Le pointillé supérieur
Trait8 Zone de texte indépendante Le pointillé inférieur
ZoneEn-têtePage Zone 2
ZonePiedPage Zone 4

5 - La mise en forme de l'état


Un état étant ouvert en mode "Modification", les outils qui nous permettent de
procéder à sa mise en forme sont dispersés à cinq endroits différents. Nous pouvons en effet
utiliser :
les icônes des barres d'outils "Créer un état" et "Mise en forme (Formulaire/État)".
Nous avons déjà indiqué au paragraphe 2 comment les faire apparaître ;
la feuille de propriétés que possède chaque objet de l'état. Pour la faire apparaître,
nous sélectionnons l'objet (ex : le titre), nous cliquons sur l'icône "Propriétés", puis nous
sélectionnons l'onglet "Format" ;
la fenêtre graphique elle-même, dans laquelle il est possible de modifier l'état en tirant
ou en glissant-déplaçant à l'aide de la souris ;
le menu, par ses rubriques "Format" et "Insertion" ;
la boite à outils. Pour la faire apparaître, nous cliquons sur l'icône "Boîte à outils".
Cette boîte est commune aux états et aux formulaires, mais elle est nettement moins utilisée
pour les premiers que pour les seconds.

Les barres d'outils. Nous noterons d'abord que la barre de mise en forme est
active lorsqu'une zone de texte est sélectionnée. Cette barre contient les outils usuels du
traitement de texte (propriété de la police, alignement du texte, couleur de fond et de premier
plan, bordures). Elle contient en outre (tout à fait à gauche) la liste des objets de l'état, liste
dont nous avons déjà parlé au paragraphe 4 précédent.
Lorsque nous modifions la présentation d'un état, il nous faut régulièrement
vérifier le résultat obtenu, car ce qui s'affiche est souvent différent de ce qui s'observe en
mode "Modifier". Pour cela, nous cliquons sur l'icône "Aperçu" de la barre d'outils "Créer
un état".
Cette barre contient également deux autres icônes fort utiles. L'icône "Liste des
champs" permet de rajouter de nouveaux champs à l'état, par simple glisser-déplacer (de la
liste vers l'état). L'icône "Propriétés" permet d'afficher la feuille de propriétés de l'objet
sélectionné dans l'état.
Ces feuilles de propriétés nous sont fort utiles, car dans leur onglet "Format"
nous pouvons :

© TIBB imbwangatroptard@[Link]
41
SQL
régler la position des quatre coins du rectangle contenant une zone de texte. L'origine
des coordonnées correspond au coin situé en haut et à gauche de la zone dans laquelle se
trouve la zone de texte ;
régler les marges et l'interligne (à l'intérieur de la zone de texte) ;
colorer le fond ou le rendre transparent ;
régler la bordure (couleur, épaisseur) et l'apparence (3D, ombré, etc.) ;
fixer tous les attributs du texte, comme dans un traitement de texte.

Si nous avons affaire à une zone de l'état, la liste des attributs est évidemment
plus réduite.
La fenêtre graphique nous permet d'effectuer de multiples opérations à l'aide
de la souris :
modifier la taille des différentes zones qui constituent l'état, en tirant sur la barre qui
les sépare, lorsque le curseur prend la forme d'une croix. Appliquée à la zone "Détail",
cette opération a pour effet de modifier l'interligne à l'impression (dans la présentation
tabulaire) ;
déplacer les zones de texte et les étiquettes, soit séparément, soit en les regroupant par
sélection multiple (touche shift enfoncée). Lorsque le curseur prend la forme d'une main
ouverte, toutes les zones sélectionnées sont simultanément déplacées. Lorsque le curseur
prend la forme d'un index pointé, seule la zone concernée est déplacée. Attention ! ne
positionnez pas une zone de texte contre la limite de la zone imprimable, sinon l'imprimante
débitera une page blanche pour chaque page imprimée ;
modifier la taille d'une étiquette ou d'une zone de texte, en tirant sur les sommets ou
les milieux des côtés du rectangle correspondant ;
modifier la largeur de la zone imprimable. Réduisez-la si vous le désirez, mais ne
l'élargissez pas au-delà de sa taille initiale, même si vous avez réduit les marges entre temps.
Sinon, une page blanche accompagnera chaque page imprimée. Un bon conseil : ne touchez
pas à la largeur de la zone imprimable.

Le positionnement à l'aide de la souris ne permet pas d'obtenir un résultat précis.


Il est donc recommandé de perfectionner le positionnement en réglant les coordonnées dans
les feuilles de propriétés.
Attention ! Si nous plaçons une zone de texte dépendante dans l'en-tête de l'état,
seule la première valeur du champ correspondant sera imprimée (parce que l'en-tête est
unique). Ceci peut être mis à profit pour imprimer une information qui ne varie pas dans la
table sous-jacente (une date par exemple).
Le menu. Les fonctions de la rubrique "Format" deviennent actives lorsqu'une
étiquette ou une zone de texte est sélectionnée. Elles nous permettent :
d'aligner (plusieurs étiquettes ou zones de texte) ;
de régler la taille (au contenu, par exemple) ;
de fixer l'espacement horizontal (plus grand ou plus petit) entre étiquettes et/ou zones
de texte ;
de placer en premier plan ou en arrière plan (une image par rapport à une zone de
texte par exemple).

Les fonctions de la rubrique "Insertion" nous permettent :

© TIBB imbwangatroptard@[Link]
42
SQL
de numéroter les pages et d'imprimer la date et l'heure (si nous avons créé l'état sans
l'aide de l'assistant) ;
d'insérer des graphiques, des images ou des objets divers, que nous pouvons ensuite
placer où nous voulons dans l'état.

La boite à outils. Seuls sont réellement utiles :


l'outil "Sélection", qui est présent par défaut lorsque la boite à outils n'est pas
affichée ;
l'outil "Étiquette", qui permet en fait de créer une zone de texte indépendante ;
l'outil "Zone de texte". Lors de l'affichage ou de l'impression de l'état, le SGBD nous
demandera de saisir le contenu de cette zone ;
l'outil "Image", qui permet d'insérer une image dans l'état ;
l'outil "Saut de page". Dans un état en présentation verticale, l'insertion d'un saut de
page en bas de la zone Détail permet de n'afficher qu'un seul enregistrement par page (gare à
la consommation de papier !) ;
l'outil "Sous-formulaire". Les sous-formulaires seront étudiés au chapitre 24 suivant.

Les autres outils -- en particulier ceux qui permettent d'insérer des boutons, des
boutons radio, des cases à cocher, des listes, etc. -- n'ont pas d'utilité pour mettre en forme un
état qui est, par vocation, destiné à être imprimé.

6 - Conclusion
L'état s'avère être un objet utile dans le cas où l'impression de données issues
d'une BDD est une opération récurrente. La création d'un état bien présenté étant une
opération consommatrice de temps, il est préférable d'effectuer les impressions occasionnelles
à l'aide d'un tableur. De plus, l'usage d'un tableur est pratiquement obligatoire lorsqu'on veut
présenter les données sous forme d'un graphique.
Les recommandations qui s'appliquent aux arts graphiques en général sont
également valables pour les états en particulier. Il ne faut pas abuser des images, des fonds
colorés, des polices exotiques et des présentations tarabiscotées. La simplicité, la clarté et la
lisibilité priment.

Chapitre 25 : les échanges de données


1 - Introduction
De plus en plus, les applications échangent des données, et les SGBD n'y font
pas exception. Il y a bien sûr le fameux "copier-coller", qui marche en de nombreuses
occasions. Mais dans des cas plus difficiles ou plus spécifiques, il faut recourir à des
opérations d'importation ou d'exportation. C'est pourquoi, dans les menus des applications,
à la rubrique "Fichier", on constate de plus en plus souvent la présence des fonctions
"Importer..." et/ou "Exporter...".
Les BDD sont des réservoirs à données. Ces données ont peut-être été saisies au
clavier, mais la saisie manuelle est coûteuse, et le risque d'erreur est toujours présent. Chaque
fois que cela est possible, on saisit les données à l'aide de capteurs reliées à des ordinateurs

© TIBB imbwangatroptard@[Link]
43
SQL
(appareils de mesure, lecteurs de codes barres, scanners, etc.), avant de les importer dans une
base.
De plus, on constate une dématérialisation croissante des données échangées
entre les entreprises. Pour les opérations commerciales récurrentes, les bons de commande et
les factures imprimés vont peu à peu disparaître au profit de transmissions directes via
Internet (cela s'appelle le "e-procurement"). Toutes les données résultant de ces transactions
aboutiront dans des BDD par importation.
Il est bien rare que, dans une entreprise d'une certaine taille, toutes les données
soient stockées dans une seule et même BDD (et ce ne serait peut-être pas judicieux de le faire
-- il y a des discussions passionnées sur ce sujet). On est donc fatalement amené à transférer
des données d'une base à une autre. Le cas échéant, il peut être intéressant de transférer des
objets (requêtes, formulaires, états, macros, etc.), c'est à dire des structures et non plus des
données. Enfin, en cas de changement de matériel et/ou de logiciel, on peut être amené à
transférer une base entière d'un système informatique à un autre.
Certains échanges, bien sûr, peuvent être très difficiles à réaliser (entre des
systèmes informatiques n'utilisant pas le même système d'exploitation, par exemple), voire
même impossibles. Les divers SGBD que l'on trouve sur le marché sont plus ou moins
ouverts, et l'étude de l'import/export est donc très spécifique du système utilisé.
Comme pour les autres chapitres de ce tutoriel (ou tutorial, ou cours en ligne),
nous utiliserons le SGBD Access comme support pratique.

2 - L'importation de données de type texte


Les données que l'on veut importer dans une BDD se trouvent souvent dans de
simples fichiers texte. Ces derniers présentent en effet trois avantages déterminants :
on les génére très facilement ;
leur poids est modeste, parce que les balises de mise en forme sont absentes ;
les ordinateurs peuvent les lire aisément, par suite de l'absence d'un format
propriétaire.

Les tableaux n'existant pas dans les fichiers texte, les données d'un même
enregistrement sont rassemblées sur une même ligne (nous supposerons ici que c'est toujours
possible). Le passage d'un champ à l'autre est repéré par un caractère particulier réservé à cet
effet (espace, point virgule, etc.) et appelé caractère de séparation, ou par une tabulation. La
figure ci-dessous représente un exemple d'une telle disposition, où l'espace sert de caractère
de séparation.

Groupe X - Magasin Y
Date : 28/12/2002
Date Heure Caisse Produit Quant. Prix Total
28/12/2002 9:02:31 03 C-168324 1 24,95 24,95
28/12/2002 9:02:35 02 P-2896 3 13,55 40,65
28/12/2002 9:02:41 02 X-12709 1 6,90 6,90
etc......

A la fermeture du magasin, le fichier texte contenant le détail des ventes de la


journée est envoyé (via un réseau de transmission de données ) au centre de traitement

© TIBB imbwangatroptard@[Link]
44
SQL
informatique du groupe, où il est importé dans une base de données. Le lendemain matin, le
patron trouvera sur son bureau une synthèse des résultats de la veille, générée de manière
entièrement automatique...
Commençons, plus modestement, par importer manuellement un tel fichier dans
Access. Mais avant de commencer, il faut que nous décidions si nous importons dans une
table existante, ou si nous laissons au système le soin d'en créer une. Nous conseillons
vivement la première solution, et ce pour deux raisons :
on règle mieux les propriétés des champs dans la grille de création d'une table que
dans l'assistant d'importation ;
importer dans une table existante revient à réaliser une requête Ajout (les nouvelles
données viennent s'inscrire à la suite des précédentes), et c'est généralement le résultat que
l'on recherche.

Donc, avant d'importer, nous créons une table comportant sept champs (Date,
Heure, N°_caisse, Code_produit, Quantité, Prix_unitaire, Prix_total), dotés des types de
données et des propriétés adéquats, et en évitant les espaces dans leurs noms.
Nous lançons ensuite l'assistant "Importation de Texte" via "Fichier > Données
externes > Importer...". Il faut d'abord préciser l'extension du fichier à importer et son chemin.
On notera au passage la liste des formats qu'Access peut importer (outre le sien propre) :
dBase, Excel, HTML, Outlook, Lotus, Paradox, texte, XML et les formats des SGBD
respectant l'interface ODBC (Open DataBase Connectivity). Cette interface, créée par
Microsoft en 1993, permet à presque tous les SGBD de communiquer lorsqu'ils sont installés
sous Windows (il faut cependant que le pilote ODBC correspondant existe).
L'assistant démarre et nous conseillons de cliquer tout de suite sur le bouton
"Avancé...". La fenêtre "[Nom du fichier] Spécification d'importation" s'ouvre, qui nous
permet de régler tous les détails de l'importation :
Format du fichier : le fichier est-il "délimité" ou de "longueur fixe" ? Le premier cas
correspond à l'usage d'un caractère de séparation, le second à une tabulation. Dans le cas
présent, la réponse est "délimité" ;
Séparateur de champ : il faut indiquer au système quel est le caractère séparateur.
Dans le cas présent, la réponse est "space" ;
Délimiteur de texte : pour différencier les champs de texte des champs numérique, on
place parfois le texte entre des guillemets simples ou doubles. Dans le cas présent, la réponse
est "aucun" ;
Dates, heures et nombres : dans le cas présent, nous laissons les valeurs par défaut ;
Informations sur le champ : ces informations (nom, type de données, indexation)
doivent correspondre avec celles de la table dans laquelle nous allons importer. Le système
propose de ne pas importer le contenu de certains champs ("sauter"), ce qui rend service dans
certains cas.

Avant de quitter cette fenêtre, nous devons enregistrer toutes les informations
qu'elle contient en cliquant sur le bouton "Enregistrer sous..." et donner un nom au format
d'importation personnalisé que nous venons de créer.
Nous poursuivons avec l'assistant. Nous ne cochons pas "Première ligne contient
les noms des champs" pour deux bonnes raisons : ce n'est pas vrai, et les noms des champs
sont déjà déterminés puisque nous importons dans une table existante -- ce que nous
indiquons à l'étape suivant, en précisant le nom de la table (liste déroulante). Nous cliquons

© TIBB imbwangatroptard@[Link]
45
SQL
sur "Terminer", et le système nous prévient que toutes les données n'ont pas été importées
avec succès. La table que nous avions préparée se trouve ainsi remplie :

Les données des trois premières lignes du fichier texte n'ont pas pu être
importées, parce que leur type de données était incompatible (seul "Produit" est passé entre
les mailles). Une table contenant les erreurs d'importation a d'ailleurs été créée, dont voici le
contenu :

Ces erreurs ne se seraient pas produites si nous avions éliminé les trois premières
lignes du fichier avant de l'importer. Il faut cependant bien voir que si l'on importe un fichier
texte de plusieurs centaines de milliers de lignes, la probabilité de rencontrer quelques lignes
erronées n'est pas tout à fait nulle. Une coupure de courant, un incident nécessitant le
redémarrage de l'ordinateur, une machine débordée qui écrit comme elle peut dans son fichier
journal, un petit bug dans le logiciel... et voici créée une ligne qui ne s'importera pas
correctement. Mais la présence d'une à quelques lignes dans la table des erreurs d'importation
ne constitue pas un drame. On peut éliminer facilement les enregistrements déficients de la
table (dans laquelle s'est faite l'importation) à l'aide d'une requête suppression, le critère étant

© TIBB imbwangatroptard@[Link]
46
SQL
que l'un des champs au moins n'est pas renseigné (Est Null), alors qu'il devrait normalement
l'être.
Lorsqu'on importe régulièrement des données possédant la même structure, on
accélère considérablement la procédure en réutilisant le format d'importation. Pour ce faire, il
faut se rendre tout de suite dans la fenêtre des spécifications d'importation, cliquer sur le
bouton "Paramètres...", et choisir le bon format. Toutes les données correspondantes
s'inscrivent d'elles mêmes dans la fenêtre.
On peut encore aller plus vite en automatisant l'importation à l'aide d'une macro,
comme nous le verrons au chapitre 20 suivant.

3 - L'importation de données du web


On trouve de tout sur le web, y compris des tableaux de données sur les sujets les
plus divers. Il peut être utile de récupérer ces données dans un SGBD, ne serait-ce que pour
effectuer des requêtes. L'assistant d'importation d'Access reconnaît les tableaux dans une page
web, et en dresse la liste. La plupart de ces tableaux servent uniquement à la mise en page, et
il faut trouver dans la liste quel est le tableau qui contient les informations à importer.
A titre d'exemple, nous allons importer une liste d'imprimeries dont le nom
commence par un A, et qui se trouve dans les pages de liens imprimerie du CERIG (variante
sans cadres). Le première opération consiste à télécharger la page en question et à l'enregistrer
sur le bureau de l'ordinateur, grâce à la fonction "Enregistrer sous..." du navigateur.
La seconde opération consiste à lancer l'assistant d'importation, en lui indiquant
la page HTML. L'assistant dresse une liste de 11 tableaux, dont seul le huitième contient
l'information désirée. La suite des opérations se poursuit comme précédemment, mais nous
laissons cette fois au système le soin de créer la table correspondante. La figure ci-dessous en
représente les premières lignes.

Si l'on examine les propriétés de la table ainsi créée, on s'aperçoit que, pour les
champs de type texte (Ville, Activité) le système réserve automatiquement la place maximale
(255 caractères), même si aucune des chaînes de caractères importées n'atteint cette taille. On
peut toujours corriger après coup, mais on court le risque de tronquer certaines informations.
Si l'on importe dans une table existante, et qu'une chaîne est trop longue pour le champ, elle
sera là encore tronquée, mais le fait sera signalé dans le fichier des erreurs d'importation.

4 - L'importation d'objets
Tous les objets d'une BDD gérée par Access peuvent être importés dans une
autre base gérée par le même SGBD : tables, requêtes, formulaires, états, macros, modules.
Mais cela ne veut pas dire qu'ils fonctionneront à coup sûr après importation. Une requête, par
exemple, est basée sur une ou plusieurs tables ou feuilles de données. Si nous importons la

© TIBB imbwangatroptard@[Link]
47
SQL
requête, mais que l'une des tables manque, la requête ne peut pas fonctionner, et le système
nous en avertira.
Il arrive souvent que l'on ne s'intéresse qu'à une petite partie d'une grande base
de donnée, par exemple une semaine dans les opérations d'une année. On a alors intérêt à
créer des tables réduites à la semaine en question, puis à les importer dans une nouvelle base
avec tous les autres objets. On pourra effectuer les mêmes opérations que sur la base de
départ, mais avec 52 fois moins de données, ce qui va bien accélérer les opérations.
Pour voir fonctionner l'importation d'objets, nous suivons de nouveau le chemin
"Fichier > Données externes > Importer...". Nous indiquons au système un fichier Access
(.mdb), et la boite de dialogue suivante s'ouvre.

L'examen détaillé de cette boite révèle que :


tous les objets sont importables (voir les onglets) ;
en ce qui concerne les tables, on peut importer la structure seule ("Définition
uniquement"), ce qui correspond à une table vide, ou la structure et les données ("Définition
et données"). Nous retrouvons là le double aspect de l'objet table, sur lequel nous avons déjà
insisté ;
le même choix s'applique aux requêtes. Nous pouvons importer la structure seule
("Comme des requêtes"), ou la structure et le résultat ("Comme des tables").

Lorsque tous les objets désirés ont été sélectionnés (en cliquant dessus -- un
nouveau clic désélectionne), on valide par "OK", et l'importation s'effectue.

5 - L'exportation
Dès qu'un objet de la base (ex : table) est sélectionné, la fonction "Fichier >
Exporter..." devient active, et l'on peut se livrer aux opérations inverses de celles décrites ci-
dessus.

© TIBB imbwangatroptard@[Link]
48
SQL
L'exportation d'une table sous forme d'un fichier texte délimité peut servir de
dernier recours pour transférer des données d'une base à une autre, lorsque tous les autres
moyens ont échoué. L'opération d'exportation est sans douleur, il suffit d'indiquer au système
le caractère de séparation que l'on veut utiliser.
L'exportation d'un objet d'une base Access vers une autre base Access ne pose
pas de problème particulier. Si l'objet est une table, le SGBD demande si l'on veut exporter la
structure seule, ou la structure et les données ensemble.
L'échange de données entre Access et Excel est très aisé, et souvent pratiqué.
Certains utilisateurs trouvent commode de commencer une recherche d'information dans
Access, et de la terminer dans Excel. Il faut dire que la plupart des utilisateurs sont plus à
l'aise dans le second logiciel que dans le premier. Mais faut également reconnaître que la mise
en forme finale des données avant impression est plus facile à réaliser dans une feuille de
calcul d'Excel que dans un état d'Access.
L'exportation des données des BDD vers le web prend de plus en plus
d'importance. On distingue :
les pages web statiques, c'est à dire générées d'abord depuis une base de données,
puis mises en ligne sur un serveur web ;
les pages web dynamiques. Elles sont générées à la volée par un script côté serveur à
partir de données résidant dans une base de données, juste avant d'être envoyées au client
internaute.

Les deux types de pages ont leurs mérites et leurs inconvénients, et leurs
applications sont distinctes ; nous n'entrerons pas dans une discussion à ce sujet. Précisons
qu'Access ne permet pas de créer des pages dynamiques, et que son mode de création de
pages statiques est fort médiocre. L'opération n'est pas paramétrable, et le code HTML obtenu
n'est pas fameux. Pour faire communiquer une BDD (gérée sous Access) et le web, on utilise
généralement du logiciel tierce partie.

6 - Conclusion
Les échanges d'information (données et objets) entre BDD sont plus ou moins
faciles suivant les cas envisagés. De ce point de vue, Access est un SGBD relativement
ouvert, qui reconnaît plusieurs formats.
Les échanges de données et d'objets entre bases gérées par Access sont très aisés.
L'importation de données en provenance de fichiers texte ou HTML est bien gérée par
Access. L'exportation -- en particulier vers le web -- est médiocre, c'est un point faible de ce
SGBD.

Chapitre 26 : les macros (début)


1 - Introduction aux macros
Le terme "macro" est l'abréviation de "macro-instruction". Une instruction (ou
commande) est un ordre donné à un ordinateur pour qu'il exécute une action. En langage
machine ou en assembleur, on manie des instructions élémentaires que l'ordinateur comprend
directement. Dans un langage de plus haut niveau (exemple : Visual Basic, C, etc.), une
instruction entraîne en général l'exécution de plusieurs instructions élémentaires. Si l'on monte
encore d'un cran, on trouve la macro-instruction, dont l'exécution correspond à celle de

© TIBB imbwangatroptard@[Link]
49
SQL
plusieurs instructions. En clair, une seule macro-instruction entraîne l'exécution d'un grand
nombre de tâches élémentaires.
Cependant, les macros ne sont pas utilisées pour faire de la programmation à
proprement parler, et ce pour les raisons suivantes :
la notion de variable leur fait défaut. Exemple : si une macro ouvre un fichier, et si
vous changez le nom du fichier, vous devez corriger la macro en conséquence ;
le branchement conditionnel est soit absent, soit très sommaire. Les actions d'une
macro s'exécutent séquentiellement. Tout au plus peut-on rendre une exécution
conditionnelle ;
le traitement des erreurs n'existe pas. Si une macro provoque une erreur d'exécution,
elle affiche un message et s'arrête.

Le véritable usage des macros, c'est l'automatisation des tâches répétitives, que
l'on utilise Access ou tout autre logiciel. Une telle automatisation présente deux avantages
importants, qui justifient généralement le temps passé à écrire les macros :
elle fait gagner du temps ;
elle diminue le risque d'erreurs.

Bien entendu, il ne faut automatiser que des opérations qui ont été rodées
manuellement, et qui sont bien au point. Il s'agit là d'une remarque de bon sens, qui déborde
largement le cadre des macros.
Les macros sont très spécifiques d'un logiciel donné ; les macros d'Access, par
exemple, sont très différentes de celles d'Excel. On trouve des macros dans de nombreux
logiciels, et même dans certains systèmes d'exploitation. Leur conception, leur facilité
d'usage, et les services qu'elles rendent, varient beaucoup d'un logiciel à l'autre.

2 - Le rôle des macros dans les SGBD


Il est fréquent qu'une BDD soit alimentée de manière régulière en données, et
que les nouvelles données fassent l'objet d'opérations récurrentes telles que :
importation
reformatage (modifications, suppressions)
analyse (requêtes multiples)
enregistrement (hors de la BDD, sous un format particulier)
impression (états)
expédition par courrier électronique
exportation (vers une autre base ou un autre ordinateur), etc.

Des macros peuvent regrouper toutes les actions répétitives associées à ces
opérations, et c'est là leur principale application.
Une application secondaire des macros consiste à associer des actions à des
boutons. Tous les utilisateurs de SGBD qui aiment le décorum parsèment leurs formulaires et
leurs menus de boutons. Lorsqu'on examine la liste des actions que permettent les macros
d'Access, on voit clairement qu'un certain nombre d'entre elles ont été créées dans ce but.
C'est un aspect des macros que nous signalons, mais que nous n'approfondirons pas.
On notera que les professionnels qui utilisent Access pour développer des
applications, se servent généralement assez peu des macros. Ils préfèrent utiliser VBA (Visual
Basic for Applications), une extension du langage Visual Basic qui permet de manipuler les

© TIBB imbwangatroptard@[Link]
50
SQL
objets d'Access, sans présenter les limitations des macros. Les utilisateurs non professionnels
se trouvent plutôt dans la situation inverse, parce qu'apprendre à se servir des macros est
beaucoup -- beaucoup -- plus rapide que se familiariser avec VBA. C'est la raison pour
laquelle nous avons inclus ce chapitre dans le présent tutoriel dédié aux bases de données
relationnelles.
Comme pour les autres chapitres, nous utiliserons le SGBD Access comme
support pratique de ce tutoriel (ou tutorial, ou cours en ligne). Nous n'examinerons pas toutes
les actions utilisables pour créer une macro, car il en existe une bonne cinquantaine. Notre but
sera plutôt de montrer ce que l'on peut faire, et de souligner ce que l'on ne peut pas faire, avec
les macros. Notre choix comporte fatalement une forte part d'arbitraire, si bien que nous
acceptons par avance toutes les remarques et suggestions.

3 - L'objet macro dans Access


"Getting started", comme disent les anglophones ! Dans la colonne de gauche de
la fenêtre "Base de données", sélectionnez l'objet "Macro". Si vous n'avez pas encore créé de
macro, la fenêtre de droite est vide. Cliquez sur le bouton "Nouveau" : la fenêtre de création
d'une macro s'ouvre. Il n'existe pas d'assistant, il faut se débrouiller tout seul.
Le haut de la fenêtre comporte la grille de définition de la macro. La colonne de
gauche, intitulée "Action", comporte une liste déroulante qui propose, par ordre alphabétique,
toutes les actions disponibles, de "Actualiser" à "TrouverSuivant". Comme vous le constatez,
une macro d'Acces est constituée d'actions. Ces actions s'exécutent les unes après les autres,
dans l'ordre où vous les placez sur la grille.
Toujours dans le haut de la fenêtre, la colonne de droite permet d'écrire des
commentaires. Ils seront ignorés lors de l'exécution de la macro, mais ils se révéleront bien
utiles le jour où vous voudrez modifier une macro un peu ancienne.
Le bas de la fenêtre comporte, à gauche, une liste d'arguments spécifiques de
l'action que vous avez sélectionnée dans la liste déroulante. Certaines actions très simples
n'ont pas d'argument, mais c'est un peu l'exception. Exemples :
l'action "Agrandir" agrandit au maximum la fenêtre active, de telle sorte qu'elle
remplisse complètement la fenêtre Access ;
l'action inverse, "Réduire", iconise la fenêtre active, et la place en bas à gauche de la
fenêtre Access ;
l'action "Restaurer" rétablit la taille initiale de la fenêtre active agrandie ou iconisée ;
l'action "AfficherTousEnreg" synchronise une table ;
l'action "ArrêtMacro" peut marquer la fin de la liste des actions de la macro, ou
arrêter conditionnellement la macro en cours d'exécution ;
l'action "Bip" émet un bip sonore, pour attirer l'attention de l'opérateur ;
l'action "TrouverSuivant" sélectionne l'enregistrement qui suit l'enregistrement actif.

En bas à droite de la fenêtre s'affiche un commentaire spécifique de l'action que


vous avez sélectionnée, ou de l'argument que vous êtes en train de définir. En appuyant sur la
touche de fonction F1, vous obtenez une aide contextuelle.

4 - L'affichage d'un message


Nous commencerons par un exemple fort simple (et fort classique), qui ne
comporte qu'une seule action. Cette dernière consiste à afficher une boîte de message, que
l'opérateur ferme en l'acquittant.

© TIBB imbwangatroptard@[Link]
51
SQL
Dans la grille de création de macro, choisissez l'action "BoîteMsg". Cette fois,
des arguments sont nécessaires :
Message : vous pouvez écrire le texte du message qui sera affiché. Mais vous pouvez
aussi créer une expression qui effectuera des calculs ou opérera sur des chaînes, à condition
de la faire précéder du signe égal. Par exemple, saisissez "=Date()" (sans les guillemets), pour
afficher la date du jour. Ce sera toujours plus intéressant que d'afficher "Hello folks", comme
on le fait au début des cours de programmation ;
Bip : précisez par "Oui" ou par "Non" si vous voulez que l'affichage du message
s'accompagne d'un bip sonore ;
Type : définit l'image qui illustrera la boite de message. Pour la date du jour,
"Information" fera l'affaire ;
Titre : définit le texte qui s'affiche en haut de la boite de dialogue. Par exemple,
"Nous sommes le :" convient. Notez que l'argument "Titre" peut être traité comme l'argument
"Message".

Il ne vous reste plus qu'à appuyer sur le bouton "Exécuter". Le système vous
demande d'enregistrer d'abord la macro, et vous propose le nom "Macro1", ce qui peut
convenir à votre première macro (pour une macro utile, le nom du service rendu serait plus
avisé). Merveille ! cela marche (enfin, nous l'espérons), et vous obtenez le message suivant, à
la date près :

Acquittez le message et fermez la fenêtre de définition de la macro. Dans la


partie droite de la fenêtre "Base de données" figure désormais votre macro, sous le nom
"Macro1", précédée de l'icône spécifique des macros.
Sélectionnez votre macro : les icônes "Exécuter" et "Modifier" deviennent
actives. La seconde vous ramène dans la fenêtre de définition des macros, où vous pouvez
retravailler votre premier chef d'oeuvre à loisir. Par exemple, vous pouvez remplacer
"=Date()" par "=Temps()" pour obtenir l'heure, ou par "=Maintenant()" pour obtenir à la fois
la date et l'heure.
Les messages sont souvent utilisés en fin de macro, pour avertir l'utilisateur qu'il
doit reprendre la main, et lui rappeler éventuellement ce qu'il doit faire.

5 - L'importation de données
Nous avons montré au chapitre précédent comment importer dans Access les
données d'un fichier texte. Si une telle opération est répétée régulièrement, on gagnera du
temps en l'automatisant à l'aide d'une macro.
Nous avons vu que l'on pouvait enregistrer le format personnalisé d'importation
(boutons "Avancé...", puis "Enregistrer sous..."). Ce format contient la plupart des réponses

© TIBB imbwangatroptard@[Link]
52
SQL
aux questions posées par l'assistant. On peut le réutiliser à chaque importation manuelle, et
nous allons nous en servir pour créer la macro d'importation.
L'action correspondant à une importation de fichier texte s'appelle
"TransférerTexte" et possède sept arguments, dont les cinq premiers seulement nous
concernent :
Type transfert : nous permet de préciser "délimité" ;
Format : dans la liste déroulante, nous retrouvons le format d'importation que nous
avons créé lors de l'importation manuelle ;
Nom table : nous précisons la table dans laquelle les données seront introduites. Si
cette table existe déjà, les données seront rajoutées à celles déjà présentes ;
Nom fichier : le chemin complet d'accès au fichier doit être inscrit ici (exemple : C:\
Documents and Settings\Administrateur\Bureau\Tutoriel\[Link]) ;
Contient noms de champs : la réponse est "Oui" quand la première ligne du fichier
texte contient les noms des champs et que l'on veut les conserver. Présentement, la réponse
est "Non".

La macro est prête, il ne reste plus qu'à l'enregistrer, puis à l'exécuter. Bien
entendu, la macro n'est réutilisable que si les noms de fichier, de table, et de format ne
changent pas : nous butons là sur le fait que la notion de variable n'existe pas dans les macros.
En reprenant tel quel l'exemple du chapitre précédent, nous obtenons le résultat déjà cité :

Dans la version 2002 d'Access, l'importation via une macro est une opération
rapide (ce n'était pas le cas des versions plus anciennes). A titre d'exemple : sur un PC de
milieu de gamme, un fichier texte de 10 Mo, contenant 50.000 lignes de 10 champs chacune
(20 octets d'information en moyenne par champ), s'importe en moins de 10 secondes.

6 - La suppression d'enregistrements
Nous allons maintenant écrire une macro qui efface les trois premières lignes de
la table précédente. Rappelons-nous qu'une macro ne fait qu'enchaîner de manière
automatique des opérations qui sinon seraient effectuées une à une par l'opérateur. Pour
supprimer manuellement les trois premières lignes de la table, nous procédons de la manière
suivante :
nous ouvrons la table, car il est impossible de travailler dans une table fermée ;
nous plaçons le curseur sur la première ligne ;

© TIBB imbwangatroptard@[Link]
53
SQL
dans le menu "Édition" nous choisissons "Supprimer l'enregistrement". Nous
acquittons le message, l'enregistrement disparaît, et le curseur passe automatiquement sur la
ligne suivante ;
nous répétons l'opération une deuxième fois ;
nous répétons l'opération une troisième fois.

Nous allons, dans la macro, retrouver à peu de choses près les mêmes étapes. Les
actions utilisées sont les suivantes :
OuvrirTable. Cette action ouvre effectivement la table (si elle n'est pas déjà ouverte).
Il y a trois arguments. Le premier "Nom table" permet de choisir le nom de la table dans la
liste déroulante. Pour le second ("Affichage"), la bonne valeur est "Feuille de données". Pour
le troisième ("Mode données"), le bon choix est "Modification" ;
AtteindreEnregistrement. Cette action place le curseur sur une ligne spécifiée de la
table. Il y a quatre arguments, mais seuls les trois premiers nous concernent. La réponse à
"Type objet" est "Table", la réponse à "Nom objet" est le nom de la table, et la réponse à
"Enregistrement" est "Premier" de telle sorte que le curseur se place sur la première ligne. Si
la table n'avait pas été ouverte par l'action précédente, cette action arrêterait la macro avec
affichage d'un message d'erreur ;
Avertissements. En fixant l'argument "Avertissements actifs" à "Non", nous rendons
la macro silencieuse. Aucune confirmation ne nous sera demandée avant la suppression des
lignes. Seuls les messages inévitables (ex : message d'erreur) sont encore émis. Le but de ce
silence est de gagner du temps, une macro étant faite pour aller vite ;
ExécuterCommande. Pour l'unique argument "Commande" il faut choisir
"SupprimerEnregistrement". Cette action supprime la première ligne de la table. La deuxième
ligne devient la première, et le curseur s'y trouve placé ;
ExécuterCommande. Pour l'unique argument "Commande" il faut choisir
"SupprimerEnregistrement". Cette action supprime la première (ex-seconde) ligne de la table.
La deuxième (ex-troisième) ligne devient la première, et le curseur s'y trouve placé ;
ExécuterCommande. Pour l'unique argument "Commande" il faut choisir
"SupprimerEnregistrement". Cette action supprime la première (ex-troisième) ligne de la
table. La deuxième (ex-quatrième) ligne devient la première, et le curseur s'y trouve placé ;
ArrêtMacro. Cette action est facultative. Lorsqu'il n'y a plus d'actions à exécuter, la
macro s'arrête et les avertissements redeviennent actifs.

Enregistrez la macro, et refermez sa fenêtre. Dans la fenêtre Access, placez côte


à côte la fenêtre "Base de données" et la fenêtre de la table dans laquelle la macro opère.
Lancez la macro d'un double-clic, et observez bien. Dans la fenêtre de la table, les trois
premières lignes disparaissent l'une après l'autre en moins de 2 secondes.
Si vous le désirez, vous pouvez également exécuter la macro pas à pas pour voir
l'effet de chaque action. Ouvrez la macro en mode "Modifier", activez l'icône "Pas à pas"
de la barre d'outils, et lancez l'exécution de la macro. La fenêtre suivante s'ouvre, qui vous
permet d'exécuter la macro pas à pas, de l'arrêter, ou de l'exécuter en continu. A chaque
pression sur le bouton "Pas à pas", ou sur la touche P, une action s'exécute. Vous voyez ainsi
la fenêtre s'ouvrir, le curseur se mettre en place, la ligne s'effacer, etc.

© TIBB imbwangatroptard@[Link]
54
SQL

La macro que nous venons de créer comporte sept actions. Chaque action
correspond en gros à une instruction en VBA. Vous voyez ainsi d'où provient le terme de
macro-instruction.
On peut regrouper les deux macros précédentes, si bien que la suppression des
trois premières lignes de la table suit immédiatement l'importation des données.

Chapitre 28 : les formulaires simples


1 - Introduction
Le formulaire est souvent considéré comme le troisième objet des bases de
données, par ordre d'importance décroissante, après la table et la requête. En fait, son
importance réelle dépend de la manière dont on utilise le SGBD.
Le formulaire est avant tout un outil de saisie d'information au clavier. A ce
titre, il entre en concurrence avec :
l'écriture directe dans les tables ;
l'importation des données.

La facilité d'écriture directe dans les tables peut varier de très pratique à
parfaitement impraticable suivant les cas. Un formulaire peut rendre la saisie de certaines
informations plus facile, principalement dans les SGBD qui, au contraire d'Access, n'affichent
pas les sous-feuilles de données. Enfin, les formulaires permettent l'ajout de boutons, menus,
etc. qui donnent à l'application un aspect très "fini". Les SSII (sociétés de service en
informatique) soignent donc les formulaires pour donner la meilleure impression possible à
leur client -- surtout si ce dernier n'est pas capable de juger sur autre chose que la
présentation.
Certaines bases de données sont principalement alimentées en données par
importation des données : le formulaire ne sert alors plus à rien. C'est, par exemple, le cas
des magasins à grande surface, qui alimentent leur BDD directement et en temps réel depuis
les caisses enregistreuses. C'est aussi le cas des sites web qui déversent quotidiennement leur
fichier journal dans la BDD qui sert au suivi du site et à la mesure d'audience. C'est encore le
cas de tous ceux qui font de l'acquisition de données via des capteurs couplés à des
ordinateurs, etc.

© TIBB imbwangatroptard@[Link]
55
SQL
Accessoirement, le formulaire sert aussi d'outil de visualisation, c'est à dire de
consultation du contenu de la base à l'écran. On reproche parfois au formulaire de montrer les
enregistrements un par un, alors qu'une table en montre un grand nombre à la fois, mais on
peut concevoir le formulaire de telle sorte que sa présentation soit très proche de celle d'une
table.
Cette discussion peut en fait se résumer ainsi :
lorsque la BDD est utilisée par des personnes très diverses sans expérience
particulière en matière de SGBD, ou lorsque l'accès aux tables est interdit aux utilisateurs, ou
lorsque la saisie directe dans les tables est malaisée, les formulaires constituent un passage
obligé ;
lorsque la BDD est utilisée par un petit groupe de professionnels formés à l'usage des
SGBD, ou lorsque les données sont importées au lieu d'être saisies, les formulaires
constituent un simple habillage de la BDD et n'ont guère d'utilité.

Comme pour l'ensemble de ce tutoriel (encore appelé "cours en ligne" ou


tutorial), nous utiliserons le SGBD Access comme support pratique.

2 - La création d'un formulaire simple


Un formulaire est avant tout un outil permettant de saisir au clavier des données
qui sont immédiatement introduites dans une ou plusieurs tables. Le formulaire est donc lié à
une ou à plusieurs tables, et il hérite de leurs propriétés : types de données, propriétés des
champs, listes de choix et protection contre les doublons via un index. A l'inverse, les
propriétés du formulaire ne rejaillissent pas sur les tables sous-jacentes. Il arrive enfin que l'on
puisse attribuer à un champ de formulaire une propriété qui modifie ou contredit celle du
champ correspondant de la table.
Pour étudier les formulaires, nous utiliserons une table (nommée "Personnes")
dotée d'une liste de choix (nommée "Communes"), comme le montre la figure ci-dessous.
Nous faisons en sorte (comme expliqué au chapitre 3) que le nom de la commune, et non son
code, s'affiche dans le champ "Code_commune" de la table "Personnes".

Pour travailler sérieusement, nous créons un index sans doublon sur les champs
Nom+Prénom dans "Personnes", et sur les champs "commune+code postal dans
"Communes". Nous interdisons de plus le Null et la chaîne vide dans tous les champs sauf
"Adresse". Le champ "code_commune" de la table "Communes" est du type NuméroAuto.
Créons, pour commencer, un formulaire simple qui nous permette de saisir les
noms des communes et les codes postaux correspondants. Dans la fenêtre "Base de données",

© TIBB imbwangatroptard@[Link]
56
SQL
nous sélectionnons (colonne de gauche) l'objet "Formulaires". Nous double-cliquons sur
"Créer un formulaire à l'aide de l'Assistant" et nous répondons aux demandes de ce dernier :
d'abord, nous sélectionnons la table "Communes". Les champs disponibles s'affichent
(code_commune, commune, code postal), et nous sélectionnons les deux derniers. En effet le
code, qui sert à faire fonctionner la mécanique relationnelle, est implémenté par le système
lui-même (type de données NuméroAuto) ;
ensuite, nous choisissons une disposition -- "Colonne simple" par exemple ;
puis nous choisissons l'un des styles proposés ;
enfin nous nommons le formulaire "Formulaire des communes", et nous cliquons sur
"Terminer".

Voici comment se présente le formulaire, dont le nom apparaît désormais dans la


fenêtre "Base de données" :

Le formulaire est constitué d'étiquettes (les noms des champs dans la table) et de
contrôles correspondant aux champs de la table. Lorsqu'ils sont directement dérivés de la
table, les contrôles sont appelés "contrôles dépendants", ou encore "champs". La table à partir
de laquelle est construit le formulaire est la table sous-jacente.
Nous constatons d'abord que nous pouvons examiner le contenu de la table
"Communes" enregistrement par enregistrement, le formulaire jouant alors son rôle d'outil de
visualisation. Certes, l'aspect est plus joli que celui de la table, mais cette dernière présente
l'avantage de nous donner une vue globale des informations. Si nous avions choisi la
disposition "Tabulaire", nous aurions obtenu une présentation par lignes plus proche de la
table sous-jacente. La disposition "Feuille de données", quant à elle, fournit une présentation
pratiquement identique à celle de la table sous-jacente.
Nous constatons ensuite que nous pouvons nous placer sur la première ligne vide
de la table sous-jacente, et saisir des données (noms et prénoms des personnes). Ces données
sont automatiquement introduites dans la table sous-jacente, comme nous pouvons le
constater en fermant le formulaire et en ouvrant la table. Le formulaire joue alors son rôle
d'outil de saisie des données. Mais les problèmes de synchronisation que nous avons déjà
rencontrés demeurent : si nous laissons la table sous-jacente ouverte, nous constatons que les
données saisies dans le formulaire n'y apparaissent pas. On peut fermer, puis rouvrir la table
sous-jacente, pour que les nouvelles données s'y trouvent inscrites, mais il est plus simple de
rendre la table active, de cliquer dans le menu sur "Enregistrements", puis sur "Afficher tous
les enregistrements". La table se complète immédiatement.
Notons que le formulaire nous présente les informations dans l'ordre où elles se
trouvent dans la table sous-jacente. Pour faire en sorte que les informations apparaissent
triées, nous disposons de plusieurs méthodes :
nous pouvons effectuer une requête de sélection simple sur la table (en sélectionnant
tous les champs, en triant d'abord sur le nom et ensuite sur le prénom), puis créer le

© TIBB imbwangatroptard@[Link]
57
SQL
formulaire à partir de cette requête. Toutes les saisies que nous effectuons dans ce nouveau
formulaire sont automatiquement transmises à la table "Personnes", au travers (si l'on peut
dire) de la requête de tri ;
si un tri simple nous convient, nous plaçons le curseur dans le champ désiré du
formulaire, puis nous cliquons sur l'icône du tri ;
pour effectuer un tri multiple, nous cliquons dans le menu sur "Enregistrements", puis
sur "Filtrer", puis sur "Filtre/tri avancé..." et nous intervenons dans la grille qui s'affiche.

3 - La mise en forme du formulaire


Il est fréquent que les administrateurs de BDD empêchent les utilisateurs de voir
les tables (et par la même occasion, d'effectuer des requêtes -- quelle politique !). Les
formulaires constituent alors (avec les états et les menus, que nous étudierons plus loin) la
seule interface entre la base et ses utilisateurs. Le SGBD Access met à disposition des
concepteurs de BDD de multiples outils permettant de rendre cette interface aussi soignée que
possible. Avec la mise en forme du formulaire, nous entrons quelque peu dans le domaine de
l'informatique "cosmétique".
Sélectionnons le formulaire que nous venons de créer, et cliquons sur l'icône
"Modifier". Le formulaire s'ouvre en mode de création (on devrait dire plutôt en mode de
modification, car il est déjà créé). Notons que, à partir de l'option "Affichage" du menu, nous
pouvons passer du mode création au mode formulaire, ou au mode feuille de données, la
présentation duquel est très proche de celle de la table sous-jacente. Nous obtenons le même
résultat en cliquant sur l'icône située à gauche de la barre d'outils "Création de formulaire", à
condition que cette dernière soit affichée.
Comme les tables et les requêtes, le formulaire se présente donc sous deux
aspects :
la structure (titre, étiquettes, contrôles, etc.), que l'on définit en mode création ;
l'outil de saisie et de visualisation des données, que l'on utilise en mode formulaire.

Le mode création met à notre disposition de multiple outils (entre lesquels il


existe une redondance partielle) pour modifier le formulaire que nous avons créé. Nous
pourrions même les utiliser pour créer le formulaire de toutes pièces, mais il est plus simple
de passer d'abord par l'assistant. Ces outils peuvent être regroupés ainsi :
une intervention via un clic droit sur une partie spécifique du formulaire, et choix de
"Propriétés" dans la liste déroulante. Une boite de dialogue s'ouvre, dans laquelle nous
sélectionnons l'onglet "Format". Il nous est alors possible de régler de nombreux détails de
présentation ;
une intervention graphique directe dans la fenêtre. Nous pouvons développer les
parties "en-tête" et "pied de page", régler la hauteur et la largeur du formulaire, déplacer les
contrôles et les étiquettes, étendre le formulaire sur plusieurs pages (séparées ou en onglet),
etc. ;
une boite à outils qui s'affiche en même temps que le formulaire en mode création. Si
cette boite n'apparaît pas, cliquer sur "Affichage" dans le menu, et sélectionner "Boite à
outils".

La mise en forme d'un formulaire, avec ses très nombreuses possibilités, fera
l'objet d'une annexe (décembre 2002). Nous reviendrons plus loin sur certains usages

© TIBB imbwangatroptard@[Link]
58
SQL
particuliers de la boite à outils. Voici ce que devient la figure précédente après un léger lifting
:

4 - Le perfectionnement du formulaire
Pour modifier les propriétés d'un formulaire, il faut ouvrir sa feuille de propriétés
de la manière suivante :
sélectionner le formulaire ;
cliquer sur l'icône "Modifier" ;
cliquer sur l'icône "Propriétés" ou double-cliquer sur le carré noir qui se trouve en
haut et à gauche de la fenêtre du formulaire ;
sélectionner l'onglet "Données", qui donne accès à diverses propriétés du formulaire.

Dans le formulaire tel qu'il est, nous pouvons non seulement saisir de nouvelles
données, mais aussi modifier ou supprimer des données existantes. Cette possibilité peut être
fort dangereuse, et nous pouvons la supprimer en basculant la propriété "Modif autorisée" de
"Oui" à "Non". En revenant en mode formulaire, nous constatons que désormais, les données
enregistrées (par fermeture du formulaire) ne peuvent plus être modifiées. Cette interdiction
est très gênante en cas d'erreur de saisie, mais elle ne s'étend pas à la table sous-jacente.
Nous pouvons aller plus loin, et cacher complètement les enregistrements déjà
saisis. Les enregistrements nouvellement saisis seront cachés à leur tour dès que nous
refermerons le formulaire. Pour ce faire, nous basculons la propriété "Entrée données" de
"Oui" à "Non". En revenant en mode formulaire, nous constatons qu'aucune donnée ne
s'affiche. Nous pouvons, par contre, saisir de nouvelles données.
Nous pouvons aussi faire en sorte que le formulaire ne permette pas la
modification des données, c'est à dire qu'il serve uniquement de dispositif de visualisation.
Pour ce faire, nous basculons la propriété "Ajout autorisé" de "Oui" à "Non", puis nous
revenons au mode formulaire. Nous pouvons ainsi donner à un utilisateur la possibilité de
consulter la base, mais sans pouvoir en modifier le contenu.
Recréons le formulaire des communes en incluant le champ "code_commune".
Nous constatons que nous pouvons introduire le curseur dans ce champ, mais que nous ne
pouvons pas le modifier. Le type de données est NuméroAuto, et seul le SGBD peut écrire
dans ce champ. Dans le formulaire, cette propriété est héritée de la table sous-jacente. Pour ne
pas agacer la personne qui utilise le formulaire, nous pouvons faire en sorte que le curseur ne
passe plus dans le champ "code_commune". Plusieurs solutions s'offrent à nous.
Pour modifier les propriétés d'un contrôle ou d'une étiquette, nous pouvons faire
apparaître la feuille de données comme ci-dessus, et sélectionner l'objet dans la liste
déroulante qui se trouve tout en haut. Nous pouvons aussi sélectionner l'objet en mode
création , effectuer un clic droit, et choisir "Propriétés".
Sélectionnons l'onglet "Autres", et basculons la propriété "Arrêt tabulation" de
"Oui" à "Non". Quand nous revenons au mode formulaire, nous constatons que le curseur ne

© TIBB imbwangatroptard@[Link]
59
SQL
peut plus être placé dans le champ "code_commune", bien que la valeur de ce dernier
continue à s'afficher.
Nous pouvons aussi sélectionner l'onglet "Donnée", et basculer la propriété
"Activé" de "Oui" à "Non" (la propriété "Verouillé" étant sur "Non"). Quand nous revenons
au mode formulaire, nous constatons que le contrôle "code_commune" et son étiquette sont
grisés, comme lorsqu'une fonction n'est pas disponible dans un menu. De plus, le curseur ne
pénètre plus dans le champ. La figure suivante illustre cette situation :

Basculer la propriété "Verrouillé" à "Oui" (la propriété "Activé" étant sur "Oui")
a pour conséquence d'empêcher la modification du contenu du champ, sans en modifier
l'aspect et sans empêcher le curseur d'y pénétrer. Cela ne nous est d'aucune utilité dans le cas
présent, puisque le champ "code_commune" hérite déjà de cette propriété de par son type de
données NuméroAuto.
Pour consulter la suite, qui traite des formulaires basés sur deux tables, cliquez
sur la flèche droite ci-dessous.

Chapitre 29 : les formulaires sur deux tables


1 - Le formulaire avec liste de choix
Lorsque la table sous-jacente est dotée d'une liste (laquelle provient le plus
souvent d'une table auxiliaire), le formulaire en hérite automatiquement. Pour le montrer,
nous créons un formulaire sur la table "Personnes". Après un peu de mise en forme, il se
présente comme le montre la figure ci-dessous :

Dans la table "Communes", qui sert de liste, nous avons déclaré nulle la largeur
de la colonne "code_commune". Comme pour une table, c'est alors le nom de la commune qui
s'affiche à la place du code. Nous devrions donc modifier l'étiquette, en remplaçant
"Code_commune" par "Commune", afin que l'utilisateur du formulaire ne soit pas troublé.

© TIBB imbwangatroptard@[Link]
60
SQL

© TIBB imbwangatroptard@[Link]
61
SQL
2 - Le formulaire avec liste indépendante

Le logiciel Access nous permet de créer une liste indépendante, contenant par exemple les
noms et prénom déjà saisis. Pour ce faire, nous ouvrons le formulaire en mode création, puis
nous agrandissons la zone d'en-tête pour y placer la liste. Si la boite à outils n'est pas
apparente, nous cliquons sur "Affichage", puis "Boite à outils" (nous pouvons aussi cliquer
sur l'icône ). Dans cette boite, nous activons l'icône "Assistants contrôle". Comme son
3 - Le formulaire basé sur deux tables
L'assistant permet de créer un formulaire basé sur plusieurs tables. Il suffit de
répéter l'opération de saisie des champs pour les tables considérées. Réalisons l'expérience à
l'aide des tables "Personnes" et "Communes". La procédure est la suivante :
nous sélectionnons la table "Personnes", et nous introduisons tous les champs
correspondants ;
nous sélectionnons la table "Commune", et nous sélectionnons le champ "Code
postal". Il est inutile que nous sélectionnions le champ "Code _commune", puisque nous
l'avons déjà pris dans la table "Personnes". Il est également inutile que nous sélectionnions le
champ "Commune", puisque le nom de la commune s'affichera dans le contrôle
"Code_commune", comme nous l'avons vu dans le paragraphe précédent ;
l'assistant nous demande alors si nous souhaitons afficher les données "par
Communes" ou "par Personnes". Nous choisissons la deuxième option, et nous voyons que
cela nous conduit à un formulaire unique. Nous ferons l'essai de la première option dans le
paragraphe suivant ;
nous choisissons la disposition et le style, nous renommons le formulaire, et nous
examinons le résultat, qui est représenté sur la figure ci-dessous, après un peu de mise en
forme.

Nous constatons que, si nous saisissons ou modifions le nom d'une commune, le


code postal correspondant s'affiche automatiquement -- ce que nous ne pouvons pas faire dans
une table. Il faut par contre éviter que l'opérateur puisse modifier le code postal. Pour cela,
nous désactivons ou nous verrouillons le contrôle "Code postal".

nom l'indique, cette icône active un certain nombre d'assistants relatifs à la création de
contrôles.

© TIBB imbwangatroptard@[Link]
62
SQL
Nous cliquons ensuite sur l'icône "Zone de liste déroulante", puis à l'endroit
choisi pour implanter la liste. La boite de dialogue "Assistant de zone de liste déroulante"
s'ouvre. Nous dialoguons ainsi avec l'assistant :
nous choisissons la troisième option "Rechercher un enregistrement dans mon
formulaire basé sur la valeur que j'ai sélectionnée..." ;
nous sélectionnons ensuite le nom et le prénom ;
nous réglons graphiquement la largeur des colonnes ;
nous baptisons l'étiquette "Liste des personnes", et nous cliquons sur terminer ;
nous ajustons graphiquement la position de la liste (lorqu'une petite main noire
apparait) ;
nous réglons les détails de présentation, puis nous basculons en cliquant sur l'icône
"Ouvrir" pour observer le résultat.

Si nous avons pris la précaution de baser le formulaire sur une requête qui trie la
table "Table01", la liste indépendante que nous venons de créer est triée par ordre
alphabétique. Nous pouvons donc vérifier rapidement si le nom d'une personne donnée a déjà
été saisi. De plus, si nous sélectionnons un nom dans cette liste, les informations
correspondantes s'affichent immédiatement, comme le montre la figure ci-dessous. Par contre,
le fait de changer d'enregistrement n'a pas d'influence sur la liste indépendante.

Une telle liste indépendante rend-elle réellement service ? A l'internaute de


juger !

4 - Le formulaire avec sous-formulaire


Reprenons la procédure précédente, mais demandons cette fois l'affichage des
données par communes. Le dialogue avec l'assistant s'établit ainsi :
nous sélectionnons la table "Communes", et nous introduisons les champs
"commune" et "Code postal" ;
nous sélectionnons la table "Personnes", et nous introduisons les champs "nom",
"prénom" et "adresse" ;
nous demandons l'affichage des données par Communes, dans un formulaire avec
sous-formulaire, et non dans des formulaires attachés ;
la meilleure disposition pour un sous-formulaire est "feuille de données" ;
nous choisissons un style, nous renommons le formulaire et le sous-formulaire, et
nous terminons l'opération.

© TIBB imbwangatroptard@[Link]
63
SQL
Nous obtenons ainsi un formulaire principal dans lequel nous pouvons saisir des
noms de communes avec leur code postal,et les utiliser dans le sous-formulaire associé. La
figure ci-dessous illustre le résultat obtenu :

Nous voyons que le sous-formulaire correspond -- avec une présentation


différente -- à la sous-table que nous avons rencontrée au chapitre 3, et dont nous
reproduisons un exemple ci-dessous :

Il est possible d'introduire plusieurs sous-formulaires dans un même formulaire,


mais l'assistant ne permet d'en créer qu'un seul. Les sous-formulaires supplémentaires peuvent
être introduits avec l'aide de la boite à outils.

5 - Conclusion
Ce chapitre, étalé sur deux pages web, donne un aperçu de l'objet formulaire
dans les bases de données. Il ne prétend pas, loin de là, épuiser le sujet, qui est fort vaste. A un
formulaire on peut associer des boutons, de la programmation événementielle, etc. On peut
modifier la présentation, l'étaler sur plusieurs pages, créer des onglets, etc. Du point de vue de
l'auteur de ces lignes, tout ceci ressemble un peu à du décorum, mais... à chacun ses goûts !
En fait, ce n'est pas tellement le formulaire que nous critiquons, mais l'usage qui
en est fait. Les administrateurs de BDD font presque toujours en sorte que les utilisateurs ne
puissent voir les données qu'à travers les formulaires. Privés de tables, les utilisateurs ne
peuvent pas créer de requêtes, et la base de données de l'entreprise perd pour eux une grosse

© TIBB imbwangatroptard@[Link]
64
SQL
part de son intérêt. Se doter d'un outil coûteux (très coûteux, même, dans la plupart des cas),
et en limiter le plus possible l'usage, quel paradoxe !

© TIBB imbwangatroptard@[Link]

Vous aimerez peut-être aussi