📱

Get Our Mobile App

Take your business learning on the go!

Download on the App StoreGet it on Google Play

Benjamin N'Guyen : Bases de données

Centre International de Rencontres Mathématiques1:39:43

Transcription

Donc cette première session, c'est majoritairement ce que j'ai déjà fait l'année dernière, alors en plus court, parce que j'avais pris au moins 3 heures pour faire la même chose. J'avais fait un certain nombre de choses programme aussi l'année dernière, donc là je me je me concentre plus sur le sur le programme.

Alors juste en mots, moi je suis donc Benjamin Guen, du laboratoire PRISME, donc Université de Versailles Saint-Quentin, et je fais partie de l'équipe projet INRIA SMITH, c'est-à-dire Systèmes d'Information Sécurisés et Mobiles. Nous, on travaille essentiellement sur les bases de données, sur du matériel sécurisé embarqué, donc des bases de données à empreinte très légère, pas beaucoup de mémoire, pas beaucoup de puissance de calcul, et cetera. Et en contrepartie, on a de la sécurité importante sur toutes les les opérations.

Le le cours que j'ai fait l'année dernière, il a un petit peu évolué avec d'autres collègues, donc Serge Abitbou, vous connaissez sans doute, du Conseil National du Numérique, euh Léon Cachant et INRIA, donc Yannick Lebrac, un de vos collègues, il est prof au lycée Montesquieu à au Mans, et Pierre Senard, qui est prof à Télécom Paris. Donc on a rédigé un support de cours centré sur la partie base de données. Hein, il y a le il y a le livre Informatique pour tout ce qui est sorti avec une partie base de données, hein, qui qui traite le programme, euh pas forcément écrite par des spécialistes. Et donc ça, c'est quelque chose d'un petit peu plus complet, euh et avec un certain nombre de développements qui ne sont pas forcément programme, mais c'est pour avoir le le bagage théorique pour aborder les bases de données, je dirais tranquillement et de manière intéressante, pas simplement du point de vue applicatif.

Donc ce que je vais faire, voilà, cette première séance, des rappels, enfin pour ceux qui étaient l'année dernière, autour du programme de CPGE. Et la séance numéro 2, donc quelque chose qui est totalement reprogramme et qui n'a rien à voir. Donc là, c'est plutôt une conférence, un peu comme les les autres que vous avez cette semaine, sur les transactions, c'est-à-dire qu'est-ce qui se passe quand on veut gérer plusieurs utilisateurs sur une base de données en même temps. Et ça, c'est une partie d'un cours que moi je fais en en M2, notre M2 base de données, enfin s'appelle Analyse et Conception de Systèmes d'Information SR.

Voilà. Donc euh sur cette première partie, une toute petite introduction, puis je vais présenter les concepts des SGBD. La partie très longue sera cette partie sur les langages d'interrogation. Euh donc ça, c'est des choses dont j'ai déjà parlé l'année dernière. Euh ce ce que j'ai rajouté, c'est une petite méthodologie de résolution de problème. Donc on va dire une sorte de recette, quoi, pour réussir à à écrire une requête compte tenu d'un d'une question qu'on se pose en en langage naturel. Et puis quelques transparents sur les architectures. C'était aussi quelque chose qui était au programme.

Des exercices, si jamais on a le temps, euh mais euh bon, ça m'étonnerait. Voilà, c'est pas que j'ai pas envie d'en faire, il y en a il y en a, il y a des corrections dans le poli, euh et et et donc on en rajoute au fur et à mesure, hein. Si jamais vous voulez les faire, que vous avez des questions, n'hésitez pas à me contacter euh via via mail ou là oralement, tant que je suis là. Je serai là ce soir, ce soir aussi. Bon.

Par rapport au programme officiel, hein, qui euh euh je dirais tel qu'il est défini, euh l'idée, c'est d'expliquer d'abord la nécessité des bases de données par rapport à simplement l'utilisation des fichiers. Donc ça, je vais en parler un petit peu après, comme comme introduction. Je pense que c'est une manière intéressante, hein, de d'introduire le les bases de données. Et puis il y a le contenu, donc le vocabulaire. Alors je trouve que vocabulaire, c'est un petit peu réducteur, c'est plutôt les concepts euh autour pour des bases de données. On demande de présenter à chaque fois sur une, enfin, dans une perspective applicative. Je ne savais pas bien si c'était quelque chose de positif, négatif, s'il fallait être content que ce soit quelque chose qui ait des applications, au contraire, se dire mince, non, ça devrait être présenté dans une perspective théorique. Donc bon, je je sais pas trop ce qu'il faut penser de ce commentaire. Euh en tout cas, c'est présenté avec des exemples concrets, hein. Je veux dire, on fait des bases de données, donc c'est des personnes, c'est des comptes en banque, et cetera, hein. Bon, ça, c'est ça ça c'est sûr.

Donc il y a une deuxième partie sur les opérateurs de le des bases de données. Donc ça, c'est autour de l'algèbre relationnelle, avec des précisions qui expliquent qu'on fait que des choses simples, hein, grosso modo. Et puis finalement, discuter de la partie client-serveur ou architecture 3 tiers. Donc là, je ferai deux transparents dessus, parce que euh bon, ça, c'est quelque chose qui n'est pas spécifique aux bases de données. Et bon, de mon point de vue, c'est euh c'est un peu bizarre de de vouloir juste mettre ça. Donc moi, je le traiterai de manière assez superficielle.

Si euh si j'étais vous, mais bon, euh voilà. Donc après, l'idée, c'est de faire un certain nombre d'exercices pratiques. Hein, je pense que comme vous allez le voir, c'est assez, enfin, finalement, les les concepts et toutes les opérations qu'on fait se disent assez rapidement. Un ou deux cours suffisent pour présenter l'ensemble des concepts nécessaires, et après, il faut pratiquer, hein, pour pour réussir à à comprendre, parce qu'il y a un certain, on voit pas forcément, en se posant simplement la question en français, ce qui est compliqué, ce qui ne l'est pas. Donc faut vraiment un petit peu pratiquer pour euh pour pour voir. Donc il y a une partie importante qui doit être disons centrée autour des exercices, hein, je pense. Voilà.

Puis après, il détaille un petit peu les attendus. Alors en lisant les attendus, on comprend que les personnes qui ont écrit le programme imaginent qu'il faudrait que les élèves aient un niveau disons de débutant, c'est-à-dire comme s'ils avaient suivi un tutoriel quelconque sur internet pour faire des bases de données. Donc moi, c'est pas mon point de vue, hein. Je pense que c'est des élèves de CPGE, donc il faudrait leur donner des bagages plus importants que simplement j'ai suivi un tutoriel, j'ai créé ma base de données en cliquant sur trois boutons, et puis j'ai pas tout compris ce qui se passait. Et puis j'ai pas l'impression que ce soit très dur, parce que bon, voilà, les bases de données, ça fait quand même appel à à des mathématiques non triviales et à des problèmes qui sont assez compliqués. Donc faut pas que ça se résume, comme c'est indiqué dans le programme, à du pouce-bouton pour pour novice. Ça, ça peut être fait par n'importe qui.

Alors voilà. Donc l'introduction, c'est justement de dire, bah, si on veut gérer des données, on sait ouvrir des fichiers, les écrire sur le disque. Donc bah, il suffit de faire ça. Et puis on va stocker, dès lors qu'on a une application qui gère des données, on va stocker les informations sur le disque dans des fichiers, et puis ça suffira. Alors on va évidemment vouloir interroger ces données. Donc on écrira des programmes pour interroger ces données. Si on veut calculer une moyenne, faudra qu'on lise le fichier, qu'on repère où sont les informations, et puis qu'on fasse un petit un petit calcul. Alors tant qu'on on gère des petits volumes de données, tant qu'on est chacun dans son coin, éventuellement, ça peut ça peut suffire. Mais dès qu'on a des grosses applications qu'on cherche à lancer et tout un tas de problèmes essentiellement liés autour de la durabilité, la résistance aux pannes, donc la robustesse de votre système, pas le fait que bah, j'ai effacé mon fichier par erreur, du coup j'ai perdu toutes mes données. Et ben, on rentre dans la problématique des bases de données. C'est-à-dire que les bases de données répondent à tout un tas de questions qui sont autour de simplement la gestion de données sur sur un fichier, on parle particulièrement comment modifier efficacement ces données, comment les interroger efficacement, comment sécuriser l'accès, et cetera, et cetera.

Si on si on se place pas dans une optique de base de données et qu'on se dit bon ben, on va juste écrire des programmes en C, en Python, en n'importe quoi, euh qu'est-ce qu'on ferait ? On définirait une structure de données. Donc là, l'exemple, c'est des comptes en banque, hein, c'est c'est l'exemple traditionnel des bases de données, puisque dans les années 70, voilà, ça a été inventé autour de ça, autour de la gestion des des des informations bancaires. Donc on a un compte en banque qui a un identifiant, une chaîne de caractère, et puis des opérations qui sont faites sur ce compte, donc débit ou crédit, qui est un tableau d'une certaine longueur, voire de longueur illimitée, enfin bref, ne détaillons pas, de de réels. Et si on veut calculer le solde d'un compte, ben on va écrire une fonction, une fonction solde qui prend comme paramètre un compte, qui retourne un réel, et puis qui fait un calcul en faisant une boucle. Voilà. Donc là, je pourrais dire, B, très bien, je sais gérer des données. Et après, il me suffirait d'écrire toutes ces informations dans des fichiers, et puis ce sera ce sera nickel.

Alors bah, premier problème, c'est que ben, je les écrire dans un fichier, ok, mais c'est pas si simple. Alors déjà, comment les stocker ? Il faut définir un format de fichier. Alors je vais dire, ouais, je vais mettre une entrée par ligne, je vais la séparer par des virgules, et cetera. Bon, faudra après, si je commence à avoir des millions d'opérations, alors pour des banques, c'est des millions d'opérations à la seconde, euh bon, va falloir savoir où les placer et ainsi de suite, hein. Donc c'est pas forcément compliqué, c'est pas forcément simple. Si je veux modifier les données, j'écris un programme. Si je veux sécuriser les données, j'écris un programme. Si je veux écrire une interrogation différente, poser une autre question, j'écris un programme. Bref, je je m'en sors plus. Et vous savez certainement qu'écrire des programmes, c'est assez compliqué, il y a souvent des bugs, et ça demande un développement qui est assez qui est assez compliqué et assez long.

Donc l'idée, c'est que en fait, bah, il y a tout un tas de de difficultés et de problèmes autour des formats de fichiers, autour de la redondance de données, là, j'ai pas insisté dessus, mais il peut y avoir tout un tas d'incohérences dans mes fichiers, je les ai recopiés, je sais pas comment ça marche exactement, le coût élevé du développement des des requêtes, c'est-à-dire l'interrogation, donc le fait qu'il va falloir faire un programme à chaque fois, maintenir ces programmes, ils ont peut-être écrit été écrits dans un langage ancien, euh et puis donc les les gens ne les utilisent plus. Gérer, et ça, c'est extrêmement important, euh parce que effectivement, les bases de données, c'est quelque chose d'assez pragmatique. Gérer les pannes. Qu'est-ce qui se passe si bah, j'ai une panne de courant sur mon ordinateur ? Alors bah, si vous étiez en train de faire un calcul, vous dites, c'est pas grave, j'ai relancé le calcul. Quand c'est une base de données qui conserve tout l'historique des données bancaires, euh voilà, d'une entreprise, c'est un petit peu plus embêtant. Si on dit, mais on va relancer, et puis bah, et puis quoi ? Euh voilà. Donc il faut absolument qu'on perde aucune des données qui rentre dans dans le système. Pareil, si je veux partager les données ou les sécuriser, tout ça va falloir faire des développements supplémentaires et puis les refaire à chaque fois.

Donc les SGBD, alors SGBD, ça veut dire un Système de Gestion de Base de Données, c'est une espèce d'ensemble de à la fois de concepts et puis de de disons de de logiciels qui veulent répondre à l'ensemble de la problématique de la gestion de données. Donc ça résout tout ce problème-là avec tout un tas d'avantages. Donc l'indépendance physique, c'est-à-dire que on va pas savoir comment sont stockées les données, c'est le c'est le SGBD qui va se débrouiller pour faire ça. Il va choisir des structures de données optimales pour pour les les informations qu'on rentre dedans. Donc ça, ça permet de ne rien connaître aux fichiers, ne rien connaître au système d'exploitation, ne rien connaître à ce genre de choses, et quand même pouvoir interroger les données. L'indépendance logique, c'est-à-dire le fait d'avoir mes données vues, enfin juste les données dont j'ai besoin, utiles et utilisables par par mon application. Donc si jamais j'étais encore dans le cas des fichiers, ben peut-être que je serai intéressé par un bout du fichier, une autre application serait intéressée par un autre bout. Est-ce qu'il faudrait faire deux fichiers ? Est-ce qu'il faudrait découper le fichier et cetera ? Vous voyez que c'est c'est compliqué. Donc là, c'est tout est séparable de manière assez assez simple.

