3. Les associations et les jointures

Rappel sqlite3

Dans sqlite3, il faut faire ces 2 commandes pour avoir un meilleur affichage.

        
Copié
.header on .mode column .nullvalue <NULL>

Mise en contexte

La problématique

Imaginez qu'il faut créer une base de données qui doit enregistrer l'information des cours du Cégep.

Dans la table Cours, il faut indiquer le sigle du cours, le nom du cours, le nom de l'enseignant et le courriel de l'enseignant.

Voici un exemple des données de la table.

        
Copié
Sigle NomCours Enseignant CourrielEnseignant Anciennete ---------- –--------- ---------- ---------- ---------- 420-3N3-DM Base de Données François St-Hilaire francois.st-hilaire@cegepdrummond.ca 2 420-3W1-DM Web 3 Benoit Tremblay benoit.tremblay@cegepdrummond.ca 1 420-1N1-DM Initiation à la prog Stéphane Janvier stephane.janvier@cegepdrummond.ca 8 420-1R1-DM Initiation à l'ordi François St-Hilaire francois.st-hilaire@cegepdrummond.ca 2 420-3N1-DM PPO 2 Louis Marchand louis.marchand@cegepdrummond.ca 15 420-3N2-DM Native 2 Louis Marchand louis.marchand@cegepdrummond.ca 15

Notez que François St-Hilaire se répète deux fois, car l'enseignant donne deux cours. Le courriel et l'ancienneté de l'enseignant se répètent également sur les 2 cours.

Il serait difficile de changer le nom du cours, car il devra être changé dans tous les enregistrements qui le contiennent. Il y aurait inévitablement des cas où le nom aura été changé dans un enregistrement, mais pas dans un autre. Il y aura donc une incohérence dans les données.

Imaginez maintenant qu'il faut ajouter le champ téléphone de l'enseignant. Il faudra s'assurer qu'il est ajouté à tous les enregistrements existants.

Également, avoir de l'information en double utilise plus d'espace dans la base de données.

Cette représentation fait feuille Excel. Dans les bases de données relationnelles, il faut éviter ce genre de table.

Imaginez un système de classement papier. Il existe une fiche par cours. Cette fiche est dans un classeur et elle contient toute l'information du cours avec le nom de l'enseignant, son courriel et son ancienneté. Il faut changer l'ancienneté sur toutes les pages. Ce n'est pas pratique.

La solution

La solution est d'utiliser plusieurs tables en fonction du concept et de faire des relations entre elles.

Imaginez toujours le système de classement papier. Il y a maintenant un tiroir pour les cours et un tiroir pour les enseignants. Le tiroir pour les cours contient les fiches des cours et le tiroir des enseignants contient les fiches des enseignants.

La fiche cours au lieu d'avoir toutes l'information de l'enseignant, elle a seulement une référence vers le numéro de fiche de l'enseignant. Donc s'il faut modifier l'ancienneté de l'enseignant, ce sera fait uniquement sur la fiche enseignant. La fiche cours ne sera pas modifiée.

À l'inverse, s'il faut modifier l'enseignant d'un cours, il n'est pas nécessaire de modifier toute l'information de l'enseignant pour ce cours. Il suffit d'indiquer le numéro de fiche du nouvel enseignant.

SQLite est une base de données relationnelle. Elle permet de faire des liens entre des tables en indiquant des références.

Chacun des tiroirs sera une table.

  • Cours
  • Enseignants

Voici le diagramme entité-associations (DEA) de la nouvelle base de données.

Il y a maintenant 2 tables. Entre les tables, il y a une ligne. Cette ligne indique qu'il y a une relation entre les tables.

La table Cours a une colonne EnseignantId pour indiquer quel enseignant a ce cours.

Les notions du DEA seront expliquées dans un prochain cours.

Clé étrangère

Une clé étrangère est également appelée foreign key en anglais ou abrégé FK. Une clé étrangère est également une contrainte sur la table.

