La base etude
Pour illustrer les requêtes sur une BD, nous allons utiliser la base etude.sqlite.
Nous présentons ci-dessous les tables de cette base. Pour chaque table est donnée son entête (les attributs) et quelques lignes de la table, ainsi qu'une lecture des données.
Nous n'apprendrons pas à construire des bases de données avec toute la rigueur nécessaire (cela nécessiterait un temps d'enseignement plus long que celui dont on dispose en ICN, pour en savoir plus vous pouvez taper "formes normales d'une BD relationnelle" dans un moteur de recherche). Quelques remarques sont toutefois faites ci-dessous dans la description des tables pour souligner quelques types de problème qui se posent avec une BD mal construite.
La table "personne".
id_personne est l'identifiant d'une ligne (clef primaire).
| id_personne | nom | prenom | anneeNaissance |
|---|---|---|---|
| 1 | Labrosse | Adam | 2000 |
| 2 | Gemlamorte | Adèle | 1985 |
| 3 | Auboisdormant | Abel | 2001 |
| 4 | Etpan | Ahmed | 1975 |
| 5 | Térieur | Alain | 1999 |
| 6 | Térieur | Alex | 1976 |
Code de définition de la table :
CREATE TABLE "personne" (
"id_personne" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,
"nom" VARCHAR NOT NULL ,
"prenom" VARCHAR NOT NULL ,
"anneeNaissance" INTEGER NOT NULL
)
La table "cours".
id_cours est l'identifiant d'une ligne (clef primaire). id_enseignant est une clef étrangère faisant référence à la clef primaire de la table "personne". Par exemple, le cours d'identifiant 1 est un cours sur la théorie des graphes et ce cours a été donné par l'enseignant d'identifiant 2, c'est-à-dire Adèle Gemlamorte.
| id_cours | id_enseignant | intitule |
|---|---|---|
| 1 | 2 | théorie des graphes |
| 2 | 4 | programmation objet |
| 3 | 6 | programmation fonctionnelle |
| 4 | 8 | théorie des automates |
| 5 | 10 | base de données relationnelle |
| 6 | 13 | réseaux |
Code de création de la table :
CREATE TABLE "cours" (
`id_cours` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`id_enseignant` INTEGER,
`intitule` VARCHAR NOT NULL,
FOREIGN KEY(`id_enseignant`) REFERENCES personne
)
La table "horaire".
id_horaire est la clef primaire.
| id_horaire | plage |
|---|---|
| M1 | 8h-9h |
| M2 | 9h-10h |
| M3 | 10h-11h |
| M4 | 11h-12h |
| AM1 | 14h-15h |
| AM2 | 15h-16h |
Code de création de la table :
CREATE TABLE "horaire" (
`id_horaire` TEXT NOT NULL,
`plage` TEXT NOT NULL,
PRIMARY KEY(id_horaire)
)
La table "aSuivi".
Lecture : l'étudiant d'identifiant 1 (Adam Labrosse) a suivi les cours d'identifiant 1 et 7 (théorie des graphes et langage python), il a obtenu la note de 15 en théorie des graphes et la note de 16 en langage python.
| id_etudiant | id_cours | note |
|---|---|---|
| 1 | 1 | 15 |
| 1 | 7 | 16 |
| 1 | 12 | 7 |
| 3 | 7 | 12 |
| 3 | 16 | 14 |
| 5 | 11 | 17 |
| 5 | 15 | 16 |
| 7 | 16 | 18 |
| 7 | 18 | 15 |
| 9 | 7 | 16 |
| 9 | 10 | 18 |
| 11 | 12 | 13 |
| 11 | 14 | 15 |
| 12 | 6 | 10 |
| 12 | 9 | 12 |
| 15 | 8 | 16 |
| 15 | 6 | 14 |
| 16 | 8 | 9 |
| 16 | 5 | 14 |
| 19 | 2 | 14 |
| 19 | 1 | 18 |
| 19 | 11 | 17 |
| 21 | 10 | 8 |
| 21 | 13 | 12 |
| 21 | 4 | 15 |
Code de création de la table ci-dessous. On voit au passage que l'on peut imposer la contrainte note au moins égale à 0 et au plus égale à 20 : si l'utilisateur se trompe en rentrant une note, le SGBD lui signalera qu'une contrainte n'est pas respectée. Le contrôle par le SGBD de telles contraintes est évidemment l'un des intérêts d'un SGBD.
CREATE TABLE "aSuivi" (
`id_etudiant` INTEGER NOT NULL,
`id_cours` INTEGER NOT NULL,
`note` INTEGER CHECK(note >= 0 AND note <= 20),
FOREIGN KEY(`id_etudiant`) REFERENCES personne,
FOREIGN KEY(`id_cours`) REFERENCES cours
)
- Sur cette table, vous remarquez une erreur de conception: elle ne présente pas de clef primaire. Un SGBD bien conçu ajoute dans ce cas automatiquement un identifiant qui permettra de pallier cette erreur de conception; mais il est déconseillé très fortement de procéder ainsi.
- Il est obligatoire d'avoir un identifiant sur chaque ligne : si deux lignes sont identiques, soit il y a redondance d'informations (et vu la taille des bases de données actuelles, ceci doit absolument être évité car cela augmente en particulier le temps de tout traitement sur la base), soit il y a effectivement deux informations très proches (par exemple deux personnes ayant même nom et prénom) et dans ce cas, il est clair que la base doit vous permettre de les distinguer.
- On peut remarquer également que dans l'état actuel, on pourrait rentrer deux fois un couple (étudiant , cours), ce qui n'a pas de sens : un étudiant ne suit pas deux fois le même cours (on suppose ici que la base concerne une année fixée). Les SGBD permettent d'ajouter des contraintes pour signaler à l'utilisateur lorsqu'il entre dans la base deux lignes incompatibles.
- Ici plutôt que de définir une telle contrainte, nous allons faire du couple (id_etudiant, id_cours) la clef primaire d'une ligne, cela imposera la contrainte d'unicité également.
Le code de définition de la table devient ainsi :
CREATE TABLE "aSuivi" (
`id_etudiant` INTEGER NOT NULL,
`id_cours` INTEGER NOT NULL,
`note` INTEGER CHECK(note >= 0 AND note <= 20),
FOREIGN KEY(`id_etudiant`) REFERENCES personne,
FOREIGN KEY(`id_cours`) REFERENCES cours,
PRIMARY KEY ([id_etudiant],[id_cours])
)
La table "salle".
| nom | id_cours | id_horaire |
|---|---|---|
| A101 | 1 | M1 |
| A101 | 2 | M2 |
| B126 | 4 | M4 |
Dans la salle A101 a eu lieu entre 8h et 9h (les jours ne sont pas indiqués ici pour ne pas alourdir...), le cours de théorie des graphes.
Code de création de la page :
CREATE TABLE "salle" (
`nom` TEXT NOT NULL,
`id_cours` INTEGER NOT NULL,
`id_horaire` INTEGER,
FOREIGN KEY(`id_cours`) REFERENCES cours,
FOREIGN KEY(`id_horaire`) REFERENCES horaire,
PRIMARY KEY ([nom],[id_horaire])
)
Avant de lancer des requêtes sur cette base, vous devriez constater à nouveau des possibilités d'incohérence : on risque fort d'avoir inscrit des étudiants sur deux cours différents se déroulant en même temps, ou deux cours dirigés par le même enseignant sur une même plage horaire... Les SGBD permettent évidemment de définir également des contraintes de ce type afin que l'utilisateur soit prévenu dès qu'il cherche à rentrer une valeur incompatible avec les valeurs déjà présentes.
Nous ne détaillerons pas plus avant ces contraintes dans ce cours qui est surtout destiné à vous apprendre comment interroger une base de données existante.