Le fait aussi que ce soit plus facile d'écrire des questions sur sur ces données. Alors donc ça, c'est parce que le langage qui est utilisé est un langage déclaratif, donc SQL. Donc ça, je vais en parler longtemps par par la suite. Le fait que la conception aussi de tous les toutes les données qu'on met dedans est plus simple. Donc là, c'est autour du modèle entité-association. Je l'avais détaillé l'année dernière, c'est quelque chose qui est en programme. Bon, moi qui me paraît important, mais je vais pas en parler cette cette année pour des raisons de temps et cetera et cetera. Donc là, ça, c'est un certain nombre d'avantages. Et puis il y a des des parties, on va dire plus plus avancées, qui permettent de faire fonctionner les SGBD. Et donc là, il y a eu toute euh un tas de choses qui ont été faites dans le domaine de la recherche, et puis après, tout ça, ça a été appliqué par des entreprises qui fabriquent des SGBD. Donc ça peut être des éventuellement des SGBD qui sont en en open source, hein, mais il y a quand même des gens qui qui les ont programmés. Donc autour, c'est peut-être le problème le plus le problème le plus important, hein, mais je j'en parlerai ben peut-être une autre fois si je reviens autour de l'exécution et l'optimisation des requêtes. Donc comment est-ce qu'on fait véritablement pour exécuter euh des requêtes ? Qu'est-ce qu'il y a derrière le le le langage SQL, hein ? Donc là, on parle gestion de fichiers, justement, on parle d'index, et ainsi de suite. Bon, l'intégrité logique, c'est comment faire pour que les données soient cohérentes à l'intérieur de la base. Et puis ce dont je vais parler, donc dans la deuxième partie du du séminaire, c'est le problème de concurrence et le problème de tolérance aux pannes. Donc comment faire pour que les données qui rentrent dans dans le SGBD soient stockées de manière sûre, de manière durable. Après, il y a des problèmes, donc de de confidentialité, autour de la sécurité des données, des données, de l'anonymisation, et cetera. Ça, c'est des des travaux de recherche que que je fais, que je fais moi.

Voilà. Donc bon, ça, c'est une manière, moi je l'ai fait de manière très rapide. Je pense que vous pouvez prendre un petit peu plus de temps vous en en cours pour un petit peu faire réfléchir les élèves sur comment est-ce qu'ils feraient pour gérer des données, donc quel genre de programme ils écriraient, éventuellement leur faire écrire des programmes, et puis après leur montrer, bon ben voilà, le même problème, on veut gérer des comptes en banque avec tel et tel type de contrainte. Voilà, comment ça se fait avec un SGBD, et puis vous, ben, regardez le nombre de lignes de code que vous avez écrit, faudra faire ça à chaque fois qu'on aurait une nouvelle application. Voilà. Donc en tout cas, là, le le programme officiel vous invite à à à présenter le problème de cette manière-là. Je pense que c'est c'est tout à fait tout à fait bien.

Alors sur les concepts, il y en a un certain nombre, ils ne sont pas forcément compliqués, mais comme il y en a pas mal, bon, ça ça demande un peu le temps de le temps de rentrer. Nous, on fait tout en une fois. Bon, je pense qu'il faut le faire aussi tout en une fois, parce que prendre juste un sous-ensemble, ça ça ça ne permet pas de faire grand-chose, hein. Mais éventuellement, faut revenir dessus, quoi, et puis et puis réinsister. Et il y a quelques éléments de vocabulaire qui sont nouveaux, hein, par rapport aux aux bases de données. Bon.

Alors première chose, c'est un ensemble de de domaines, de types. Donc on va avoir des entiers, des chaînes de caractères, et cetera. Des pays. Donc ça, ça peut être n'importe quoi. Dans les SGBD, ben souvent, on stocke des chaînes de caractères et puis et puis des valeurs numériques, hein. Donc ça, ça va pas trop, ça va pas chercher trop loin pour ce qui concerne les les les domaines. Et puis on a un nom, peut-être un petit peu nouveau, qui est un attribut. Alors un attribut, c'est un domaine, mais auquel on a associé un nom. Et derrière, bah, il va y avoir un sens à ce nom, hein. Donc euh, ça, ça se traduit par des colonnes. Mais par exemple, on dira, euh, on a un nom euh qui correspond à une chaîne de caractère, on a un âge qui correspond à un entier, on a une adresse qui correspond à une chaîne de caractère, et cetera. Donc vous voyez, on rajoute un petit peu de sémantique sur simplement un un domaine. Et on peut bien sûr avoir plusieurs attributs qui sont sur le même domaine, d'accord ? Vous allez avoir plein d'attributs qui sont sur les entiers, plein d'attributs qui sont sur les chaînes de caractères, ça, c'est pas c'est pas du tout un problème. Par contre, vous allez avoir un seul attribut, enfin disons euh vraisemblablement, vous aurez qu'un seul attribut qui a un nom donné.

Ensuite, donc on parle de variable de relation quand on regroupe ensemble des attributs. Donc là, par exemple, j'ai regroupé nom et âge. Ça, ça représentera éventuellement des informations qui sont reliées ensemble. Par exemple, ça peut être une personne qui possédera un nom et et un âge. Mais pour l'instant, on n'a pas mis de valeur sur sur ces attributs. Les valeurs, elles apparaissent avec un concept qu'on appelle, bah, le nupl, ou le en anglais, le le tuple, qui est un ensemble ordonné de couples attribut-valeur. C'est l'équivalent aussi des des rangées dans les tables qu'on va voir qu'on va voir ensuite. Donc là, vous avez par exemple le tuple euh avec un nom qui est Toto et un âge qui est qui est 18. Et finalement, vous avez une relation. Donc là, c'est aussi un concept qui est qui est nouveau, qui est un ensemble de tuples auxquels on va adjoindre un nom. Donc là, par exemple, on va définir les étudiants comme étant un ensemble de tuples. Donc là, voyez, trois tuples différents qui a 18 ans, Titi qui a 22 ans, et Tata qui a 20 ans.

I pendant que j'y pense, parce qu'on me l'a dit au début de la séance, Francis a dû vous dire qu'il fallait installer quelques logiciels ou que vous pouviez installer quelques logiciels. Donc ça, c'était utile si jamais j'arrive jusqu'à la partie exercice. Donc c'est installer un serveur WAMP ou LAMP, selon que vous êtes sur Windows ou ou Linux. Bon, on verra si on y arrive le cas échéant. Moi, de toute manière, je ferai une démonstration sur l'ordinateur. Donc c'est plutôt si vous vous voulez vous vous en servir et que qu'il faut les installer. Bon, je vous invite à le faire. Soit vous l'avez déjà fait, soit soit vous faites plus tard, c'est pas c'est pas un souci. Voilà.

Donc ça, c'était c'était les concepts. Et puis une base de données, bah, ça va simplement être un ensemble de relations. Alors donc la question, c'est ici, on parle d'ensemble, et puis dans les bases de données, on peut mettre plusieurs fois la même ligne, ce qui veut dire que ce n'est pas des ensembles. Alors effectivement, la théorie des bases de données, en tout cas la théorie des bases de données sans les agrégats, elle elle est basée sur la théorie des ensembles. Donc ce que moi je raconte après, et tous les liens que je fais avec la logique du premier ordre, c'est une théorie qui est basée sur les ensembles. Les SGBD, ils sont implémentés sur ce qu'on appelle des multi-ensembles, c'est-à-dire que vous pouvez avoir plusieurs lignes qui ont la même valeur. Ça s'appelle aussi un un bag en anglais, ou des choses comme ça. Donc effectivement, pourquoi est-ce que les multi-ensembles sont utiles ? Mais alors après, la théorie est beaucoup plus compliquée, c'est pour pouvoir faire des agrégats, pour pouvoir faire des des choses comme ça, d'accord ? Pour pouvoir compter les occurrences d'un certain nombre de choses. Donc effectivement, le SGBD, lui, il fonctionne par défaut en multi-ensemble, mais en utilisant le mot-clé qui s'appelle DISTINCT, vous pouvez toujours vous ramener à une à une logique ensembliste. Donc si vous voulez faire des choses avec que des ensembles, vous rajoutez DISTINCT partout, et ça va toujours vous virer les les doublons. Donc vous pouvez voilà, vous pouvez travailler sur juste des ensembles si vous voulez faire ça avec les avec les élèves, c'est c'est tout à fait possible. Donc ça, c'est c'est effectivement une remarque qui est qui est intéressante. Donc là, les concepts sont effectivement pour disons la partie zéro des des bases de données, c'est vraiment le le début, hein, c'est c'est là-dessus que qui sont que sont construits les fondements les fondements logiques.

Donc là, c'est une autre, enfin, je reviens un petit peu sur sur ces définitions, hein. Donc je note D l'ensemble des domaines, c'est l'ensemble des attributs, donc les noms plus plus une valeur de de domaine. C'est c'est l'ensemble de tous les attributs qui vont apparaître dans la base de données. Bon, ça, c'est une définition un petit peu formelle, hein, du coup, c'est pas forcément comme ça qu'on va raisonner, hein, mais mais là, ça permet d'avoir des notations plus simples. Donc l'ensemble de tous les attributs, l'ensemble de toutes les relations, ou plutôt de tous les noms de relations, et puis une fonction qui associe à un nom de relation, ben un sous-ensemble des attributs qui va correspondre au au schéma de la relation. Donc là, par exemple, cette fonction H, donc qui est à valeur dans 2 à la puissance le nombre des attributs, et ben H de responsable va avoir comme valeur le sous-ensemble NR entier, donc numéro de responsable, le nom chaîne de caractère, et le prénom chaîne de caractère. D'accord ? NR, nom et prénom sont tous des éléments de l'ensemble C. Et puis donc la base de données, bah, c'est un ensemble de de relations. Donc ça va être un triplet, ensemble de domaines, ensemble de noms de relations, et puis la fonction qui donc fait map l'ensemble des relations vers donc à chaque fois un sous-ensemble des des domaines. Voilà.

Donc là, vous avez un exemple de base de données avec des responsables de cours, des étudiants, et des étudiants qui sont inscrits là-dedans. Alors voyez, cette première définition, c'est uniquement sur la structure de la base de données. Là, j'ai pas parlé de ce qu'il y avait dedans. Donc ce qu'il y avait dedans, donc ce qu'à chaque fois dans une relation, ça va être un tuple, qui est défini comme une fonction, pardon, partielle de C dans le produit cartésien de de tous les de tous les attributs. Donc là, par exemple, vous avez un tuple qui sera à valeur sur un sous-ensemble de ces attributs : numéro d'étudiant, nom et prénom. Donc ça, ce sera un tuple qui a un certain un certain domaine qui qui est défini par l'ensemble de ces attributs, donc numéro d'étudiant, nom et prénom. L'ensemble de tous les tuples possibles, bon, on le note TD. Donc là, évidemment, cet ensemble-là, il est très grand. Et la base de données, elle est définie comme une fonction de R dans l'ensemble des parties de des tuples possibles, qui donc grosso modo, à chaque relation associe un sous-ensemble de de tuples, de telle sorte que, mais ça, c'est disons évident, le schéma de la relation correspond au domaine du tuple, c'est-à-dire que bah, les attributs qui sont dans la structure correspondent aux attributs qui sont dans les données. Donc là, c'est une manière formelle, peut-être un petit peu compliquée, hein, de de dire ce que je viens de de dire là à l'oral, hein. Vous avez la structure qui correspond à des noms de colonnes avec des des types, et puis derrière, vous avez des données, des données à l'intérieur, bah qui évidemment doivent avoir une valeur pour chacune des colonnes. Alors ça peut paraître naturel, mais du coup, vous voyez que là, on ne prend pas en compte par exemple des valeurs nulles, d'accord ? Donc là, si j'ai une table qui possède trois colonnes, donc une relation qui possède trois attributs, bah il faut qu'à chaque fois un tuple pour avoir le droit d'appartenir à cette relation, il faut qu'il ait une valeur correcte pour chaque attribut, donc une valeur de de domaine correcte.

Alors dans le programme, il parle de la clé. Donc il faut parler du principe de la de la clé. C'est effectivement un concept fondamental en base de données, mais dont on ne fera rien. Donc bon, bon, moi, je suis un petit peu déçu, c'est-à-dire que on vous explique, il faut parler d'une clé. Donc qu'est-ce que c'est qu'une clé ? Bah, une clé, c'est un attribut ou un ensemble d'attributs qui permet d'identifier de manière unique un tuple dans une relation. Donc par exemple, le numéro d'étudiant va permettre d'identifier de manière unique, enfin, on imagine qu'il permettra d'identifier de manière unique un tuple étudiant. Donc numéro d'étudiant, nom, prénom, puis peut-être d'autres données derrière. Ce n'est pas forcément juste un attribut, hein, qui permet de définir une clé, ça peut être deux ou plusieurs attributs qui permettent de définir une clé. Par exemple, le triplet nom, prénom, adresse, ou nom, prénom, date de naissance, pourrait définir une clé, c'est-à-dire que deux individus pour être différents au sens, donc des des ensembles qui sont derrière, devront avoir une valeur différente sur ce sur ce triplet-là. Donc on peut avoir le même nom, le même prénom, mais pas la même date de naissance. Donc ça, c'est la seule chose un petit peu compliquée par rapport à à la définition d'une clé, c'est que souvent une clé, on la voit comme quelque chose de de monovalué, elle peut être multivaluée. Alors dans les faits, et pour des raisons d'optimisation, dans une base de données, on utilise toujours des clés qui sont monovaluées. Donc bon, le fait qu'elles soient multivaluées, c'est c'est intéressant du point de vue des contraintes qui s'appliquent à la base de données pour éviter qu'on va de pour éviter d'introduire des erreurs dans la base de données, hein, voilà, pour éviter d'introduire des doublons. Mais mais ça s'arrête là. Donc effectivement, le fait de savoir qu'il y a une clé unique, c'est c'est intéressant.