La table qui contient la clé étrangère est nommée la table enfant. La clé étrangère est liée à la clé primaire de la table parent.

Dans l'exemple ci-dessus, quelle est la table enfant et quelle est la table parent ? La table enfant est Cours et la table parent est Enseignants.

Voici comment voir les contraintes de clés étrangères avec SQLiteStudio.

En jaune, il y a la pastille dans la colonne Foreign Key que le champ EnsignantId est une clé étrangère.

Dans la section du bas, il y a la description de la contrainte de clé étrangère.

En bleu, c'est le nom de la colonne de la table enfant, donc la table en cours de visualisation.

En rose, c'est le nom de la table parent.

En vert, c'est le nom de la clé primaire de la table parent.

Idéalement, il est préférable de nommer la clé étrangère dans la table enfant comme la clé primaire de la table parent si le nom n'est pas générique comme Id.

Sinon, certaines équipes mettent en préfixe le nom de la table parent et ensuite le nom de la clé primaire comme nom de clé étrangère.

Dans l'exemple, la clé primaire contient déjà le nom de la table, il n'est donc pas nécessaire de l'ajouter.

Il est possible d'avoir plusieurs clés étrangères dans une table. Une table peut être une table enfant et parent selon le cas. Il y aura des exemples plus complexes sur les relations entre les tables.

Formulaire

Dans un programme informatique, il y aurait un formulaire pour ajouter des données dans la table Cours.

Lorsqu'il y a des clés étrangères, généralement, le champ est une liste déroulante pour indiquer tous les choix possibles.

Insertion

Lorsqu'il y a une contrainte sur une table, elle sert à valider les données si elles sont valides en fonction des contraintes.

Pour une clé étrangère, la contrainte s'assurera que la clé étrangère existe dans la table parent.

Effectuez un SELECT sur la table Enseignants pour vous assurer quelle est vide.

        
Copié
SELECT * FROM Enseignants;

Donc, il ne sera pas possible de faire aucune insertion dans la table Cours , car la clé étrangère ne sera pas liée à une clé primaire de la table Enseigants.

Effectuez la commande ci-dessous.

        
Copié
INSERT INTO Cours(Sigle, Nom, HeureTheorie, HeurePratique, HeureMaison, EnseignantId) VALUES ('420-3N3-DM', 'Exploitation d''un système de gestion de base de données', 2, 2, 2, 1);

Il n'y a pas eu d'erreur et l'enregistrement est dans la table.

SQLite a une particulié. Par défaut, les contraintes de clés étrangères sont désactivées. Pour Les autres bases de données, les contraintes sont toujours activées. Il n'est pas très pratique de l'avoir non activé, car c'est la contrainte la plus importante dans une base de données relationnelles.

Pour l'activer, il faut faire cette commande. Il est important de toujours faire cette commande à partir de maintenant au début des scripts d'insertion.

        
Copié
PRAGMA foreign_keys = ON;

Ensuite, effectuez cette insertion.

        
Copié
INSERT INTO Cours(Sigle, Nom, HeureTheorie, HeurePratique, HeureMaison, EnseignantId) VALUES ('420-3N1-DM', 'Programmation orientée objet 2', 3, 3, 2, 2);

Le système retournera une erreur Runtime error: FOREIGN KEY constraint failed (19);

L'ordre de l'insertion est très important lorsqu'il y a des relations entre les tables.

L'insertion doit être faite dans la table parent avant d'insérer des valeurs dans la table enfant qui utilise une clé étrangère.

        
Copié
--Valeurs de la table parent INSERT INTO Enseignants(EnseignantId, Prenom, Nom, Courriel, Anciennete) VALUES (1, 'François', 'St-Hilaire', 'francois.st-hilaire@cegepdrummond.ca', 2), (2, 'Louis', 'Marchand', 'louis.marchand@cegepdrummond.ca', 15), (3, 'Stéphane', 'Janvier', 'stephane.janvier@cegepdrummond.ca', 8), (4, 'Benoit', 'Tremblay', 'benoit.tremblay@cegepdrummond.ca', 1), (5, 'Frederic', 'Montembeault', 'frederic.montembeault@cegepdrummond.ca', 5); --Valeurs de la table enfant INSERT INTO Cours(Sigle, Nom, HeureTheorie, HeurePratique, HeureMaison, EnseignantId) VALUES ('420-3N1-DM', 'Programmation orientée objet 2', 3, 3, 2, 2), ('420-3N2-DM', 'Développement d''application native 2', 2, 2, 1, 2), ('420-1N1-DM', 'Initiation à la programmation', 3, 3, 2, 3), ('420-1R1-DM', 'Initiation à l''ordinateur et ses composantes', 2, 3, 1, 1);

Sélection avec jointure interne : INNER JOIN

Effectuez la commande SELECT.

        
Copié
SELECT * FROM Cours;

Qui est l'enseignant #2 ? Vous avez peut-être la réponse facile, car l'insertion vient d'être faite. Mais imaginez qu'il y a 300 enseignants et que l'insertion a été faite par un collègue. Il serait plus difficile de se rappeler qui est l'enseignant 2.

Jusqu'à maintenant, vous seriez en mesure de me répondre en effectuant une 2e requête.

        
Copié
SELECT Prenom, Nom FROM Enseignants WHERE EnseignantId = 2;

Mais il faut présenter à l'utilisateur les cours sous cette forme en une seule requête.

        
Copié
Sigle HeureTheorie HeurePratique HeureMaison Courriel ---------- ------------ ------------- ----------- ------------------------------------ 420-3N1-DM 3 3 2 louis.marchand@cegepdrummond.ca 420-3N2-DM 2 2 1 louis.marchand@cegepdrummond.ca 420-1N1-DM 3 3 2 stephane.janvier@cegepdrummond.ca 420-1R1-DM 2 3 1 francois.st-hilaire@cegepdrummond.ca 420-3N3-DM 2 2 2 francois.st-hilaire@cegepdrummond.ca

Voici la syntaxe pour faire une sélection avec une jointure interne.

        
Copié
SELECT ... FROM tableGauche INNER JOIN tableDroite ON conditionDeJointure INNER JOIN tableDroite2 ON conditionDeJointure2

La requête compare chaque enregistrement de la première table avec chaque enregistrement de la 2e table afin de trouver tous ceux qui satisfont la condition. Quand la condition est satisfaite, les champs des deux tables sont combinés afin de créer un nouvel enregistrement.

La condition de jointure est le lien entre la clé étrangère et la clé primaire.

Pour obtenir le résultat, il faut faire cette requête.

        
Copié
SELECT Sigle, HeureTheorie, HeurePratique, HeureMaison, Courriel FROM Cours INNER JOIN Enseignants ON Cours.EnseignantId = Enseignants.EnseignantId;

Il est possible d'inverser les tables de gauche et de droite. Il n'y a pas de différence dans le cas d'une jointure interne.

        
Copié
SELECT Sigle, HeureTheorie, HeurePratique, HeureMaison, Courriel FROM Enseignants INNER JOIN Cours ON Enseignants.EnseignantId = Cours.EnseignantId;

Par convention, il faut mettre du côté droit de la condition de jointure, la table de droite et à gauche de la condition la table de gauche.

Remarquez que l'enseignant Benoit Desrosiers n'est pas dans la liste. La jointure interne valide qu'il y a des enregistrements dans la table de droite et dans la table de gauche en fonction de la condition de jointure.

Il est possible d'ajouter des conditions additionnelles avec une clause WHERE.

        
Copié
SELECT Sigle, HeureTheorie, HeurePratique, HeureMaison, Courriel FROM Enseignants INNER JOIN Cours ON Enseignants.EnseignantId = Cours.EnseignantId WHERE Sigle LIKE '420-3%'; -- Pour obtenir les cours de la 3e session.