Alors en fait, à quoi sert cette clé ? Elle sert, comme je visais, pour des raisons de de contrainte d'intégrité, c'est pour éviter de mettre n'importe quoi dans une table, pour éviter de mettre des doublons. Mais elle sert aussi pour l'optimisation et l'exécution des requêtes derrière, en particulier pour pour les jointures. Donc quand on se pose la question de savoir comment est-ce qu'on va faire pour calculer le résultat d'une requête, pour vraiment le programme qui tourne derrière, donc ça, c'est c'est totalement hors programme, et ben on va s'intéresser au fait qu'on a des clés, qu'on a des clés primaires. Quand on aura des clés primaires, on pourra lancer un certain type d'algorithme. Quand on on n'aura pas, faudra lancer d'autres types d'algorithmes, et il va y avoir des différences en termes de coût d'exécution qui seront extrêmement importants. On va passer de quelque chose qui sera en temps constant à quelque chose qui sera en temps linéaire par rapport au nombre de tuples dans la table. Donc bon, les clés, c'est fondamental pour tout ce qui est exécution des bases de données, c'est important pour ce qui est de la conception de la base de données. Voilà. Donc on vous demande un petit peu d'en parler, mais comme je le dis, malheureusement, les élèves ne pourront pas voir jusqu'où ça sert vraiment, puisque on fait ni conception ni exécution.

Bon, alors voilà. Bon, ça, c'était une petite parenthèse à laquelle j'ai j'ai un peu répondu tout à l'heure. Donc comment est-ce qu'on fait pour noter les une base de données ? Bon, là, je revenais un petit peu dessus. Bon, la définition des tables en donnant le nom de la table, puis l'ensemble des attributs, en soulignant la clé, donc l'attribut ou l'ensemble d'attributs qui correspond à la clé primaire. Euh voilà, donc ça, c'est à peu près une convention classique pour définir des tables dans le modèle relationnel. Donc je pense que quand on donnera des schémas, ils seront exprimés comme ça. Donc vous aurez un ensemble de tables de cette manière-là : le nom de la table, le nom de l'attribut, et puis le domaine de l'attribut ou le type de l'attribut. Alors ils sont exprimés de cette manière-là parce qu'on n'a pas justement le le modèle entité-association qui qui est qui est derrière.

Deux autres termes de vocabulaire, donc intention et extension. Bon ben, l'intention, ça correspond au schéma, et l'extension, ça correspond aux valeurs. Et puis donc le schéma de la BD, mais ça, je l'ai déjà dit, c'est l'ensemble des schémas des des relations. Bon, les contraintes, tout ça, j'en j'en parle pas, mais donc normalement, une base de données, c'est un ensemble de tables plus un ensemble de contraintes plus des informations ici. Donc là, c'est sur les clés candidates, c'est-à-dire que ce n'est pas que des clés primaires, c'est pour indiquer des contraintes d'unicité sur sur les tuples. Mais je pense que dans le programme, vous ne regarderez que cette partie-là, hein, puisque les les clés étrangères, il me semble, ne sont pas dans le ne sont pas dans le programme.

Alors ça, c'était juste pour donner un petit exemple de diagramme entité-association qui euh donc n'est pas n'est pas au programme, mais éventuellement, vous en verrez passer, parce que quand on fait des bases de données, on on voit souvent ce genre de choses. Donc ça, c'est un un autre langage, en quelque sorte, qui permet de faire de la modélisation, qui peut être appliqué aux bases de données, mais qui peut être aussi appliqué à d'autres types de de de programmation, comme la programmation objet, pour gérer les informations que vous avez dedans, avec deux types de choses qui sont des entités et puis des associations qui lient les deux. Et l'intérêt de cette modélisation, c'est qu'elle est assez facile à à mettre en place. Donc normalement, ça permet assez facilement de passer de la réalité vers un premier diagramme papier, et après, il existe des méthodologies dont je crois que j'ai parlé l'année dernière, qui permettent de transcrire ce schéma vers un schéma de base de données.

Alors en fait, grosso modo, on on a une méthode pour transformer les entités en tables, c'est direct. Et puis une méthode pour transformer les associations en tables. Là, c'est un tout petit peu plus compliqué, mais mais pas beaucoup. Donc ça, c'est quelque chose qui est programme, mais que vous verrez certainement si vous prenez des exercices sur le web, qui sont faits dans dans les facs ou ou ou simplement sur les sites pour un petit peu modéliser la structure de la base de données. Vous voyez que c'est plus facile, enfin, on comprend mieux les liens qui existent entre les entités en regardant un diagramme comme ça, plutôt qu'en regardant une liste de de tables. Alors certes, tu peux les déduire en regardant les clés étrangères, mais ici, c'est vraiment direct.

Alors simplement, donc les carrés, c'est ce qu'on appelle des entités. Donc ça, c'est des choses qui disons existent de manière indépendante dans le monde réel. J'explique pas le diagramme entité-association, hein, mais voilà. Et et les et les associations, pardon, qui sont les losanges, qui en fait sont existent uniquement si deux entités, enfin, elles sont le lien entre deux entités. Alors disons qu'une clé étrangère, enfin, quand vous avez une association, vous allez avoir au moins une clé étrangère qui va arriver. Alors peut-être, bon, je une petite parenthèse, puisque j'en ai parlé, les entités, donc deviennent des tables, et on peut toujours transformer une association en table, qui aura en fait deux clés étrangères, une clé primaire qui correspond à l'entité de gauche, et une clé primaire qui correspond à l'entité de droite, pour indiquer que ces deux entités sont en sont en relation, tout simplement. Donc là, pour indiquer qu'un client possède un compte, le client, il a un ID client, et le compte, il a un ID compte. Donc ça, ça fait deux tables. Je une troisième table où chaque ligne sera ID compte d'un côté, et ID client de l'autre, pour indiquer que le compte 1 est possédé par le client 36. Voilà. Et potentiellement, il y a d'autres informations, c'est-à-dire que même le losange peut avoir des informations supplémentaires, du style, a été ouvert à telle date, je ne sais trop quoi. Mais globalement, voilà.

Mais en fait, le problème, c'est que le modèle relationnel, lui, fait pas de distinction entre entité et association. Vous avez que des tables. Et vous avez d'ailleurs certains modèles relationnels qui se traduisent assez difficilement dans des modèles entité-association, parce que vous avez fait des clés étrangères un petit peu bizarres. C'est des problèmes de normalisation. Là, c'est pareil, c'est c'est programme. Tandis que si vous passez par un modèle comme ça, et qu'après vous déduisez des tables, vous allez toujours avoir quelque chose qui a à peu près la même tête, et vous saurez, parce qu'il y a quand même une différence conceptuelle, la différence entre une ce qui est une entité et ce qu'il a une association, c'est quelque chose qui peut exister tout seul dans la base, et quelque chose qui qui existe uniquement pour faire le lien entre deux choses dans la base. C'est pour ça que je pense que c'est quand même intéressant d'avoir cette vision euh entité-association pour plus facilement faire la transcription du monde réel vers le la base de données que vous créez. Encore une fois, ce passage-là, il est il est pas au programme. Ce qui est demandé aux élèves, c'est soit de réussir à créer une base de données avec un maximum de trois tables. Alors je suggère de faire trois tables, parce que c'est.

C'est ça qui est intéressant. Si vous en faites que deux, vous loupez un petit peu quelque chose. Je suis d'accord avec le fait que tu vas avoir plus de trois tables, ça n'apporte absolument rien à part de la complexité. Donc bon, ce qu'on sait faire sur trois tables, on sait le faire sur 50 000 tables, c'est juste, c'est un petit peu plus fastidieux quoi. Et après, il faut que les élèves sachent interroger une base de données de de très grande taille si les informations sont déjà dedans. Voilà. Donc ça, il faut que vous vous créez une base de données ou bien vous en récupérez une quelque part sur internet avec plein de tables. Bon, c'est moi, personnellement, je fais travailler les les les les étudiants essentiellement sur des petites bases de données pour pas parce que en fait, le problème d'écrire des requêtes, il est indépendant du fait d'avoir 50 000 tables. Avoir 50 000 tables, vous a un problème de vous dire où est-ce que je dois trouver la donnée et puis là, hop, à chaque fois vous tapez les 50 000 tables à lire. Donc c'est c'est pas très très intéressant. Enfin, la difficulté, elle est elle est elle est autre de mon point de vue.

Alors pour créer les tables, puisque puisqu'on parlait de de ça, bah vous avez une syntaxe dans SQL, hein, donc le le langage qui est implémenté dans les bases de données qui permet de créer une table. Bon, je la donne ici, vous la trouvez dans tous les manuels qui racontent en long, en large et en travers SQL. Alors ça, c'est la syntaxe que j'ai mise pour en fait, qui a été générée automatiquement par MySQL. Il se trouve que c'est pas une syntaxe qui est forcément standard ou en tout cas qui passe sur les sur les autres SGBD. Par exemple, Oracle, lui, il connaît pas INT, il connaît que NUMBER. Donc bon, disons, faut un petit peu que vous regardiez pour quel SGBD a été fait le le code, hein, si jamais vous vous le prenez sur Internet et puis faire quelques petits ajustements. Malheureusement, il y a un standard qui existe, mais il n'est pas toujours suivi. Bon, euh, voilà.

Alors ceci étant dit, les tables en général, en tout cas au moment de la conception, elles sont créées une seule fois. Alors elles peuvent l'être avec du code comme ça, ou bien elles peuvent être créées par une interface graphique. C'est en général plus simple de la créer via l'interface graphique. Je montrerai si j'ai le temps comment ça peut-être fait derrière. Donc on clique, on définit les choses. Mais à chaque fois, dans tous les SGBD, c'est pas parce que vous l'avez créé avec l'interface graphique que vous allez pas vouloir dupliquer votre base de données ailleurs.

Pour vos élèves, en l'occurrence, bah vous, ils peuvent peut-être créer trois tables comme ça à la main. Si vous faites une grosse base de données, bah il va falloir que vous donniez le code pour générer toutes ces tables. Donc il y a quelqu'un qui crée une fois pour toutes le schéma de la base de données et puis après, ce langage-là, il permet de recréer les tables ailleurs ou même au même endroit si jamais on efface la la base de données. Donc euh, donc voilà. Là, je je rentre pas dans les détails, c'est quelque chose qui est assez simple, hein. Vous vous pourrez retrouver cette cette création le cas échéant, n'importe où sur sur Internet.

Donc ce sur quoi je voulais insister, c'est la partie interrogation, c'est-à-dire que on a déjà un schéma de base de données qui a été créé, on a déjà des données qui sont à l'intérieur et puis et ben on cherche à poser des questions à cette base de données. C'est-à-dire que on a une phrase en langage naturel, si je peux dire, euh, et on va chercher à la transcrire en ce qu'on appelle une requête écrite dans le langage SQL. C'est ça qui est au programme. SQL, c'est, faut bien comprendre ça, n'a pas forcément l'air pour un certain nombre de raisons, mais c'est un langage qui est déclaratif. C'est-à-dire que SQL dit ce que vous voulez obtenir, il ne dit pas comment faire le calcul. Un langage comme Python, comme C, c'est un langage qui est impératif. C'est vous dites à l'ordinateur, fais ça, fais une boucle, stock telle valeur dans la variable i, et ainsi de suite, appelle telle procédure, et cetera, et cetera. En SQL, ce n'est pas ça que vous demandez. Vous dites, je veux calculer telle chose, vous exprimez une phrase. Et ce qui se passe, c'est que derrière, votre requête va va pour être exécutée, devoir être transformée en quelque chose d'impératif et quelque chose de procédural. Et ce langage impératif qui existe, c'est la l' algèbre relationnelle. C'est-à-dire un ensemble d'opérateurs qui prennent en entrée des choses, alors qui prennent en entrée des relations et des données, et puis qui retournent en sortie, bah, c'est même genre de de structure, c'est-à-dire des relations avec donc des attributs et et et des valeurs.