Conflit de nom de colonne

Il faut afficher les données suivantes.

        
Copié
Sigle Nom Prenom Nom ---------- ------------------------------------------------------- -------- ---------- 420-3N1-DM Programmation orientée objet 2 Louis Marchand 420-3N2-DM Développement d'application native 2 Louis Marchand 420-1N1-DM Initiation à la programmation Stéphane Janvier 420-1R1-DM Initiation à l'ordinateur et ses composantes François St-Hilaire 420-3N3-DM Exploitation d'un système de gestion de base de données François St-Hilaire

Essayez ce SELECT.

        
Copié
SELECT Sigle, Nom, Prenom, Nom FROM Cours INNER JOIN Enseignants ON Cours.EnseignantId = Enseignants.EnseignantId;

Le système vous retourne cette erreur : Parse error: ambiguous column name: Nom.

Lorsqu'il y a un conflit de nom du champ, il faut spécifier le nom de la table en préfixe. table.champ.

        
Copié
SELECT Sigle, Cours.Nom, Prenom, Enseignants.Nom FROM Cours INNER JOIN Enseignants ON Cours.EnseignantId = Enseignants.EnseignantId;

La requête ci-dessus fonctionne, mais elle n'est pas recommandée.

Il est préférable de toujours mettre le nom de la table devant le champ lorsqu'il y a une jointure pour tous les champs.

Il est possible de faire des jointures sur plusieurs tables, il peut devenir difficile de savoir d'où provient un champ.

Cette nomenclature doit toujours être utilisée lorsqu'il y a des jointures.

        
Copié
SELECT Cours.Sigle, Cours.Nom, Enseignants.Prenom, Enseignants.Nom FROM Cours INNER JOIN Enseignants ON Cours.EnseignantId = Enseignants.EnseignantId;

Il faut également mettre le nom de la table dans la clause WHERE.

        
Copié
SELECT Cours.Sigle, Cours.Nom, Enseignants.Prenom, Enseignants.Nom FROM Cours INNER JOIN Enseignants ON Cours.EnseignantId = Enseignants.EnseignantId WHERE Cours.Nom LIKE '%2'; --Le nom du cours se termine par 2

Alias

Un alias permet de renommer un champ ou une table pour faciliter la requête ou l'affichage

Exécutez la requête ci-dessous.

        
Copié
SELECT Cours.Sigle, Cours.Nom, Enseignants.Prenom, Enseignants.Nom FROM Cours INNER JOIN Enseignants ON Cours.EnseignantId = Enseignants.EnseignantId;

Le résultat est

        
Copié
Sigle Nom Prenom Nom ---------- ------------------------------------------------------- -------- ---------- 420-3N1-DM Programmation orientée objet 2 Louis Marchand 420-3N2-DM Développement d'application native 2 Louis Marchand 420-1N1-DM Initiation à la programmation Stéphane Janvier 420-1R1-DM Initiation à l'ordinateur et ses composantes François St-Hilaire 420-3N3-DM Exploitation d'un système de gestion de base de données François St-Hilaire

Il y a 2 fois la colonne Nom.

Pour les différencier, il faut que ce soit NomCours, NomEnseignant et PrenomEnseignant. Il faut ajouter le mot-clé AS après le champ et spécifier le nouveau nom d'affichage.

        
Copié
SELECT Cours.Sigle, Cours.Nom AS NomCours, Enseignants.Prenom AS PrenomEnseignant, Enseignants.Nom AS NomEnseignant FROM Cours INNER JOIN Enseignants ON Cours.EnseignantId = Enseignants.EnseignantId;

Le résultat.

        
Copié
Sigle NomCours PrenomEnseignant NomEnseignant ---------- ------------------------------------------------------- ---------------- ------------- 420-3N1-DM Programmation orientée objet 2 Louis Marchand 420-3N2-DM Développement d'application native 2 Louis Marchand 420-1N1-DM Initiation à la programmation Stéphane Janvier 420-1R1-DM Initiation à l'ordinateur et ses composantes François St-Hilaire 420-3N3-DM Exploitation d'un système de gestion de base de données François St-Hilaire

Table

Lorsqu'il y a plusieurs jointures, il arrive parfois que le programmeur préfère renommer la table pour simplifier les requêtes.

Il est important de noter que le mot-clé AS n'est pas utilisé pour une table.

Il faut mettre après la déclaration de la table, son alias.

        
Copié
SELECT c.Sigle, c.Nom AS NomCours, e.Prenom AS PrenomEnseignant, e.Nom AS NomEnseignant FROM Cours c INNER JOIN Enseignants e ON c.EnseignantId = e.EnseignantId;

La déclaration de la table se fait dans le FROM et dans le JOIN

Concaténation : ||

Il est possible de concaténer plusieurs champs ensemble. Il faut utiliser la double pipe.

Attention : le symbole pour la concaténation est variable en fonction de la base de données utilisées.

Par exemple, il faut afficher la pondération du cours dans ce format T-P-M.

        
Copié
SELECT Sigle, Nom, HeureTheorie || '-' || HeurePratique || '-' || HeureMaison FROM Cours WHERE Sigle = '420-3N1-DM';

Le résultat sera similaire à l'affichage ci-dessous

        
Copié
Sigle Nom HeureTheorie || '-' || HeurePratique || '-' || HeureMaison ---------- ------------------------------- ---------------------------------------------------------- 420-3N1-DM Programmation orientée objet 2 3-3-2

Le nom du champ concaténé n'est pas idéal. Il est possible d'utiliser un alias.

        
Copié
SELECT Sigle, Nom, HeureTheorie || '-' || HeurePratique || '-' || HeureMaison AS Ponderation FROM Cours WHERE Sigle = '420-3N1-DM';

Le résultat.

        
Copié
Sigle Nom Ponderation ---------- ------------------------------- ----------- 420-3N1-DM Programmation orientée objet 2 3-3-2

Reste de la base de données

Voici le reste de la base de données.

La table Programmes contient tous les programmes d'études collégiales. Elle a une clé étrangère vers la table enseignant pour indiquer qui est l'enseignant coordonnateur.

La table Etudiants contient la liste de tous les étudiants. Elle a une clé étrangère vers la table Programmes pour indiquer le programme d'étude de l'étudiant.

La table Programmes est donc la table enfant de la table Enseignants pour sa relation coordonnateur et elle est la table parent pour la relation programme d'étude de l'étudiants.

La table Etudiant a une 2e clé étrangère vers la table Pays pour connaitre le pays d'origine de l'étudiant.

Exercices

Si ce n'est pas déjà fait, télécharger la base de données des exercices du cours #3 sur LEA.

Insertion

Pour les clés étrangères, vous devez trouver celle correspondante dans la table. Dans le cas que la valeur n'existe pas dans la table parent, vous devez la créer en utilisant vos propres valeurs.

Table Cours

SigleNomDescriptionHeureTheorieHeurePratiqueHeureMaisonEnseignant
420-3R1-DMRéseau informatique 1Ce cours montre les bases de la réseautique.222Frederic Montembeault
420-5R1-DMRéseau informatique 2Ce cours montre comment construire un réseau complexe.244Frederic Montembeault
420-3W1-DMDéveloppement d'applications Web 3null232Benoit Tremblay

Table Programmes

ProgrammeIdCodeNomEstTechniqueCoordonnateur Enseignant
1420-B0Techniques de l'informatique1Frederic Montembeault
2200-B0Sciences de la nature0Sylvain Poulin
3241-A0Techniques de génie mécanique1Cindy Asselin
4243-BBTechnologie de l’électronique : Ordinateurs et réseaux1Frederic Montembeault

Table Etudiants