Donc ce qui est demandé dans le programme, c'est que les élèves sachent écrire des requêtes SQL. Et moi, j'insiste sur le fait qu'il faut qu'ils comprennent que c'est quelque chose qui est déclaratif. Et puis qu'il comprenne un petit peu comment est-ce qu'elles sont exécutées derrière. Que il connaissent les opérateurs de l' algèbre relationnelle. Et c'est tout. En fait, derrière ce qui se passe, c'est que les opérateurs de l' algèbre relationnelle, et c'est ça qui est intéressant pour une base de données, peuvent être mis dans un certain nombre d'ordres différents. Et que une question qui est posée, vous avez évidemment plein de manières de calculer la réponse. Et l'objectif du SGBD, c'est réussir à trouver la manière de calculer la réponse la plus rapide. Donc ça, c'est tout le problème de l'exécution et de l'optimisation de requête. Sachant que calculer la requête, enfin la meilleure la meilleure manière d'exécuter votre votre question, c'est un problème qui est justement NP-difficile. Donc ça peut vous coûter extrêmement longtemps, ça peut vous coûter beaucoup de temps pour calculer la meilleure manière. Donc la manière la plus rapide d'exécuter la réponse, c'est que peut-être que si vous aviez passé pas du tout de temps à réfléchir sur comment le faire et que vous l'aviez fait de manière très bête, vous auriez eu la réponse plus rapidement. Donc c'est un petit peu ça le problème auquel doit faire face les bases de données, c'est que calculer la manière la plus rapide de donner le résultat, bah en soi, ça coûte du temps au calcul. Donc ce problème d'optimisation, il est très intéressant. Encore une fois, lui, il est il est hors programme, mais c'est un problème qui est hautement difficile. Et ce qui fait la qualité des SGBD, donc des logiciels de base de données, souvent, c'est la qualité de leur optimisation. C'est-à-dire que est-ce qu'il vont pouvoir calculer plus ou moins vite une requête donnée. Donc vous passez une requête comme ça à MySQL sur une base de données qui a un très gros volume, vous passez la même requête sur un SGBD commercial, par exemple Oracle, DB2, et cetera. Il y a des chances pour que sur le SGBD commercial, votre requête, elle se calcule beaucoup plus vite, euh, tout simplement parce que il dispose d'un meilleur optimiseur. Donc il a choisi une meilleure manière de calculer la requête.

Enfin, il y a une troisième approche. Alors en réalité, c'est plutôt SQL qui est la troisième approche, he, de de mon point de vue, mais qui est le calcul relationnel. Euh, c'est en quelque sorte la logique du premier ordre qui est également un langage déclaratif qui permet d'exprimer de de de poser des questions. Donc le modèle, disons, théorique qui est en dessous de de SQL, c'est le calcul relationnel. Et c'est lui qui donne un sens normalement à votre requête. Donc toute la théorie des bases de données, elle s'appuie sur la logique du premier ordre. Et ce que l'on fait en base de données, enfin quand on écrit des requêtes, c'est qu'on écrit des formules de logique du premier ordre et on cherche à les traduire dans une algèbre relationnelle qui va permettre de les calculer. D'accord, vos formules de logique, ok, vous dites, j'ai telle formule que je cherche à calculer. Et ben, c'est déclaratif, vous n'expliquez pas comment est-ce qu'il faut faire pour calculer le disons les variables qui répondent à cette formule logique. Et c'est c'est à ça que sert le l' algèbre relationnelle.

Le gros résultat, enfin le résultat fondateur des des bases de données, donc qui date de de 1970, s'appelle le théorème de Codd. Et il dit qu'il y a une équivalence au sens du pouvoir expressif entre ce que vous pouvez déclarer avec la logique du premier ordre et ce que vous pouvez calculer avec le calcul relationnel. Donc en gros, si vous êtes capable de poser une question, alors vous allez être capable de la calculer. Le calcul prendra peut-être beaucoup de temps, mais vous aurez une expression qui sera calculable. Et donc donc ça, c'est un résultat qui est fondamental, puisque il vous permet d'écrire des questions de manière déclarative. Ok, c'est-à-dire que c'est comme si je vous disais, ben, le langage C, Python, tout ça, vous oubliez, vous déclarez, je veux calculer la moyenne. Et puis derrière, bah, on va vous calculer la moyenne. Bon, c'est quand même très impressionnant quoi, quand on voit qu'il faut faire des efforts et tout ça quand vous voulez calculer la moyenne en en avec un programme impératif. Alors évidemment, là, vous n'avez pas le même pouvoir d'expression que ce que vous avez avec le langage Python ou avec le langage C, hein. Vous n'allez pas être Turing-complet ou des choses comme ça, évidemment.

Donc l'idée, c'est que voilà. Donc vous avez d'une part des choses déclaratives qui sont faciles à énoncer. Enfin, normalement, quelque chose de déclaratif est plus facile à énoncer qu'un programme. En tout cas, c'est plus simple, disons. Et puis quelque chose de procédural qui est plus compliqué à écrire, mais qui qu'il est possible d'implémenter. Tandis que le calcul relationnel, vous ne pouvez pas l'implémenter. D'accord, vous n'avez pas une méthode qui, enfin, dis, c'est le théorème de Codd qui vous dit que la méthode pour l'implémenter, c'est de passer par par l' algèbre relationnelle. Et donc voilà. Donc je pense que c'est ça qu'il faut comprendre. Et c'est ce message-là qu'il faut transmettre aux élèves. SQL, c'est pour représenter la question que vous avez, ce que vous voulez calculer. Et l' algèbre relationnelle, donc tous les opérateurs, c'est comment ce sera calculé par le logiciel qui est derrière. Faut bien voir que ce n'est pas SQL qui calcule. SQL, vous posez votre requête. Et après, ce n'est pas parce que vous avez mis un JOIN et des choses comme ça que ce sera fait de cette manière. En fait, dans le calcul, en dans le même ordre.

Alors je fais quand même un développement, un tout petit développement hors programme sur le calcul relationnel. Donc j'en avais parlé un petit peu plus, je pense, l'année dernière, parce que ça me paraît quand même important de poser les fondements logiques et puis je pense que ça ça parle euh au bon au public de la salle, donc aux matheux. Donc vous avez deux manières de faire du calcul relationnel. Donc calcul relationnel de tuple, calcul relationnel de domaine. Bon, c'est grosso modo la même chose. Ce que vous avez ici, c'est un calcul relationnel de domaine, c'est-à-dire que je vais quantifier des attributs en quelque sorte. Je dis, il existe ne, non, et tu, ville, et cetera, tel que une certaine formule logique. Donc j'ai des prédicats. Donc par exemple, étudiant, c'est un prédicat qui sera vrai s'il existe un étudiant avec cette valeur ne, non, et tu, date, et ville. D'accord. Le calcul rationnel de tuple est parfois plus simple parce que du coup, je quantifie un tuple. Et derrière, je dis, étudiant de T, c'est un petit peu plus facile à comprendre que bah, il faut que la ligne qui correspond à ce tuple-là se trouve dans la table étudiant.

Je donne des exemples de calcul rationnel de tuple après. Donc vous avez ces prédicats-là qui donnent l'appartenance, voilà, d'un d'un tuple à une relation. Et puis après, vous pouvez écrire toutes sortes de formules logiques, donc avec des ET, des OU, et donc la négation, le quantificateur universel et quantificateur existentiel. Donc là, par exemple, il existe non section tel que section de NS, non section, et il existe année tel que inscrit de ne, ns, année. Donc en fait, qu'est-ce que je cherche à calculer avec cette formule logique ? Donc c'est quelque chose normalement qui est déclaratif et qui doit être facile à lire. Bon, ce n'est pas tout à fait pas forcément vrai, hein, mais mais disons, voilà. Ben, je cherche ici, voyez, les étudiants ici qui sont inscrits dans une section. En fait, voyez, ce NS et ce ce NS là, ce NS là, il est quantifié. Je retrouve le même ici qui fait le lien. Donc inscrit, c'est une association au sens du modèle entité-association. Donc il faut que le numéro d'étudiant que je trouve dans la table étudiant se trouve dans la table inscrit sur la même ligne que le numéro de section que je retrouve dans la table section. D'accord. Donc normalement, si je voulais écrire des requêtes avec le calcul rationnel, j'écrirais des choses comme ça. Et il faudrait que l'interprétation, en tout cas la lisibilité, soit soit assez claire pour moi. Bon, avec un petit peu d'entraînement, ça va, mais ce n'est pas forcément le truc le plus naturel du monde.

Donc en fait, j'ai sauté quelques transparents, c'est pour ça que SQL a été introduit parce que les personnes qui manipulaient le le calcul relationnel se sont dit, bon, écrire des formules logiques, c'est peut-être un petit peu compliqué pour les programmeurs. Donc on va leur donner une surcouche avec des termes un petit peu différents, mais qui représentent globalement la même chose pour pouvoir pour que ce soit plus simple d'écrire des requêtes. Mais globalement, quand vous écrivez une requête SQL, vous êtes en train d'écrire une une formule logique. Bon. Donc c'était ça l'objectif du calcul rationnel, exprimer facilement des requêtes.

Plus précisément, qu'est-ce qu'on peut mettre dedans ? Là, je passe un petit peu vite pour des raisons de de temps, euh, mais euh, vous avez donc des formules avec des formules terminales, donc des atomes qui peuvent être de trois types : soit une égalité entre des valeurs de de colonne, donc c'est-à-dire que je veux, enfin, peut-être le plus simple, c'est euh, une valeur de colonne égale une constante. Bon, soit euh, un prédicat, c'est-à-dire que le tuple appartient à euh, une relation. Soit une égalité de deux attributs pour deux tuples différents. Et une fois que vous avez ça, donc là, ça ça correspond à quoi ? Ça correspond à la logique du premier ordre avec des prédicats qui sont diadiques au maximum, hein, puisque là, vous avez une égalité, c'est un prédicat qui est qui est d'arité 2. Vous avez après l'appartenance, qui est un prédicat d'arité 1. Donc une fois que vous avez ça, bah, vous avez votre votre calcul relationnel, hein, globalement, avec avec les quantificateurs qui sont ajoutés.

Ce qu'il faut savoir, c'est que vous avez droit à la négation. Donc vous avez droit au ET, au OU, au il existe et au quel que soit. Donc j'avais donné un premier exemple. Vous avez d'autres exemples de formules. Donc par exemple, il existe T tel que client de T et T point ville égal Versailles. Donc ça, ça se lit, il existe un client qui habite à Versailles. D'accord. Donc là, voyez, à chaque fois, deux atomes : le prédicat, donc T est un client, et puis le test, attribut égal constante, la valeur ville de ce client-là est égale à Versailles. Et une requête, donc là, voyez, une requête, je vais rajouter l'information que je cherche à extraire de cette formule logique, en quelque sorte, je vais projeter un sous-ensemble, puisque là, il s'agissait d'un d'un tuple. Donc normalement, le tuple, il a exactement la même structure que que ce que je trouve dans la table. Donc il a exactement le même schéma, le même pardon, domaine que le schéma de cette table client. Je suis peut-être pas intéressé partout. Donc là, je peux projeter des informations qui proviennent de ce tuple-là, ou bien je peux prendre des informations qui viendraient de plusieurs variables que j'aurais quantifié. Donc là, par exemple, je dis, je veux trouver le nom de tous les clients versaillais. Je vais réutiliser donc ma formule logique précédente qui me trouve un client versaillais. Et je vais dire, ben, je veux les E point nom tel que il existe un T qui est un client, que l'attribut ville de ce T est Versailles, et que T point nom est égal à E point N. Donc voyez, j'ai introduit une variable libre dans une formule, dans une formule logique, et c'est cette variable libre-là après qui va me donner le le résultat à la requête.

Donc comme on le disait au début, avec ça, on gère pas les agrégats. Il faut étendre le formalisme. Mais alors là, ça devient beaucoup plus compliqué. Alors donc, voyez, le calcul relationnel, je l'ai fait là en trois transparents. Alors je suis allé très rapidement. Donc ça mériterait qu'on s'attarde davantage et qu'on l'explique peut-être plus plus longuement, mais c'était juste pour vous donner un petit peu l'envie d'aller d'aller voir ça, d'aller le regarder. Je pense pour pouvoir voilà, expliquer que SQL, c'est la même chose que que la logique.

Maintenant, je vais parler de l' algèbre relationnelle, qui est là quelque chose d'assez nouveau par rapport aux aux élèves. Bon, la logique, il connaissent peut-être un tout petit peu, quoi. L' algèbre relationnelle, bon, là, c'est c'est quelque chose qui est 100 % nouveau. Donc là, il faut passer un petit peu plus de temps à à expliquer quels sont tous ces opérateurs-là et puis à donner des exemples. Alors naturellement, si je devais faire un cours pour des élèves sur le calcul rationnel, je donnerais plus qu'un exemple et demi comme j'ai fait pour vous.

Alors je vais travailler sur une base de données qui possède ce modèle entité-association, c'est-à-dire que vous avez des étudiants qui sont inscrits dans des sections et les étudiants qui vivent dans une certaine ville. J'ai créé une entité ville parce que j'ai voulu associer à une ville éventuellement un département dans lequel se trouve la ville. Bon, c'est purement artificiel ici, hein. On pourrait se dire, bah, on pourrait tout mettre dans la table étudiant, on aurait pu d'ailleurs, compte tenu des cardinalités du modèle. Mais en tout cas, ce modèle-là, moi, je l'ai traduit par quatre tables : une table étudiant, une table section, et une table inscrit. Donc là, en plus, une inscription possède une information sur l'année. Donc vous voyez, ça apparaît ici. Un numéro d'étudiant, enfin plutôt, un étudiant est inscrit dans une section donnée, une année donnée. Donc en 2013, il peut être inscrit quelque part, en 2014, peut-être dans une section différente. Et puis donc cette table ville, je j'ai en fait intégré cette association dans étudiant. Vous voyez que dans étudiant apparaît cette information ville qui correspondra à une clé étrangère pointant vers nom ville ici dans cette table ville. Allez, voyez, c'est c'est pour ça que le diagramme, il est un peu plus facile à comprendre que le schéma relationnel. C'est pour ça, je pense que c'est sur une question qu'on pose, hein, si on donne un schéma relationnel, quel est le diagramme qui auquel il correspond ? Voilà, ça demande une petite petite gymnastique. Donc je vais travailler sur ces quatre tables dans la suite des des exemples.