DAPrenomNomCourrielProgrammePays
09452145SoniaRodriguesonia.rodrigue@etu.cegepdrummond.caTechniques de l'informatiqueCanada
22026544Jean-MarcLeclerc-Morinjean-marc.leclerc-morin@etu.cegepdrummond.caTechniques de l'informatiqueCanada
22985654SoufianeDjamelsoufiane.djamel@etu.cegepdrummond.caTechniques de l'informatiqueAlgérie
14485965LiseZourilise.zouri@etu.cegepdrummond.caSciences de la natureCanada
19874562ÉtienneGosselinetienne.gosselin@etu.cegepdrummond.caSciences de la natureFrance
21212565CindyAsselincindy.asselin@etu.cegepdrummond.caTechnologie de l’électronique : Ordinateurs et réseauxCanada
22545744JoëlleSte-Mariejoelle.ste-marie@etu.cegepdrummond.caTechniques de génie mécaniqueFrance
08065432DamienTurgeondamien.turgeon@etu.cegepdrummond.caSciences de la natureCanada

Sélection

Pour chacune des sélections, utilisez des alias de table et de champ lorsque c'est nécessaire.

  1. Affichez tous les cours (Signe et Nom) de la première session avec le prénom et le nom de l'enseignant.
  2. Affichez tous les cours qui ont une description.
  3. Affichez tous les cours qui ont 2 heures et plus de théorie.
  4. Affichez tous les cours (Sigle et nom) qui ont uniquement 1 heure à la maison avec le prénom et nom de l'enseignant.
  5. Affichez tous les cours qui ont plus de 5 heures de cours de théorie et de pratique combiné.
  6. Affichez tous les enseignants que leur id est un nombre pair. Il faut utiliser un modulo %.
  7. Affichez tous les programmes qui sont ne sont pas une technique.
  8. Affichez tous les programmes qui sont une technique avec le nom du coordonnateur.
  9. Affichez tous les enseignants (EnseignantId, Prenom, Nom) et leur programme de coordination (ProgrammeId, Nom)
  10. Affichez tous les étudiants (Prenom, nom et courriel) avec le nom de leur pays. Triez par nom de pays, ensuite le prénom de l'étudiant et finalement par le nom de l'étudiant.
  11. Affichez tous les étudiants (Prenom, nom et courriel) qui proviennent de la France.
  12. Affichez tous les étudiants avec les champs suivants : DA, NomComplet (concaténation de prénom et nom), le nom du programme.
  13. Affichez tous les étudiants avec les champs suivants : DA, nom complet (concaténation de nom et prénom, séparé par une virgule), le nom du programme et le nom du pays.
  14. Affichez tous les étudiants (Nom et Prenom uniquement) qui ont le code du programme 420-B0 et que leur pays est Canada.
  15. Affichez tous les étudiants (DA, nom et prénom), avec le nom du programme, le prénom du coordonnateur et le nom du coordonnateur.
  16. Affichez tous les étudiants (Prenom, nom, courriel et nom pays) qui proviennent du Canada et qui ont l'enseignant #5 comme coordinateur de programme.

Sélection avec jointure externe : LEFT OUTER JOIN

Préparation

Il y a un nouvel enseignant dans le département.

Effectuez cette insertion.

        
Copié
INSERT INTO Enseignants(EnseignantId, Prenom, Nom, Courriel, Anciennete) VALUES (8, 'Pierre-Luc', 'Boulanger', 'pierre-luc.boulanger@cegepdrummond.ca', 1);

La problématique

Il faut lister la liste de tous les enseignants avec leurs cours. Par contre, il y a des enseignants sans cours.

La jointure interne sort tous les enregistrements dont la condition de jointure est remplie.

        
Copié
SELECT Enseignants.Prenom, Enseignants.Nom, Cours.Sigle, Cours.Nom FROM Enseignants INNER JOIN Cours ON Enseignants.EnseignantId = Cours.EnseignantId;