Quelles opérations est-ce qu'on a dans l' algèbre relationnelle ? Donc algèbre relationnelle ensembliste, travaille aussi sur des ensembles. Donc vous avez les opérations ensemblistes de base classiques : l'union, l'intersection, la différence. Vous avez le produit cartésien, enfin, définir après, et un certain nombre d'autres choses. Donc le produit cartésien, vous avez deux ensembles, donc deux relations étudiant et ville. Et si je calcule donc la relation qui est le produit cartésien de étudiant croix ville, je vais prendre simplement tous les tuples, donc tous les éléments de ce premier ensemble, et à chaque fois, je vais combiner un élément avec l'ensemble des éléments du deuxième ensemble. Et le schéma de la relation résultante sera l'union des schémas de la relation étudiant et de la relation ville. Donc là, voyez, j'avais trois champs pour étudiant, deux champs pour ville, donc je vais avoir cinq champs dans la relation produit cartésien. J'avais quatre tuples dans étudiant, deux tuples dans ville, donc je vais avoir 4 x 2 = 8 tuples dans la relation euh produit cartésien. Et puis vous avez du coup, hein, l'équivalent avec la logique. Qu'est-ce que je quelle formule logique j'exprime quand je calcule le produit cartésien ? Ou plutôt, comment calculer ce que j'exprime avec cette formule-là ? Bon, B, c'est simplement, j'avais un R dans R et un S dans S tel que bah la première partie et puis donc un un Q qui prend qui concatène R et S. La première partie est dans Q, la deuxième partie est dans S. Donc ça, c'est le produit cartésien.

À quoi sert le produit cartésien ? Ou à quoi est-ce que ça correspond le produit cartésien ? Bah, à toutes les combinaisons possibles d'une ligne avec une autre. C'est-à-dire que bon, ce n'est pas vraiment une question qu'on pose souvent dans une base de données. Et c'est plutôt utilisé comme sous-opération pour comprendre la jointure qui va arriver après, qui est l'opération de base de la base de données. Mais je commence par le produit cartésien parce que c'est, je dirais, une opération qui apparaît dans la clause FROM de de SQL, à laquelle on touche tout de suite euh quand on est quand on est utilisateur. Et pour expliquer que le produit cartésien n'est pas la jointure, donc je commence en expliquant le produit cartésien parce que si vous commencez par la jointure, les les élèves pensent que le produit cartésien, c'est pareil. Donc je commence en montrant un truc qui se demande un peu à quoi ça sert, et après on raffine avec la jointure pour donner quelque chose de vraiment utile.

Alors quand même, avant de parler de la jointure, je vais parler de la projection et de la restriction, parce que j'en ai besoin aussi pour définir la la jointure. Donc la projection, bah, vous prenez une relation avec un certain nombre d'attributs et vous allez éliminer un certain nombre d'attributs. Donc j'ai projeté sur un sous-ensemble des attributs. Par exemple, je vais projeter les étudiants sur date de naissance et ville. La relation résultante possède deux attributs et forcément un nombre inférieur ou égal de lignes, puisqu'on a une sémantique ensembliste. Donc si j'ai deux lignes qui sont identiques, elles seront fusionnées. Ça, c'est c'est ce qui se passe normalement quand vous faites la projection et que vous travaillez en ensembliste, donc avec DISTINCT. Si vous ne le faites pas, vous aurez des doublons potentiellement. Donc pareil, vous avez une définition avec avec la logique qui qui permet de projeter, c'est que vous avez un R qui possède N dimensions, enfin N N attributs, vous avez un tuple Q qui n'en possède que P, avec P plus petit que N, et puis vous voulez qu'il y ait égalité sur ces P premières composantes entre Q et R.

La restriction, donc l'idée, c'est qu'on se donne une formule logique Q. Alors il peut y avoir des restrictions qu'on se, enfin, des limites sur ce qu'on s'autorise à exprimer dans Q, mais vous pouvez imaginer que ça peut être n'importe quoi. Donc c'est noté Sigma indice Q appliqué à une relation. En général, ce qu'on utilise pour Q, c'est euh, une relation attribut thêta valeur, où thêta est un comparateur d'égalité ou supérieur, inférieur, et cetera. Mais vous pouvez en fait, dans Q, mettre une requête, une formule logique. Voilà. Donc un un petit peu ce que vous voulez. La sémantique formelle, c'est pareil, c'est que vous avez ce Q-là, donc vous autorisez à aller chercher, donc vous cherchez un S, donc un tuple S, qui correspond à un tuple S qui appartient à cette relation, tel qu'égalité sur l'ensemble des attributs, et que ce prédicat Q soit vrai appliqué à R. Donc Q peut être n'importe quelle formule logique acceptable dans dans mon calcul.

Prenons un exemple assez simple avec donc cette restriction date de naissance supérieure à 1992. Donc voyez, on applique ça à la relation étudiant, on conserve le même schéma, les mêmes attributs, mais on va avoir filtré et retiré un certain nombre de lignes. Donc il reste plus que les lignes qui vérifient le prédicat date de naissance strictement supérieure à 1992. Donc là, c'est pareil, j'ai moins de lignes, au plus le même nombre de lignes qu'au départ.

Une fois que j'ai introduit ces trois opérations : produit cartésien, projection et restriction, je peux définir la jointure, qui est l'opération centrale, enfin la plus spécifique, disons, aux bases de données, et celle qui pose le plus de problèmes quand on cherche à l'optimiser, parce que en fait, on peut l'optimiser, contrairement au produit cartésien. Produit cartésien, faut simplement tout prendre, et ça vous donne une table qui est très grande. La jointure, de quoi est-ce qu'il s'agit ? Bah, c'est un produit cartésien avec une restriction qui porte sur un attribut de jointure. C'est-à-dire que je fais le produit cartésien entre deux tables, mais je vais vouloir qu'il y ait égalité entre les valeurs dans une colonne donnée de la table 1 et les valeurs dans une autre colonne qui correspond à la table 2. Donc ça, c'est quelque chose qui va être écrit à l'aide de ma restriction. Et puis après, je vais projeter en éliminant une colonne. En l'occurrence, comme je vais avoir égalisé souvent deux colonnes, bah, je vais supprimer une des colonnes.

Donc voyez, la jointure, c'est quelque chose qui en fait donne du sens au produit cartésien. C'est-à-dire que je vais combiner ensemble deux tables avec une restriction qui dit, bah, la pourquoi je combine une ligne avec une autre. Voyez, c'est un petit peu logique. Si on prend deux tables étudiant et ville, et qu'on fait la jointure, il s'agit d'obtenir une information supplémentaire cohérente, si on peut dire, avec les informations qui sont dans la base. C'est-à-dire, je vais vouloir pour là, un étudiant donné, connaître la ville où il habite et le département qui est associé à la ville. Donc je vais faire une jointure entre étudiant et ville sur la tribu, sur les deux attributs étudiant.ville = ville.nom_ville. C'est-à-dire que lorsque je prends une ligne de étudiant ici, je vais la combiner avec toutes les lignes ici qui vérifient le nom de la ville, la valeur de ville dans étudiant est égale à la valeur de nom_ville dans ville. Donc là, à chaque fois, j'ai une seule ligne avec laquelle je vais pouvoir combiner une ligne de la table étudiant. Mais si j'avais par exemple deux fois Versailles, et ben à chaque ligne ici qui aurait la valeur Versailles pour ville, je combinerai deux entrées.

Donc ce qu'on a là, c'est que comme à chaque fois, il y a une seule possibilité de combinaison, et ben j'ai euh le le nombre de lignes que j'avais au départ dans la table étudiant. Donc là, à chaque fois, j'ai Versailles 78, pareil, 75, et cetera, et cetera. Si on réfléchit à comment ça a été calculé à l'aide du produit cartésien, on peut le représenter de cette manière-là, c'est-à-dire que j'ai construit le produit cartésien de étudiant par ville. Donc j'ai une table qui possède cinq colonnes. J'avais quatre étudiants, deux villes, donc j'ai huit lignes dans cette table. Ça, c'est la cardinalité du produit cartésien. Et après, j'ai fait une restriction sur le fait que la valeur de ville devait être égale à la valeur de nom_ville. C'est-à-dire que j'ai éliminé toutes les lignes pour lesquelles ville était différent de nom_ville. Donc là, voyez, j'ai éliminé donc quatre lignes. Il me reste plus que les lignes où la valeur de ville dans étudiant est égale à la valeur de nom_ville dans ville. Donc voyez que en connaissant produit cartésien, restriction, et puis après, bon, on pourrait projeter, c'est que là, ça sert à rien de garder ville et nom_ville, puisque à chaque fois ils ont la même valeur. Donc il me suffit de garder une seule colonne ville ou ou nom_ville. Donc c'est pour ça que j'ai introduit dans cet ordre-là les choses.

Alors on pourrait commencer par la projection, la restriction, et puis le produit cartésien. Bon, on pourrait aussi commencer par la jointure, en montrant le résultat sans sans expliquer comment ça peut être calculé. Bon, je trouve ça un petit peu plus logique de partir dans ce dans ce sens-là, parce que quand vous écrivez en fait à la fois des formules logiques et des requêtes SQL, souvent dans le FROM, vous allez donner la liste des tables, comme dans votre formule logique, vous allez donner la liste des prédicats d'appartenance, allez dire étudiant de T et ville de V, donne comme ça ces ensembles de tables sous la forme d'un produit cartésien. Et la jointure, elle est faite par d'autres prédicats qu'on rajoute, qui sont les prédicats qui expliquent sur quel attribut on fait cette jointure. Voilà. Donc du point de vue, comment dire, déclaratif, la jointure, ça n'existe pas. Vous n'avez pas une opération de jointure. Vous avez un produit cartésien. Enfin, en tout cas, quand vous l'exprimez avec le le calcul relationnel, vous n'avez pas une opération qui dit, je fais une jointure. Vous allez exprimer à chaque fois l'appartenance dans ces tables, ça c'est produit cartésien, et un prédicat qui dit égalité entre un certain nombre d'attributs. Voilà. Donc je pense qu'il faut l'introduire dans ce sens-là.

Quand vous faites du SQL, vous vous pouvez éventuellement déclarer dans la clause FROM, on va le voir après, une jointure directement. C'est vous dites, je veux prendre mes valeurs dans la table T1 jointe avec T2 sur tels attributs. Euh, moi, je trouve que ça, ce n'est pas déclaratif. Pourquoi ? Parce que là, vous êtes en train de dire, je veux faire une jointure entre la table 1 et la table 2 sur ces attributs-là. En fait, rien ne vous dit d'ailleurs que l'optimiseur va choisir de faire la jointure dans l'ordre que vous vous le donnez. Vous pouvez dire, par exemple, je joint T1 avec T2, puis ça, je vais le joindre avec T3. Donc vous allez parenthéser. Il se trouve que c'est peut-être optimal de faire d'abord la jointure entre T3 et T1, puis ensuite de joindre avec T2. Je donnerai un exemple. Donc vous vous déclarez quelque chose qui ressemble à une manière de calculer le résultat, donc qui ressemble à quelque chose d'impératif, mais qui en fait, par l'optimiseur, pourrait être exécuté de manière complètement différente. C'est un peu comme si moi j'écrivais un FOR, et puis finalement, bah, je sais pas, soit transformé en autre chose, en un appel de de fonctions récursives ou des choses comme ça. Donc vous voyez, vous vous êtes un peu étonné quand vous avez ce fonctionnement-là. C'est pour ça que je pense que c'est mieux de tout simplement ne pas écrire de jointure et bien comprendre que ce qu'on fait, c'est déclarer des tables, puis déclarer des prédicats, et qu'ensuite, c'est le SGBD qui se débrouille pour faire le calcul de jointure le plus, enfin, le meilleur possible. Sinon, il y a toujours des gens qui bah, écrire une jointure dans un dans un certain sens, et puis se disent, mais pourquoi le SGBD l'exécute pas ? Bah, parce que SQL est déclaratif.

Dans le programme, vous avez donc programme officiel, vous avez aussi la division. On vous parle de produit cartésien, on vous parle de division. Alors la division, c'est quelque chose qui permet d'implémenter le quel que soit. Bon, c'est pratiquement jamais utilisé parce qu'en fait, c'est assez rare de poser quand même des des questions avec quel que soit. Ceci explique cela. Du coup, ce n'est pas une opération qui est implémentée directement dans aucun SGBD. Donc vous êtes obligé de de refaire le calcul. Typiquement, ça, c'est des choses qu'on fait en exercice, on explique ce que c'est que la division. Donc la division d'une relation par une autre relation, c'est un sous-ensemble tel que quand vous faites le produit cartésien de ces deux ensembles, vous les retrouvez dans l'ensemble de départ. Voyez, c'est un peu le même principe que quand vous divisez deux entiers. D'accord, quand j'ai le quotient d'entiers, si je le multiplie par, je sais pas, comment s'appelle le diviseur, je retrouve la valeur initiale. Là, comme on est sur des choses qui sont ensemblistes, on n'a pas l'égalité, mais on a l'inclusion. Voilà. Donc moi, je dirais, la division, honnêtement, ça sert jamais. Comment ? Oui, oui, maximal. Oui, oui, oui, oui, oui.

À quoi sert l' algèbre relationnelle ? Donc ça permet, et voyez là, à chaque fois, j'ai donné la manière de traduire une expression logique en algèbre relationnelle. Bah, ça vous donne une manière d'exécuter votre requête. Qu'est-ce que ça veut dire ? Ça veut dire que si j'écris un programme qui implémente les opérateurs de l' algèbre relationnelle, que j'autorise des utilisateurs à poser des questions dans le formalisme du calcul de prédicat, donc si je autorise à écrire des formules logiques, bah, je peux traduire directement ces formules logiques dans mes opérateurs. Puis comme j'ai une implémentation de mes opérateurs, je peux obtenir les résultats dans mon SGBD. Donc c'est ça qui explique que le SGBD fonctionne. Implémenter un SGBD, enfin, écrire un programme qui permet de faire un SGBD assez naïf, c'est relativement simple. Le langage d'interrogation, donc vous faites pas SQL, vous faites, j'écris des formules logiques. Ce que vous implémentez, c'est trois opérateurs : produit cartésien, projection, et puis restriction. Et vous implémentez la traduction, hein, donc depuis le calcul relationnel vers le, comment dire, vers les opérateurs de l' algèbre relationnel, qui là, c'est pareil, c'est direct. Donc c'est c'est quelque chose qui est automatique. Après, bah, faut que vous implémentiez comment stocker vos informations sur le disque et cetera. Donc ce qui est compliqué, c'est l'implémentation des opérateurs de l' algèbre relationnelle. Le reste, c'est assez simple. Et si vous faites ça, vous avez implémenté, disons, un SGBD qui vous garantit ni la durabilité, ni quoi que ce soit, mais qui vous permet en tout cas de poser des questions de manière déclarative et d'obtenir les résultats. Donc ça, c'est déjà euh quelque chose d'assez puissant.

Maintenant, ce qui est véritablement difficile à faire, c'est trouver une formule de l' algèbre relationnelle équivalente à celle que vous aurez écrite, qui traduit votre formule logique, et qui soit la plus rapide à calculer compte tenu de la manière dont vous vous avez implémenté votre SGBD. Donc toute la problématique des SGBD commerciaux, elle est, enfin, beaucoup de cette problématique est là-dedans. Alors elle est déjà largement résolue, hein. Donc il y a d'autres problèmes, mais mais disons, il y a eu au moins 20 ans.

d'effort pour travailler là-dessus, d'accord. Donc, sur des calculs de, à la fois d'optimisation et puis de manière de faire des jointures, puisque, en fait, c'est la jointure qui est la plus intéressante à optimiser. On ne peut pas vraiment optimiser une projection, enfin, voyez.

Donc, pourquoi est-ce que tout ça ça marche ? Pourquoi est-ce qu'on peut euh passer du calcul relationnel vers l'algèbre relationnelle ? Eh bien, c'est grâce au théorème de Codd, c'est-à-dire que vous avez un pouvoir d'expressivité équivalent en calcul relationnel et en algèbre relationnelle. Donc, ça, c'est quelque chose qui euh, bon, je ne sais pas, peut faire l'objet d'un, d'un TIPE, d'un document ou ou ce genre de chose. Voilà.

Donc, vous voyez, je donne un exemple d'algèbre relationnelle, de calcul relationnel correspondant, et cetera. SQL, ça, j'avais un, j'en ai un petit peu parlé au départ. Donc, qu'est-ce que c'est ? C'est une manière plus simple, plus lisible de traduire euh, disons, le calcul relationnel. Et puis, en fait, bah, comme il y a équivalence entre le calcul relationnel et l'algèbre relationnelle, on peut voir ça aussi comme une manière d'écrire une opération de l'algèbre relationnelle. Mais ce qu'il faut savoir, c'est que ce n'est pas forcément ça qui sera exécuté, et c'est même sûrement pas ce que vous écrivez qui sera exécuté. Ce sera quelque chose qui sera équivalent à une formule canonique qui permet de traduire euh, votre expression SQL vers une formule de l'algèbre relationnelle.

Donc, en l'occurrence, si je travaille juste sur le `SELECT FROM WHERE`, parce que je je fais que des choses qui sont ensemblistes, donc j'ai pas de `GROUP BY` et j'ai pas de, j'ai pas de `HAVING`, vous avez un `SELECT` qui correspond à la projection, vous avez un `FROM` qui correspond au produit cartésien, et vous avez un `WHERE` qui correspond à toutes les restrictions, y compris les restrictions qui permettent de calculer des jointures. Donc, vous avez une traduction canonique immédiate depuis une formule comme ça. Donc, `SELECT A1, A2, ..., AP FROM les relations R1, ..., RK` ou `RQ` avec une projection sur les attributs `A1` à `AP`, une restriction sur la formule logique `Q`, et tout ça appliqué au produit cartésien de toutes les relations `R1` jusqu'à `RK`. Donc, j'insiste, le produit cartésien, ce n'est pas une jointure. Donc, c'est très important de mettre dans la formule `Q` ce qui va vous permettre de calculer les jointures. Voilà.

Donc, on voit que c'est assez simple de passer de SQL vers l'algèbre relationnelle. Mais encore une fois, moi, je pense qu'il est mieux de voir SQL comme une manière de représenter une certaine formule logique. Formule logique que j'écris en dessous, c'est-à-dire, vous avez bah, un certain nombre de de variables qui prennent leur valeur dans des relations, auxquelles vous appliquez des prédicats, et auxquelles vous faites des liens, c'est-à-dire, vous allez faire des jointures entre certaines valeurs de ces attributs. Voilà.

Donc, vraiment, le principe des bases de données, c'est de dire, ça, c'est, c'est de dire bah, vous avez une équivalence totale entre quelque chose qui vous permet de déclarer ce que vous voulez obtenir et la manière de le calculer. Donc, le problème des SGBD, c'est comment calculer une requête. Donc, vous écrivez votre requête en SQL, elle a une certaine sémantique, votre requête, elle est traduite en algèbre relationnelle, puis elle est optimisée, puis vous obtenez le résultat. Donc, comment tout ça ça marche, c'est hors programme, mais je vous montre quand même un petit exemple juste pour.

Donc, c'est le même exemple, même exemple que l'année dernière, avec des tables différentes, mais c'était la même, la même structure. Donc, en général, on représente les formules de l'algèbre relationnelle quand on fait de l'optimisation à l'aide d'opérateurs graphiques comme ça. C'est un petit peu plus facile à lire que les formules parenthésées, mais c'est exactement la même chose, évidemment. Euh, donc, vous avez la sélection qui est un trapèze sur le côté, une projection qui est un trapèze vers le haut, une jointure qui est bah, le petit nœud papillon avec les deux relations qui entrent à droite et à gauche, et puis les informations sur la jointure, puis éventuellement d'autres opérateurs comme ça à l'intérieur de bulles.

On pose la requête : trouver tous les ID comptes et ID opérations clients qui se prénomment Sylvie, qui ont un PEA, et c'est des opérations qui ont lieu après le 1er janvier 2014. Je peux traduire ça avec plein d'expressions de l'algèbre relationnelle différentes. La plus simple, c'est peut-être de se dire, on va faire d'abord les jointures. Enfin, en tout cas, une manière de faire, c'est de faire d'abord les jointures. Donc, je fais une jointure entre `client` et `compte`, donc j'ai ces deux relations, je les joins `ID client = ID propriétaire`. Après ça, je le joins avec `opération`. Dans `opération`, bah, j'ai une information sur le compte et l'opération, he, donc `ID compte` de ce qui vient de ce côté-là égal `ID compte` de ce qui est à droite. Donc, ça, ça me fait un résultat où j'ai joint toutes les informations. Il me reste plus qu'à sélectionner ceux dont le prénom est Sylvie, qui ont un PEA, et toutes les opérations qui sont après le 1er janvier, et puis de projeter sur les attributs `ID compte` et `ID opération`.

Donc, vous voyez, là, on a une manière de calculer cette requête qui était exprimée en français. Maintenant, je pourrais faire différemment. Je pourrais faire des restrictions avant de faire les jointures. Donc, là, la restriction sur Sylvie, c'était une information qui pouvait s'appliquer sur le client, he, puisque le client, c'était un `ID client`, `nom`, et `prénom`. Euh, je me suis trompé entre date et type, autant pour moi. Donc, ce qui s'appliquait sur `compte`, c'était le type, le type de compte devait être égal à PEA, et les opérations devaient avoir une date qui était euh, postérieure au 1er janvier 2014. Donc, excusez-moi, là, c'est faut inverser les deux. Donc, là, je filtre avant de faire les jointures, et ensuite, je projette comme avant.

Mais ici, voyez, j'ai d'abord fait une jointure entre `client` et `compte`, puis entre ça et `opération`. J'aurais pu faire dans un autre ordre : d'abord joindre `compte` avec `opération`, puis joindre avec `client`. Ce qui est sûr, c'est que par rapport à ce que je fais ici, les deux, les deux formules ici vont être meilleures, parce que je vais avoir moins de lignes sortant des tables, si je peux dire, sur lesquelles je fais la jointure. Ce qui coûte cher, c'est de faire une jointure, hein, parce que ça, ça peut multiplier de beaucoup les les les lignes. Donc, le moins j'ai de lignes qui rentrent dans la jointure, le meilleur va être, meilleur va être ma requête. Donc, cette manière-là de faire, c'est sûr que c'est moins bien de faire comme ça, et ce sera toujours moins bien.

Donc, vous avez une heuristique qui vous dit, c'est toujours mieux de faire les sélections le plus tôt possible, les restrictions, pardon, le plus tôt possible. En revanche, entre le plan de gauche et le plan de droite, là, a priori, je ne peux pas décider. Je ne sais pas si c'est mieux de d'abord faire une jointure entre `client` et `compte`, ou si c'est mieux de faire une jointure entre `compte` et `opération`. Ça, ça va dépendre de la sélectivité de mes, de pardon, de mes jointures, de ça va dépendre de la sélectivité de mes restrictions et de comment je les combine par par derrière. Donc, là, pour pouvoir décider sur le fait de prendre la requête de gauche ou la requête de droite, il faut que j'aie une information sur les informations, il faut, il faut que j'aie des informations sur les données de la base de données. Combien il y a de lignes dans `client` ? Est-ce que c'est intéressant de, enfin, quelle est la proportion des clients qui s'appellent Sylvie ? Quelle est la proportion des comptes qui sont de type PEA ? Quelle est la proportion des opérations qui sont après le 1er janvier 2014 ? Tout ça, c'est important pour savoir un peu dans quel ordre je vais faire les choses. Voilà.

Donc, vous voyez, ça, ça va être le rôle derrière de, de, de l'optimiseur de décider, étant donné une requête, donc qui peut s'exprimer sous une certaine forme canonique, éventuellement, quel plan je choisis. Et le problème, c'est que des plans, il y en a pas deux, il y en a un très grand nombre, évidemment. Donc, ça, c'est le problème de l'optimisation de requête, pareil, qui qui n'est pas au programme. Mais l'algèbre relationnelle est intéressante de ce point de vue là, puisque vous allez pouvoir changer les opérateurs d'ordre et donc réussir à à optimiser vos expressions.

Alors, la deuxième chose, je fais quand même une parenthèse. La deuxième chose importante, c'est qu'il existe plusieurs algorithmes qui vont implémenter la jointure. Donc, la jointure, selon la manière dont je vais avoir stocké mes informations sur le disque, je vais pouvoir faire plusieurs types de jointures avec des complexités plus ou moins bonnes. Donc, là, il y a, c'est surtout là-dessus, en fait, que se fait la la réflexion de l'optimiseur, quel type de jointure je vais pouvoir faire, et cetera. Donc, ça, c'est, c'est à voir plus tard.

Donc, je termine avec, enfin, sur sur les opérations de de calcul avec, donc, des opérations supplémentaires pratiques, voilà, mais pas indispensables. Comme le renommage d'une colonne en une autre. Donc, là, je peux renommer `DN` vers `date de naissance`. Renommage pas très intéressant. Voilà. Et puis des choses qui, elles, par contre, sont très intéressantes et qui méritent de s'y attarder plus que ce que je ne vais faire là, qui sont les calculs de fonction et les calculs d'agrégat.