Le résultat sera ceci.

        
Copié
Prenom Nom Sigle Nom -------- ------------ ---------- -------------------------------------------- Louis Marchand 420-3N1-DM Programmation orientée objet 2 Louis Marchand 420-3N2-DM Développement d'application native 2 Stéphane Janvier 420-1N1-DM Initiation à la programmation François St-Hilaire 420-1R1-DM Initiation à l'ordinateur et ses composantes Frederic Montembeault 420-3R1-DM Réseau informatique 1 Frederic Montembeault 420-5R1-DM Réseau informatique 2 Benoit Tremblay 420-3W1-DM Développement d'applications Web 3

Solution

Pour avoir Pierre-Luc Boulanger, il faut faire une jointure externe.

La jointure externe permet de retourner les enregistrements de la table de gauche, même si aucun enregistrement de la table de droite répond à la condition de jointure.

Les champs des enregistrements de la table droite sans valeur sont NULL.

Il faut remplacer INNER JOIN par LEFT OUTER JOIN.

        
Copié
SELECT Enseignants.Prenom, Enseignants.Nom, Cours.Sigle, Cours.Nom FROM Enseignants LEFT OUTER JOIN Cours ON Enseignants.EnseignantId = Cours.EnseignantId;

Le résultat sera ceci :

        
Copié
Prenom Nom Sigle Nom ---------- ------------ ---------- -------------------------------------------- François St-Hilaire 420-1R1-DM Initiation à l'ordinateur et ses composantes Louis Marchand 420-3N1-DM Programmation orientée objet 2 Louis Marchand 420-3N2-DM Développement d'application native 2 Stéphane Janvier 420-1N1-DM Initiation à la programmation Benoit Tremblay 420-3W1-DM Développement d'applications Web 3 Frederic Montembeault 420-3R1-DM Réseau informatique 1 Frederic Montembeault 420-5R1-DM Réseau informatique 2 Sylvain Poulin <NULL> <NULL> Cindy Asselin <NULL> <NULL> Pierre-Luc Boulanger <NULL> <NULL>

Donc la requête indique que Sylvain Poulin, Cindy Asselin et Pierre-Luc Boulanger n'ont pas de cours.

Les enseignants coordonnateurs

Voici un exemple de requête pour avoir la liste des enseignants et leurs programmes de coordination. Il faut avoir tous les enseignants, même ceux sans programme de coordination.

        
Copié
SELECT Enseignants.Prenom, Enseignants.Nom, Programmes.Code, Programmes.Nom FROM Enseignants LEFT OUTER JOIN Programmes ON Enseignants.EnseignantId = Programmes.CoordonnateurEnseignantId;

Le résultat.

        
Copié
Prenom Nom Code Nom ---------- ------------ ------ ------------------------------------------------------ François St-Hilaire <NULL> <NULL> Louis Marchand <NULL> <NULL> Stéphane Janvier <NULL> <NULL> Benoit Tremblay <NULL> <NULL> Frederic Montembeault 243-BB Technologie de l'électronique : Ordinateurs et réseaux Frederic Montembeault 420-B0 Techniques de l'informatique Sylvain Poulin 200-B0 Sciences de la nature Cindy Asselin 241-A0 Techniques de génie mécanique Pierre-Luc Boulanger <NULL> <NULL>

Exercices

  1. Ajoutez un nouveau pays.
  2. Affichez la liste de tous les pays et des étudiants. Les pays sans étudiants doivent être dans la liste.
  3. Affichez le nom des pays qui n'ont aucun étudiant.
  4. Ajoutez 2 nouveaux programmes.
  5. Affichez la liste de tous les enseignants coordonnateurs (prénom et nom) avec le nom du programme et la liste des étudiants (prénom et nom). Les programmes sans étudiant doivent être dans la liste. Affichez les programmes sans étudiant en premier et ensuite il faut avoir le nom du programme en ordre alphabétique.

Version originale par François St-Hilaire

Mise à jour 2023 par Pierre-Luc Boulanger