Un calcul de fonction, en fait, c'est quelque chose qui va être calculé pour une ligne donnée, sachant qu'une ligne, ça peut être le résultat d'une requête, donc il peut y avoir des jointures et des choses comme ça, et qui va s'exprimer comme une fonction mathématique sur un certain nombre de colonnes. Donc, je peux définir des intérêts comme étant la valeur du solde fois un certain pourcentage. Donc, ça, ce sera, ce sera appliqué pour chacune des lignes de, de la requête.

Et puis, la problématique des agrégats. Donc, là, conceptuellement, c'est, c'est, c'est plus compliqué, parce qu'il faut imaginer qu'on travaille plus nécessairement sur des ensembles, mais sur des multiensembles. Donc, vous allez avoir plusieurs lignes qui ont la même valeur, et vous allez regrouper donc ces ensembles de lignes sur certains critères. C'est-à-dire que vous allez dire, vous allez donner un ensemble d'attributs de regroupement, et toutes les lignes qui ont les mêmes valeurs sur ces ensembles d'attributs vont être groupées ensemble dans ce qu'on va appeler des groupes. Et par rapport à ces groupes-là, vous allez pouvoir calculer des opérations d'agrégation, c'est-à-dire des calculs qui se font sur l'ensemble des lignes. Alors, ça, c'est très important, he, parce que tout ce qui se passe avant, c'est toujours des choses qui se passent ligne à ligne. Si vous voulez calculer des choses comme le min, le max, la moyenne, ce sont des opérations d'agrégation. C'est, c'est des choses qui sont sur plusieurs lignes, donc qui se font en général sur des regroupements. Alors, soit c'est juste une opération d'agrégation sur l'ensemble des lignes de la requête, donc là, il n'y a pas de regroupement. Soit vous avez regroupé selon certains critères, et le min et le max sont calculés une fois pour chacun des groupes.

Alors, la manière dont ça, ça s'écrit dans l'algèbre relationnelle étendue aux agrégats, c'est avec un gamma. Enfin, en tout cas, plusieurs manières de faire. Moi, je l'écris comme ça, avec, à en indice gauche du du gamma, l'ensemble des attributs sur lesquels vous faites le regroupement, et dans la partie droite du gamma, l'ensemble des fonctions d'agrégation que vous voulez calculer. Du genre, là, vous projetez sur `ville`, et ici, vous projetez, enfin, vous calculez la moyenne des comptes, donc le moyen des soldes des comptes. Ou justement, comment est-ce qu'on va faire pour calculer le solde des comptes, puisque ici, on a que des opérations unitaires ? On va regrouper sur l'identifiant du compte, et on va calculer la somme des opérations. Somme algébrique. Quand vous faites une agrégation, vous avez une projection implicite ou explicite, c'est un peu, je ne sais pas comment il faut dire, sur l'ensemble de ces colonnes, c'est-à-dire les attributs de regroupement et les fonctions d'agrégation que vous avez calculées.

Donc, si dans ma requête, je vais regrouper selon un attribut, par exemple, l'attribut `ville`, je ne vais plus pouvoir projeter après que sur `ville` et les agrégations que j'aurais faites sur ces groupes. Ça ne fait pas sens de dire, j'ai regroupé par `ville`, et après, j'affiche le prénom d'une personne. D'accord ? Ça, mais n'empêche que parfois, on écrit ça, et et le problème, c'est que SQL l'accepte. Du coup, bah, qu'est-ce qu'il vous donne ? Il vous retourne une valeur un petit peu aléatoire, en général, la première qu'il aura calculée pour le groupe. Comme vous ne savez pas exactement comment il calcule, bah, c'est effectivement une valeur sur laquelle vous n'avez rien.

Deux exemples d'agrégat : un agrégat qui est calculé sur l'ensemble de la table. Donc, dans ce cas, j'ai `gamma`, et j'ai projeté sur rien, et j'ai calculé la moyenne de l'âge des étudiants. Donc, ça, ça donne quoi comme résultat ? Bah, ça va donner une relation qui possède une seule colonne, `moyenne_âge`, et une seule valeur, la moyenne des âges des étudiants. Si je fais le calcul de la moyenne d'âge, mais regroupé par ville, bah, je construis deux paquets : un paquet pour Versailles, un paquet pour Paris. Dans chacun des paquets, bah, là, chaque fois, j'ai, j'ai, j'ai deux étudiants. Ben, je calcule, alors c'était le, le max de leur âge.

Comment ça, ça s'écrit en SQL ? Avec les attributs de regroupement dans une clause `GROUP BY` qui apparaît derrière le `SELECT FROM WHERE`. Vous avez une dernière clause qui existe dans le, dans SQL, qui est la clause `HAVING`, qui, en fait, n'est rien de plus qu'une restriction, mais c'est une restriction qui se fait sur une condition d'agrégat. C'est que vous pouvez dire, avec le `WHERE`, vous filtrez des lignes. Donc, je dis, par exemple, je vais enlever tous les étudiants qui ont moins de 18 ans, et après, je vais calculer la moyenne d'âge sur les étudiants qui restent. Dans ce cas, vous allez filtrer `âge < 18` dans le `WHERE`. Le `HAVING`, vous permet de dire, je veux conserver uniquement les groupes qui possèdent une certaine caractéristique d'agrégat. Par exemple, je veux pas calculer la moyenne d'âge sur des groupes où il y aurait moins de 5 étudiants, pour des raisons de confidentialité, par exemple. Donc, toutes les villes où il y a moins de 5 étudiants, je ne calcule pas la moyenne d'âge. Dans ce cas, je vais devoir, voyez, moins de 5 étudiants, ça veut dire que j'ai compté combien il y avait d'étudiants dans un groupe. Compter, c'est une opération d'agrégation. Donc, je veux qu'il y ait plus de 5 étudiants dans un groupe, c'est pas quelque chose que vous pouvez exprimer dans le `WHERE`. Le `WHERE`, il parle juste ligne à ligne. Donc, c'est une condition que vous allez devoir mettre dans le `HAVING`. Quand vous écrivez votre requête SQL, par contre, sur le principe formel, si vous voulez, c'est la même chose, c'est une restriction, simplement, elle s'applique sur un groupe. Donc, le `WHERE`, en fait, ils ont choisi de faire comme ça dans la norme SQL. On aurait très bien pu se dire, ok, on le mettrait aussi dans le `WHERE`, mais voilà.

Alors, je propose une méthodologie. Alors, ça, c'est une méthodologie que, que j'ai faite moi. Elle vaut ce qu'elle vaut, mais comme je n'en trouvais pas vraiment, enfin, les gens ne vous disent pas comment faire, j'en ai mis une un petit peu au point pour pour les étudiants, qui explique un peu, par rapport à une, enfin, les questions qu'il faut se poser pour essayer de ne pas écrire n'importe quel type de requête. Ça ne vous dit pas comment tout faire, mais ça, ça permet de vous guider pour éviter de faire trop d'erreurs.

Donc, vous avez une requête `SELECT FROM WHERE GROUP BY HAVING` que vous voulez faire, et vous avez une question qui est en français. Alors, je propose de faire d'abord le `SELECT`, puis les groupes. Alors, ça, c'est, je pense, faut faire dans cet ordre-là, et après, les restrictions, les jointures, et les sous-requêtes. Là, on pourrait éventuellement changer un petit peu l'ordre.

On commence par le `SELECT`, pourquoi ? Parce que le `SELECT`, c'est ce qui est de plus simple à faire. Alors, autant commencer par un truc facile, ça permet de se mettre le pied à l'étrier. Donc, la clause `SELECT`, c'est les attributs sur lesquels j'ai projeté le résultat de ma requête. Donc, en fait, dans la clause `SELECT`, je vais mettre ce qu'on me demande à une requête, c'est typiquement, donnez-moi le nom et le prénom de ceci, cela. Bon, bah, je mets nom et prénom. Mais ce n'est pas tout. Je vais pouvoir déjà commencer à remplir la clause `FROM`, qui me dit quelles sont les sources de données dont je vais avoir besoin pour obtenir ces résultats. Si on me demande le nom, le prénom, et les opérations, le nom et le prénom se trouvent dans la table `client`, les opérations se trouvent dans la table `opération`. Donc, je sais déjà que pour avoir accès à ces trois informations au final, je vais devoir utiliser au moins la table `client` et au moins la table `opération`. Donc, je peux déjà commencer à les mettre dans la clause `FROM`. Je ne parle pas du point 3, c'est un petit peu du détail. Et puis, le point 4, c'est si on a des fonctions à calculer. Bon, on peut aussi les mettre donc dans ce `SELECT`, et puis identifier les informations nécessaires pour calculer ces fonctions, voir où elles se trouvent dans la base de données, ajouter ces tables dans la clause `FROM`.

Ensuite, si jamais on en a besoin, c'est-à-dire que si jamais c'est une requête où on fait des regroupements. Alors, ça, c'est assez facile à à identifier dans une requête, puisque ça veut dire, ben, je veux tel type d'information selon, je sais pas, la ville, ou regroupé par ceci ou cela. Donc, ça, ça veut dire qu'il y a un regroupement à faire. Donc, s'il y a un regroupement à faire, faut identifier les attributs sur lesquels on fait le regroupement, les mettre dans la clause `GROUP BY`, et si ces attributs interviennent, enfin, proviennent de tables qui ne sont pas déjà utilisées, on les rajoute dans la clause `FROM`. Et puis, on rajoute aussi dans la clause `SELECT` les attributs utilisés pour le partitionnement. Souvent, les attributs utilisés pour le partitionnement, vous les aurez déjà mis quand vous construisez la clause `SELECT`, parce que si on vous demande de regrouper par quelque chose, souvent on vous demande de l'afficher. C'est que si je vous demande la moyenne d'âge par ville, si vous me donnez juste les moyennes d'âge et pas à quelle ville ça correspond, bon, ça sert pas franchement à à grand-chose. Donc, en général, vous avez déjà fait ça dans la la première partie, construction du `SELECT`.

Alors, ensuite, bon, je fais dans cet ordre-là, vous construisez les restrictions. Alors, pareil, parce que c'est facile. On va vous demander tel que l'âge est plus petit que ceci ou ou cela. Vous construisez les restrictions sur des constantes, d'accord ? Donc, `âge < ceci` et ainsi de suite. Si jamais vous avez des restrictions sur des attributs qui proviennent de tables qui ne sont pas dans le `FROM`, pareil, vous les rajoutez. J'insiste sur le fait qu'une condition de restriction peut s'exprimer en utilisant une sous-requête. Si c'est le cas, on le traite à la fin. Et comme vous avez déjà fait le `GROUP BY`, si vous avez des restrictions qui se font sur des regroupements, bah, vous les inscrivez dans la clause `HAVING` ensuite.

Et là, c'est pratiquement terminé. Vous construisez les jointures. C'est que maintenant, vous avez plein de tables, il faut les lier ensemble par un chemin qui fait sens. Et en général, dans 99 % des requêtes, en tout cas, dans 99 % des requêtes réalistes, le chemin, il se fait sur la base des clés étrangères, c'est-à-dire, bah, sur ce qui lie quoi. Un client est lié à à son compte par son `ID client`. Donc, faut que `ID client` soit égale à `ID propriétaire` du compte, ou ou ce genre de chose. Si jamais vous ne savez pas comment joindre deux tables, et ben, ça veut dire qu'il manque peut-être une table intermédiaire entre ces deux-là, une ou plusieurs. Donc, il va falloir encore une fois rajouter et puis créer le chemin correspondant. Donc, on voit que plus il y a de bases, plus il y a de tables dans la base de données, plus vous avez plein de tables dans la clause `FROM`, plein de jointures à faire. Mais sur le principe, c'est exactement la même difficulté qu'à quand vous avez trois tables et que vous vouliez la table qui est la plus à gauche avec la table qui est la plus à droite. Ben, si elles sont liées par la table au milieu, il va falloir la rajouter dans la clause `FROM`. Donc, vraiment, juste avec trois tables, on a, on a tout ce qu'il faut.

D'une manière générale, une clé étrangère, c'est quelque chose de monovalué. Donc, si vous avez N tables dans votre clause `FROM`, il faudra avoir N-1 condition de jointure dans la clause `WHERE`. Ça, ce n'est pas toujours vrai, mais globalement, en tout cas, si vous avez moins de N-1 condition de jointure et N tables, alors il y a certaines tables que vous combinez en faisant un produit cartésien. Il y a de grandes chances pour que le résultat soit, d'une part, trop grand, d'autre part, complètement faux.

Et finalement, on construit les sous-requêtes. Alors, ça, c'est le truc un petit peu difficile, c'est-à-dire que, en fait, dans votre restriction, vous aviez une valeur qui n'était pas une constante, mais qui était quelque chose qui était calculé. Par exemple, on dit, je veux que l'âge de la personne soit plus petit que la moyenne d'âge calculée sur l'ensemble des clients. Vous voyez que ça, c'est une restriction. Il faut que l'âge du tuple soit plus petit qu'une certaine valeur, mais cette valeur-là, elle doit être calculée par une requête. Donc, calculée par une sous-requête. Et là, vous avez deux sortes de sous-requêtes : des sous-requêtes non paramétrées, c'est le cas de celle que je, dont je viens de parler, c'est que la moyenne d'âge, c'est quelque chose qui se calcule une fois pour toutes. Ou bien, quelque chose de paramétré, c'est-à-dire que dans cette sous-requête, je vais utiliser des informations du tuple que je suis en train d'étudier, donc de la ligne que je suis en train d'étudier. D'accord ? Par exemple, ce sera, je veux les personnes qui habitent dans une ville tel que, je ne sais pas quoi, qui ferait intervenir la ville. Bon, j'ai des exemples après, mais mais vous pouvez assez facilement voir ce qui est non paramétré, c'est quelque chose qui se calcule une fois pour toutes, et quelque chose qui est paramétré, c'est quelque chose qui utilise une information du tuple que vous êtes en train de de traiter. Voilà.

Et une fois que vous avez ça, et donc votre sous-requête, bah, votre sous-requête, vous la calculez exactement comme vous, enfin, vous l'écrivez exactement comme vous, vous écriviez l'autre, l'autre requête. Donc, une fois que vous avez fait ça, donc, c'est une, une méthodologie que je présente un petit peu aux étudiants, parce que souvent, ils oublient de faire des jointures, ils oublient de faire des regroupements, ils savent pas comment placer le `HAVING`, et cetera. Donc, bon, je dis pas que c'est super ou quoi, mais voilà, c'est un petit peu une checklist qui permet de contrôler un peu les requêtes qu'on est en train d'écrire, d'accord, et puis de guider humblement le l'élève aussi.

Alors, j'ai pratiquement fini, juste deux transparents là-dessus, sur l'architecture client-serveur ou 3 tiers. Je le montrerai après. Un SGBD, donc, c'est un logiciel, il tourne sur une machine, c'est la machine serveur, serveur SGBD. Donc, quand vous faites tourner un SGBD, donc, par exemple, Oracle, par exemple, MySQL, vous avez, ça tourne sur sur votre machine, où ça tourne ailleurs. Ça, c'est la machine serveur SGBD. Quand vous faites tourner MySQL, vous êtes, enfin, en général, vous faites tourner aussi un serveur web, Apache, qui est le serveur application, qui tourne souvent sur votre machine, mais qui peut tourner ailleurs. Et c'est ce serveur-là qui permet de dialoguer avec les personnes qui posent des requêtes sur la base de données.

Alors, quand vous, vous êtes en train de travailler sur votre machine, vous ouvrez votre navigateur, qui est le 3ème tiers, donc le 3ème niveau, qui est aussi sur votre machine. Donc, votre machine, c'est à la fois la machine client, la machine intermédiaire, donc serveur d'application, et la machine serveur base de données. Mais vous êtes dans le cas d'une architecture 3 tiers, vous avez trois entités différentes qui pourraient éventuellement être placées sur des machines distinctes. Dans le cas du client-serveur, vous avez juste le SGBD et une application cliente qui dialogue directement avec le SGBD. Ce qui veut dire qu'elle se connecte sur les ports du SGBD, qu'elle a des droits d'accès au SGBD, qu'elle interroge les données directement, qu'elle pose des requêtes au au SGBD. Quand vous êtes sur une architecture 3 tiers, c'est le serveur d'application qui interroge la base de données.

Alors, quel est l'intérêt d'avoir une architecture 3 tiers par rapport à une architecture client-serveur ? Bon, le le le vrai intérêt, je pense, on vous en présente plein, mais le le vrai intérêt, c'est l'équilibrage de charge entre le travail qui doit être fait purement base de données et le fait de dialoguer avec des clients et cetera, d'obtenir des des des connexions. Donc, voilà, ça, ça permet de décharger le SGBD de plein de clients qui essaient de se connecter pour centraliser tout ça sur une seule machine. C'est un petit peu plus simple d'avoir plusieurs serveurs d'application, euh, qui éventuellement, he, peuvent peuvent retraiter les données de manière de manière intermédiaire pour présenter des données un petit peu différentes, comme faire des présentations HTML ou ou des choses ou des choses comme ça. L'avantage quand même de faire du client-serveur, moi, je trouve, c'est que ça vous donne une gestion des droits qui est directement faite par le, faite par le SGBD. Donc, donc, voilà, vous avez un petit peu, bon, la sécurité, disons, c'est discutable. Mais le gros avantage de l'architecture 3 tiers, c'est déjà de permettre une interrogation à partir de quelque chose qui est assez générique, donc un navigateur web, et puis l'équilibrage de charge du côté du côté applicatif. Voilà.

Donc, dans client-serveur, qui était la manière ancienne de fonctionner, vous deviez développer à chaque fois une application qu'on va appeler métier, c'est-à-dire le client qui va interroger votre base de données. Ce qu'on a à l'heure actuelle, c'est essentiellement, voilà, des serveurs web qui sont bien rodés, et puis des applications derrière qui sont des applications web qui interrogent ce serveur-là. Donc, une base de données, un serveur web, et un navigateur, c'est une manière d'instancier l'architecture 3 tiers, qui est la manière très usuelle de le faire à l'heure actuelle. Mais vous pouvez avoir des choses différentes. Mais voilà. Et ces serveurs, le SGBD, et puis une petite fenêtre ou une application qui interroge directement. Moi, je vais donner dans la, dans la deuxième partie, un petit exemple. Voilà, j'écris mon programme qui qui se connecte au SGBD.

Alors, ce qu'on vous dit parfois, c'est que l'intérêt de l'architecture 3 tiers, c'est de permettre de faire un certain nombre de traitements sur sur le serveur applicatif. Par exemple, faire des traitements en PHP, de choses sous-entendues, c'est mieux de les faire avec Java ou avec PHP plutôt que de les faire sur le serveur à l'aide de l'algèbre relationnelle. Ça, en général, c'est pas vrai. Relationnelle, c'est quand même quelque chose qui marche bien, qui optimise bien, et donc, si vous pouvez écrire quelque chose avec l'algèbre relationnelle, il ne faut pas se priver de le faire. Souvent, ça, ça va aller plus vite si c'est fait sur le SGBD. Le souci, c'est que le SGBD, bon, souvent, c'est un serveur unique. Donc, si vous demandez beaucoup de choses au SGBD, lui, ça peut le surcharger. Donc, ça peut être intéressant pour décharger le SGBD de nombreuses requêtes qui lui arrivent, de faire faire un peu de travail par quelqu'un d'autre, par le serveur intermédiaire, concurrence. Mais au final, pour l'utilisateur qui pose sa requête, ça va aller plus lentement. D'accord ? Lui, s'il avait posé directement au SGBD, ça aurait été peut-être calculé plus vite, il aurait eu plus vite son résultat. Mais globalement, comme vous avez plein d'utilisateurs, vous déchargez le SGBD, donc vous le rendez plus disponible, et les calculs intermédiaires sont faits plus lentement, mais de manière distribuée par des serveurs intermédiaires. Donc, là, c'est un petit peu au cas par cas. Enfin, il faut faire une étude du système pour savoir, est-ce que votre serveur SGBD, il est surchargé ? Donc, il faut essayer de se débrouiller pour que les requêtes, si on ne peut pas réduire le nombre de requêtes, donc, il faut que les requêtes aillent plus vite. Donc, on va faire des requêtes plus simples, et on va demander à un serveur intermédiaire, voir au client, de les retraiter lui-même. Soit votre serveur SGBD, il a pas grand-chose à faire, et c'est votre serveur web qui mouline, parce que vous lui demandez de faire des choses compliquées comme des regroupements en Java. Souvent, on voit ça quand on fait des expertises de programmes qui sont écrits par des professionnels, au sens que c'est leur métier, hein, pas qu'ils savent bien le faire, euh, et euh, et et là, à ce moment-là, il vaut mieux décharger le serveur applicatif vers le SGBD. Voilà. Donc, là, faut, faut regarder, et et ça demande une, une bonne, bonne analyse. Voilà.

Donc, là, j'avais un certain nombre d'exercices que vous pouvez retrouver sur le poly. Alors, pas la version qui est sur le site, parce qu'on a un petit peu de retard avec la synchronisation, mais sur le lien que j'avais donné à Francis, je ne sais pas si vous l'il vous l'a transmis. Tu veux relire ? Alors, oui, je ne l'ai pas en tête, mais bon, on pourra le remailer. Donc, un certain nombre d'exercices avec à chaque fois la correction, et où j'essaie un petit peu d'expliquer pourquoi on fait comme ça, est-ce qu'il y avait d'autres alternatives, et cetera. Donc, ça correspond à un TP qui peut être fait, voilà, en 3 heures, avec avec les élèves, avec les étudiants, pour essayer de faire un peu le tour des requêtes SQL. À chaque fois, j'essaie de traiter un problème différent. Vous pouvez évidemment leur demander de faire plein de requêtes du même type pour voir s'ils réussissent à les refaire. Voilà.

Des questions sur les agrégats ? Quand on fait des fonctions, ça s'applique que par colonne ? On peut faire des fonctions qui vont utiliser les données de plusieurs colonnes en même temps ? Alors, les fonctions d'agrégat, bah, on peut mettre à l'intérieur du paramètre de l'agrégat, effectivement, une valeur qui prendrait plusieurs colonnes. Ce qui compte, c'est qu'effectivement, je ne sais pas si on veut multiplier quelque chose, enfin, faire n'importe quel calcul algébrique sur des colonnes, c'est tout à fait possible. Par contre, ça va le faire sur une ligne donnée, d'accord ? Donc, par exemple, ça va multiplier, je ne sais pas, l'opération par autre chose, par par un facteur, mettons, pour le traduire en dollars. Donc, ça, c'est ce que je vais mettre à l'intérieur de la parenthèse où je vais calculer la somme par derrière. Donc, ouais, c'est tout à fait possible. Voilà. Mais il faut bien voir que, donc, c'est plusieurs colonnes sur une ligne, et après, l'agrégation se fait sur ce là. Donc, ouais, c'est naturel, ça, c'est de manière naturelle.

Oui, bonjour. Au sujet des architectures, pour des raisons d'intendance, on va être un certain nombre de collègues à travailler à la maison, mais aussi au lycée, sur des bases SQLite. Est-ce que, est-ce que là, on est dans une architecture typique client-serveur, ou est-ce que c'est encore un autre truc ? Euh, mais pourquoi vous, enfin, B, vous avez mis où votre base de données, en fait ? Elle est sur quelle machine ? Elle est sur une machine, c'est une application qui, en fait, elle est dans un fichier. C'est quand même très spécial. Ah, et donc, est-ce que là, on est plutôt en dehors des des architectures telles que tu les as décrites là ? C'est du client-serveur, enfin, disons, disons, vous avez embarqué, c'est ce qu'on dit, c'est, on va embarquer le serveur dans une application. Donc, là, vous êtes sur plutôt du client-serveur, si on peut dire, où le client et le serveur sont sur la même machine. Mais, dis, faut bien séparer les rôles entre le SGBD, qui est normalement, enfin, parce que quand vous faites les appels, vous allez faire quand même des appels en utilisant JDBC ou en utilisant des interfaces assez classiques, qui qu'on pourrait faire avec un serveur de base de données classique. Donc, on a bien cette séparation entre ce qui est fait par le serveur et ce qui est fait par l'application. La seule différence, c'est qu'effectivement, tout est mis en sur une seule machine, et donc, vous avez, communique même pas, enfin, voilà, il communique directement. Donc, on peut dire, c'est une espèce de client-serveur, quoi. Mais bon, oui.

Une question sur la, la base de données sur les étudiants. Est-ce que ça peut avoir un intérêt en terme de mémoire ou d'efficacité de mettre dans la table `ville` une clé primaire numérique et de mettre dans la base, dans la table `étudiant`, juste le numéro plutôt que la, bon, que la ville ? Alors, ce qui est fait toujours. Donc, la question, elle est, elle est ici, hein. Donc, vous avez vu, là, j'ai défini, en fait, de manière implicite, enfin, ici, j'ai estimé que `NonVille` était une clé primaire, d'accord ? Donc, effectivement, ça, c'est une valeur unique qui se qui apparaît, et on fait des jointures sur ces chaînes de caractères. Donc, effectivement, on comprend bien que faire des jointures sur des chaînes de caractères, c'est quelque chose qui est qui est pas très rapide. Donc, bon, vous avez toujours des valeurs numériques qui sont associées aux aux chaînes de caractères. C'est que même si vous indexez comme ça, même si vous dites juste, je vais indexer les chaînes de caractères, le calcul qui sera fait par derrière, ce sera une égalité sur des valeurs qui sont numériques. Donc, bon, enfin, dépendant, ça dépend de votre SGBD, hein, mais en général, il va quand même vous le réindexer automatiquement avec quelque chose qui va être numérique. Après, vous pouvez le faire vous-même. Donc, avoir des champs numériques, ça, ça vous prend un petit peu de place, mais la place, ce n'est pas vraiment un problème pour les SGBD, et effectivement, après, vous faites des comparaisons sur les choses qui sont numériques. Donc, donc, c'est plus rapide. Mais, mais en fait, dès lors que vous indexez, souvent, il vous crée automatiquement, sans vous le dire, une valeur numérique. Donc, vraisemblablement, ça ne changera rien. Merci.

Bon, ben, on va maintenant se séparer entre les différents groupes. Merci beaucoup. Bon, merci de votre attention.