<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<book>
  <title lang="fr">Conception et base de données</title>

  <bookinfo>
    <author>
      <surname>KURZWEG</surname>

      <firstname>Ivan</firstname>

      <email>ik-r@wanadoo.fr</email>
    </author>

    <releaseinfo>Version 1.1</releaseinfo>

    <corpname>GRETA Neotech III</corpname>

    <date>Last Updated: $Date: 2006/03/06 09:43:02 $</date>

    <legalnotice>
      <para>Permission to use, copy, modify, and distribute this documentation
      for any purpose with or without fee is here by granted, provided that
      the above copyright notice and this permission notice appear in all
      copies.</para>

      <para>THE DOCUMENTATION IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
      WARRANTIES WITH REGARD TO THIS DOCUMENTATION INCLUDING ALL IMPLIED
      WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
      BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR
      ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
      WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
      ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
      DOCUMENTATION.</para>
    </legalnotice>
  </bookinfo>

  <chapter>
    <title>Merise et Bases de données</title>

    <para>Dans ce chapitre, nous allons faire une première approche de la
    méthode de conception de systèmes informatiques, Merise. Aspect historique
    et général d’abord, puis ensuite les différents niveaux de modélisation,
    ainsi que les étapes et les documents qui jalonnent la conception d’un
    SI.</para>

    <sect1>
      <title>Présentation de Merise</title>

      <sect2>
        <title>Intoduction / historique</title>

        <para>MERISE est une méthode de conception, de développement et de
        réalisation de projets informatiques, mise au point par une équipe de
        chercheurs français, sur commande du Ministère de l’Industrie en 1977.
        La collaboration entre des universitaires, des professionnels et des
        spécialistes en organisation d’entreprise a abouti à la publication
        d’un ouvrage en 1978.</para>

        <para>La méthode a ensuite donné lieu à plusieurs mises à jour, et on
        a parlé de « MERISE 2 ». Aujourd’hui, la méthode Merise reste une
        référence en matière de conception de systèmes d’information. Mais la
        montée en puissance de <emphasis>l’approche objet </emphasis>pose
        certains problèmes, en particulier au niveau de la séparation des
        données et des traitements.</para>

        <para>Une nouvelle méthode s’affirme, <abbrev>UML</abbrev>
        (<literal>United Modeling Language</literal>), et fait de plus en plus
        d’ombre à Merise. Mais dans le cadre de cette formation, Merise
        convient parfaitement, les outils de gestion de base de données
        orientée web étant basés plus sur une approche relationnelle que sur
        une approche orientée objet.</para>
      </sect2>

      <sect2>
        <title>Une approche par niveaux - Le cycle d'abstraction</title>

        <para>Parce que la maintenance d’une application informatique met
        clairement en évidence plusieurs types de problèmes, depuis les
        modifications qu’entraîne un changement de matériel, jusqu’à la
        refonte complète de l’application qu’exige la mise en place d’une
        réglementation totalement nouvelle, il a paru essentiel de dégager des
        niveaux correspondant à ces préoccupations différentes. Pour Merise et
        la plupart des méthodes de conception, il est classique de mettre en
        évidence 3 niveaux de réflexion :</para>

        <sect3>
          <title>Le niveau conceptuel</title>

          <para>Il correspond à la définition des finalités de l’entreprise en
          explicitant sa raison d’être. Ce niveau, décrit à travers un
          ensemble de règle de gestion, traduit les objectifs et les
          contraintes qui pèsent sur l’entreprise. On y retrouve par exemple
          les règles de gestion du personnel, de tenue de la comptabilité, de
          livraison des produits finis, etc..</para>
        </sect3>

        <sect3>
          <title>Le niveau organisationnel</title>

          <para>Son rôle est de définir l’organisation qu’il est souhaitable
          de mettre en place dans l’entreprise. On parle de choix
          d’organisation. L’analyste précise les postes de travail, la
          chronologie des opérations, les choix d’automatisation, etc..</para>
        </sect3>

        <sect3>
          <title>Le niveau technique</title>

          <para>Enfin, sont intégrés les moyens techniques nécessaires au
          projet. Ils s’expriment en terme de matériels ou de logiciels, et
          sont les plus sujets à changements (évolution technologique).</para>
        </sect3>

        <sect3>
          <title>Le cycle d'abstraction</title>

          <para>La conception du système d'information se fait par étapes,
          afin d'aboutir à un système d'information fonctionnel reflétant une
          réalité physique. Il s'agit donc de valider une à une chacune des
          étapes en prenant en compte les résultats de la phase précédente.
          D'autre part, les données étant séparées des traitements, il faut
          vérifier la concordance entre données et traitements afin de
          vérifier que toutes les données nécessaires aux traitements sont
          présentes et qu'il n'y a pas de données superflues. Cette succession
          d'étapes est appelée <citation>cycle d'abstraction pour la
          conception des systèmes d'information :</citation></para>

          <orderedlist>
            <listitem>
              <para>Système d'information manuel</para>
            </listitem>

            <listitem>
              <para>Expression des besoins</para>
            </listitem>

            <listitem>
              <para>Modèle conceptuel</para>
            </listitem>

            <listitem>
              <para>Modèle logique</para>
            </listitem>

            <listitem>
              <para>Modèle physique</para>
            </listitem>

            <listitem>
              <para>Système d'information automatisé</para>
            </listitem>
          </orderedlist>

          <table>
            <title>Les différents modèles de Merise</title>

            <tgroup cols="4">
              <tbody>
                <row>
                  <entry><emphasis>Niveaux</emphasis></entry>

                  <entry><emphasis>Données</emphasis></entry>

                  <entry><emphasis>Traitements</emphasis></entry>

                  <entry><emphasis>Questions</emphasis></entry>
                </row>

                <row>
                  <entry><emphasis>Conceptuel</emphasis></entry>

                  <entry>Modèle Conceptuel des Données
                  (<abbrev>MCD</abbrev>)</entry>

                  <entry>Modèle conceptuel des Traitements
                  (<abbrev>MCT</abbrev>)</entry>

                  <entry>Quoi ?</entry>
                </row>

                <row>
                  <entry><emphasis>Organisationnel</emphasis></entry>

                  <entry>Modèle Logique des Données
                  (<abbrev>MLD</abbrev>)</entry>

                  <entry>Modèle Organisationnel des Traitements
                  (<abbrev>MCT</abbrev>)</entry>

                  <entry>Qui ? Où ? Comment ?</entry>
                </row>

                <row>
                  <entry><emphasis>Technique</emphasis></entry>

                  <entry>Modèle Physique des Données
                  (<abbrev>MPD</abbrev>)</entry>

                  <entry>Modèles Opérationnel des Traitements
                  (<abbrev>MOpD</abbrev>)</entry>

                  <entry>Comment ?</entry>
                </row>
              </tbody>
            </tgroup>
          </table>
        </sect3>
      </sect2>

      <sect2>
        <title>La courbe du soleil</title>

        <para>La courbe du soleil permet de représenter le cycle de vie du
        projet selon Merise. On remarque une montée vers le niveau conceptuel,
        qui correspond à une étude de l’existant, puis une redescente vers le
        niveau physique, c’est la phase de conception.</para>

        <figure>
          <title>Courbe du soleil</title>

          <mediaobject>
            <imageobject>
              <imagedata fileref="courbe_soleil.jpg" />
            </imageobject>
          </mediaobject>
        </figure>
      </sect2>

      <sect2>
        <title>Application au développement Web</title>

        <para>Comme nous venons de le voir, Merise est à la fois une méthode
        d'analyse informatique et une méthode de conduite de projet.
        Parfaitement adaptée à la réalisation de systèmes d'information
        importants, elle reste cependant très vaste comparativement aux
        besoins exprimés dans le cadre d'un développement d'une application
        Internet.</para>

        <para>Ainsi, nous allons recentrer notre étude de Merise sur la
        modélisation des données. En effet, la plupart des applications
        orientées Internet utilisent aujourd'hui une base de données comme
        support d'informations. Mais la conception d'une base de données peut
        rapidement tourner au cauchemar si l'emploi d'une méthode fiable est
        ignoré. Dans les chapitres suivants, nous allons donc examiner les
        procédures permettant de modéliser le <emphasis>"réel"</emphasis> en
        une base de données solide et bien conçue.</para>
      </sect2>
    </sect1>

    <sect1>
      <title>Modèle Entité Association</title>

      <para>La modélisation conceptuelle des données est la
      <emphasis>représentation de l’ensemble des données du système
      d’information</emphasis> étudié, sans tenir compte des aspects
      organisationnels et techniques liés à leur mise en œuvre dans tel ou tel
      traitement. Cette représentation, appelée « <emphasis><command>schéma
      conceptuel des données</command></emphasis> »est obtenue par la mise en
      œuvre des concepts et des outils du modèle entité - association de la
      méthode Merise.</para>

      <itemizedlist>
        <listitem>
          <para>Il y a nécessité de <emphasis>formaliser</emphasis> le SCD
          (schéma conceptuel des données) En analyse, pour traiter un
          problème, une situation, il faut :</para>

          <para><figure>
              <title>Formalisation du MCD</title>

              <mediaobject>
                <imageobject>
                  <imagedata fileref="bdd_mcd.jpg" />
                </imageobject>
              </mediaobject>
            </figure></para>
        </listitem>

        <listitem>
          <para>Caractéristiques d’un formalisme :</para>

          <itemizedlist>
            <listitem>
              <para>Approche naturelle et de compréhension aisée (pour les
              analystes et les utilisateurs)</para>
            </listitem>

            <listitem>
              <para>Rigoureux</para>
            </listitem>

            <listitem>
              <para>Informatisable</para>
            </listitem>
          </itemizedlist>
        </listitem>
      </itemizedlist>

      <sect2>
        <title>Dictionnaire des données</title>

        <para>Une des images les plus classique de l’informaticien est celle
        d’un technicien concevant des solutions géniales à des problèmes qui
        ne lui sont pas posés, et rétif à tout dialogue avec l’utilisateur.
        Même si les cas d’écoles qui sont présentés en formation ont des
        objectifs clairement posés sur un existant vide, dans la vie
        professionnelle, il en va généralement bien autrement. Lors des
        différentes interviews qui jalonnent l’étude préalable, l’analyste
        recense les données apparaissant dans les différents documents de
        l’entreprise. Au cours de la conception détaillée, il va tenter de les
        décomposer en <emphasis>données élémentaire</emphasis>s, et les
        épurer, c’est-à-dire n’en retenir que les pertinentes.</para>

        <para>Etablir un dictionnaire des données, c'est <emphasis>recenser
        l'ensemble des informations de l'application</emphasis>, et leur
        attribuer un type de données, c'est-à-dire indiquer sous quelle forme
        informatique elles seront enregistrées.</para>

        <sect3>
          <title>Etablir la liste des données élémentaires</title>

          <para>Une donnée élémentaire est une donnée qui ne peut être
          décomposée. Souvent les données brutes sont constituées de plusieurs
          parties, mais on ne doit décider de les décomposer qu’en fonction de
          l’usage qui en sera fait.</para>

          <example>
            <title>Exemple</title>

            <para>Une adresse postale d’un client est une donnée brute, qu’on
            peut décomposer en <emphasis>AdresseRue,</emphasis>
            <emphasis>CodePostal</emphasis> et <emphasis>Ville.</emphasis>
            Cela permet par exemple de sélectionner tous les clients d’une
            ville. Mais si on a aussi besoin de connaître tous les clients
            d’une rue, on sera alors obligé de décomposer
            <emphasis>AdresseRue</emphasis> en <emphasis>NuméroRue</emphasis>
            et <emphasis>NomRue.</emphasis></para>
          </example>
        </sect3>

        <sect3>
          <title>Epurer les données</title>

          <para>Lorsque deux noms recouvrent la même réalité, il s’agit d’une
          <emphasis>synonymie.</emphasis> Lorsqu’un même nom de données
          recouvre plusieurs réalités, il s’agit d’une
          <emphasis>polysémie.</emphasis> Il faut bien sûr supprimer ces deux
          défauts.</para>

          <example>
            <title>Exemple</title>

            <para><emphasis>CodeClient</emphasis> et
            <emphasis>referenceClient</emphasis> sont deux noms de données qui
            peuvent recouvrir la même réalité, c’est-à-dire le moyen
            d’identifier le client. Il ne faut donc retenir qu’un seul nom
            pour cette propriété.</para>
          </example>
        </sect3>

        <sect3>
          <title>Distinguer les données calculées des données non
          calculées</title>

          <para>Une donnée calculée est une donnée dont la valeur peut être
          obtenue en appliquant une règle de calcul aux valeurs d’autres
          données élémentaires. Ces données ne doivent pas entrer dans le
          modèle conceptuel des données.</para>
        </sect3>

        <sect3>
          <title>Dresser le dictionnaire des données</title>

          <para>Les données élémentaires, calculées ou non calculées, épurées
          et retenues pour leur pertinence, constituent le dictionnaire des
          données. Pour chacune d’elles, on précise le type et le domaine de
          définition. On indiquera également si elles sont calculées ou
          non.</para>
        </sect3>

        <sect3>
          <title>Exercice</title>

          <para>Tout au long de ce dossier, nous allons tenter de modéliser un
          système d’information concernant des accidents de la circulation. En
          voici les grands traits :</para>

          <para><application><emphasis>Dans un double objectif de suivi et de
          prévention des accidents de la route, il a été décidé de nommer un
          haut responsable, M. Sécurité. Celui-ci dispose uniquement d’une
          remontée quotidienne d’informations, constituée par les photocopies
          des constats d’accident à l’amiable, transmise par les compagnies
          d’assurance. Outre des études ponctuelles, il fournira
          périodiquement un tableau de bord de la sécurité routière. M.
          Sécurité gère cette information pour les objectifs qui lui ont été
          assignés. C’est pourquoi, il place hors de son champ d’étude tout ce
          qui est lié au strict problème d’assurance.</emphasis>
          </application></para>

          <example>
            <title>Exercice</title>

            <para>Etablir le dictionnaire des données pour ce SI. Un exemple
            de constat à l’amiable vous est fourni ...</para>
          </example>
        </sect3>
      </sect2>

      <sect2>
        <title>Propriété</title>

        <para><emphasis><emphasis role="bold">Définition</emphasis>
        :</emphasis> Appelée aussi information élémentaire, données
        élémentaire ou rubrique, la propriété désigné le plus petit élément
        d’information manipulable. Pour être correctement définie, une
        propriété doit toujours être décrite par un « nom de propriété »,
        prendre ses valeurs dans un domaine de valeurs et avoir un sens dans
        le système d’information étudié.</para>

        <para><remark>Remarque : Une propriété est véritablement élémentaire
        si elle n’est pas décomposable en un ensemble de propriétés
        signifiantes plus petites. On dit alors qu’elle est atomique. Par
        exemple, une adresse postale peut être décomposé en : - numéro de rue
        - nom de rue - code postal - ville Mais cette décomposition fine n’est
        pas systématique, elle est uniquement guidée par la pertinence à
        traduire une réalité de l’entreprise. Ainsi, il n’est pas nécessaire
        de découper une date en trois propriétés distinctes, jour, mois et
        année.</remark></para>
      </sect2>

      <sect2>
        <title>Entités</title>

        <sect3>
          <title>Définition</title>

          <para><application>Une entité est un type d’élément (abstrait ou
          concret) du monde réel défini par : - une existence propre et une
          utilité pour l’organisation étudiée - des occurrences multiples
          (c’est-à-dire au moins deux) - des propriétés (au moins une), dont
          un identifiant. </application></para>
        </sect3>

        <sect3>
          <title>Formalisme</title>

          <para><application>L’entité est représentée par un
          rectangle.</application><figure>
              <title>Entité</title>

              <mediaobject>
                <imageobject>
                  <imagedata fileref="bdd_entite.jpg" />
                </imageobject>
              </mediaobject>
            </figure></para>
        </sect3>

        <sect3>
          <title>Exercice</title>

          <para><application>La liste épurée des données conçue au précédent
          exercice fait apparaître deux acteurs essentiels d’un accident,
          <command>VEHICULE</command> et <command>CONDUCTEUR</command>.
          Représentez ces deux objets sous forme d’entité.
          </application></para>
        </sect3>
      </sect2>

      <sect2>
        <title>Identifiant</title>

        <sect3>
          <title>Définition</title>

          <para><application>Parmi toutes les propriétés d’une entité, une ou
          plusieurs d’entre elles doivent jouer un rôle particulier, celui de
          permettre de distinguer chaque occurrence de l’entité par rapport à
          toutes les autres. Cette propriété ou groupe de propriétés est
          appelé identifiant. Il existe plusieurs types d'indentifiant :
          </application></para>

          <para><application> <emphasis>Identifiant simple</emphasis> : il
          est composé d’une seule propriété (exemple précédent) <emphasis>
          Identifiant composé</emphasis> : il est composé de deux propriétés
          ou plus. <emphasis> Identifiant relatif</emphasis> : il est
          constitué pour partie d’une propriété appartenant à une autre
          entité.  <emphasis>Identifiant hérité</emphasis> : il résulte d’un
          lien de dépendance avec une entité générique. </application></para>
        </sect3>

        <sect3>
          <title>Formalisme</title>

          <para><application>L’identifiant d’une entité est l’ensemble des
          propriétés soulignées.</application><figure>
              <title>Identifiant</title>

              <mediaobject>
                <imageobject>
                  <imagedata fileref="bdd_ident.jpg" />
                </imageobject>
              </mediaobject>
            </figure></para>
        </sect3>

        <sect3>
          <title>Exercice</title>

          <para><application>Indiquez les identifiants des entités définies
          dans l’exercice précédent. Justifiez vos choix</application></para>
        </sect3>
      </sect2>

      <sect2>
        <title>Associations</title>

        <para><emphasis role="bold">Définition</emphasis> : Une association
        est un type d’élément du monde réel défini par : - une absence
        d’existence intrinsèque - au moins une occurrence - une dimension
        (mesurée par le nombre d’entités rattachées) - une utilité pour
        l’organisation étudiée. .</para>

        <para><emphasis role="bold">Formalisme</emphasis> : L'association est
        représentée par un ovale.<figure>
            <title>Association</title>

            <mediaobject>
              <imageobject>
                <imagedata fileref="bdd_assoc.jpg" />
              </imageobject>
            </mediaobject>
          </figure></para>

        <example>
          <title>Dimensions d'associations</title>

          <itemizedlist>
            <listitem>
              <para>Association entre deux entités (dimension 2) :<figure>
                  <title>Association binaire</title>

                  <mediaobject>
                    <imageobject>
                      <imagedata fileref="bdd_assoc_bin.jpg" />
                    </imageobject>
                  </mediaobject>
                </figure></para>
            </listitem>

            <listitem>
              <para>Association entre trois entités (dimension 3) :<figure>
                  <title>Association ternaire</title>

                  <mediaobject>
                    <imageobject>
                      <imagedata fileref="bdd_assoc_ter.jpg" />
                    </imageobject>
                  </mediaobject>
                </figure></para>
            </listitem>

            <listitem>
              <para>Association réflexive (dimension 1) :<figure>
                  <title>Association réflexive</title>

                  <mediaobject>
                    <imageobject>
                      <imagedata fileref="bdd_assoc_une.jpg" />
                    </imageobject>
                  </mediaobject>
                </figure></para>
            </listitem>
          </itemizedlist>
        </example>

        <para><emphasis>Exercice :</emphasis></para>

        <para>1. Dans l’exercice précédent, nous avons considéré un conducteur
        comme une personne, mais aussi comme le titulaire d’un permis de
        conduire. M. Sécurité souhaite établir un rapport entre les types de
        permis, leur « ancienneté », et la dangerosité du conducteur.
        Décomposez l’entité CONDUCTEUR en 2 entités, et indiquez leur
        association. 2. Modélisez maintenant les accidents. Un accident
        implique deux véhicules et deux conducteurs…</para>
      </sect2>

      <sect2>
        <title>Occurence</title>

        <para><emphasis role="bold">Définition</emphasis> : Une occurrence de
        propriété est une valeur que peut prendre une propriété.</para>

        <sect3>
          <title>Occurence d'une entité</title>

          <para>Une occurrence d’entité est un ensemble ayant une existence
          propre d’occurrences de ses propriétés.</para>

          <para><example>
              <title>Occurence d'une entité</title>

              <para>Soit l'entité suivante : <figure>
                  <title>Entité stagiaire</title>

                  <mediaobject>
                    <imageobject>
                      <imagedata fileref="bdd_entite_stag.jpg" />
                    </imageobject>
                  </mediaobject>
                </figure></para>

              <para>L’ensemble <citetitle>{PAYET, JEAN,
              23/10/1970}</citetitle> est une occurrence de l’objet
              <emphasis>STAGIAIRE</emphasis> car « <emphasis>PAYET</emphasis>
              » est une occurrence de la propriété <emphasis>NOM</emphasis>, «
              <emphasis>JEAN</emphasis> » une occurrence de
              <emphasis>PRENOM</emphasis> et « 2<emphasis>3/10/1970</emphasis>
              » une occurrence de
              <emphasis>DATE_DE_NAISSANCE</emphasis>.</para>
            </example></para>
        </sect3>

        <sect3>
          <title>Occurence d'une association</title>

          <para>Une occurrence de relation est constituée d’une et d’une seule
          occurrence de chacune des entités associées. L’occurrence de chacune
          des propriétés de l’association est en relation avec les occurrences
          des entités associées.</para>

          <example>
            <title></title>

            <para><figure>
                <title>Occurence d'une association</title>

                <mediaobject>
                  <imageobject>
                    <imagedata fileref="bdd_occur_assoc.jpg" />
                  </imageobject>
                </mediaobject>
              </figure>Soient les occurrences suivantes :</para>

            <para>• {<emphasis>PAYET, JEAN, 23/10/1970</emphasis>} : une
            occurrence de l’entité « <emphasis>STAGIAIRE</emphasis> ».</para>

            <para>• {<emphasis>BDD</emphasis>} et
            {<emphasis>JAVASCRIPT</emphasis>} : deux occurrences de l’entité «
            <emphasis>MODULE </emphasis>».</para>

            <para>12 peut être une occurrence de « <emphasis>NOTE</emphasis> »
            associée aux occurrences {<emphasis>PAYET, JEAN,
            23/10/1970</emphasis>} et {<emphasis>BDD</emphasis>} ; 13 une
            autre occurrence de « <emphasis>NOTE</emphasis> » associée aux
            occurrences {<emphasis>PAYET, JEAN, 23/10/1970</emphasis>} et
            {<emphasis>JAVASCRIPT</emphasis>}.</para>
          </example>
        </sect3>
      </sect2>

      <sect2>
        <title>Cardinalités</title>

        <para><emphasis role="bold">Définition</emphasis> : La cardinalité
        d’une entité par rapport à une association s’exprime par deux nombres
        appelés cardinalité minimum et cardinalité maximum.</para>

        <para>La cardinalité minimale peut être égale à 0 ou à 1.</para>

        <para>Si la cardinalité est égale à 0, c’est qu’il existe au moins une
        occurrence de l’entité qui ne participe pas aux occurrences de
        l’association.</para>

        <para>Si la cardinalité est égale à 1, chaque occurrence de l’entité
        participe aux occurrences de l’association.</para>

        <para>La cardinalité maximale exprime le nombre maximum de fois où une
        occurrence de l’entité participe aux occurrences de l’association. On
        la note égale à <emphasis role="bold">n</emphasis>, elle peut être
        égale à 1 ou à tout autre nombre strictement positif (quand le nombre
        d’occurrences est quantifiable).<figure>
            <title>Cardinalité</title>

            <mediaobject>
              <imageobject>
                <imagedata fileref="bdd_card.jpg" />
              </imageobject>
            </mediaobject>
          </figure></para>

        <example>
          <title>Cardinalités</title>

          <para><figure>
              <title>Cardinalité</title>

              <mediaobject>
                <imageobject>
                  <imagedata fileref="bdd_card_ex.jpg" />
                </imageobject>
              </mediaobject>
            </figure></para>

          <itemizedlist>
            <listitem>
              <para>Un stagiaire peut ne pas avoir de note, c’est à dire qu’il
              peut exister un stagiaire qui n’a pas passé l'évaluation
              (cardinalité minimum = 0).</para>
            </listitem>

            <listitem>
              <para>Un stagiaire peut être inscrit à plusieurs module et avoir
              une note pour chacun des modules auxquels il est inscrit
              (cardinalité maximum = n)</para>
            </listitem>

            <listitem>
              <para>Il est possible que personne ne se présente à l'évaluation
              pour un module (cardinalité minimum = 0)</para>
            </listitem>

            <listitem>
              <para>Plusieurs notes peuvent être attachées à un même module
              (cardinalité maximum = n)</para>
            </listitem>
          </itemizedlist>
        </example>
      </sect2>

      <sect2>
        <title>Dépendances fonctionnelles</title>

        <para><emphasis role="bold">Définition</emphasis> : Deux rubriques (ou
        propriétés) sont en dépendance fonctionnelle si la connaissance d’une
        d’entre elles permet la connaissance de l’autre.</para>

        <para><emphasis role="bold">Notation</emphasis> : A → B signifie que B
        dépend fonctionnellement de A. En d’autres termes, la connaissance
        d’une occurrence de la propriété A permet la connaissance d’une
        occurrence de la propriété B.</para>

        <example>
          <title>Dépendances fonctionnelles</title>

          <para>Numéro INSEE → sexe ; Numéro INSEE → année de naissance ; Code
          d’un stagiaire → Nom de ce stagiaire</para>

          <para><emphasis role="bold">Propriétes des dépendances
          fonctionnelles : </emphasis></para>

          <itemizedlist>
            <listitem>
              <para><emphasis>Réflexivité</emphasis> : a → a</para>
            </listitem>

            <listitem>
              <para><emphasis>Projection</emphasis> : a → b + c ⇒ a → b et a →
              c</para>
            </listitem>

            <listitem>
              <para><emphasis>Augmentation</emphasis> : a → b ⇒ ∀c, a + c →
              b</para>
            </listitem>

            <listitem>
              <para><emphasis>Additivité</emphasis> : a → b et a → c ⇒ a → b +
              c</para>
            </listitem>

            <listitem>
              <para><emphasis>Transitivité</emphasis> : a → b et b → c ⇒ a →
              c</para>
            </listitem>

            <listitem>
              <para><emphasis>Pseudo-transitivité</emphasis> : a → b et b + c
              → d ⇒ a + c → d</para>
            </listitem>
          </itemizedlist>
        </example>
      </sect2>

      <sect2>
        <title>Normalisation</title>

        <para>Le modèle conceptuel des données sera toujours présenté
        en<emphasis role="bold"> troisième forme normale</emphasis>.</para>

        <sect3>
          <title>Première Forme Normale (1 FN) :</title>

          <para>Une entité est en première forme normale si et seulement si
          :</para>

          <itemizedlist>
            <listitem>
              <para>Toutes ses propriétés sont élémentaires</para>
            </listitem>

            <listitem>
              <para>Elle possède un identifiant (une clef)</para>
            </listitem>
          </itemizedlist>
        </sect3>

        <sect3>
          <title>Deuxième Forme Normale (2 FN) :</title>

          <para>Une entité est en deuxième forme normale si et seulement si
          :</para>

          <itemizedlist>
            <listitem>
              <para>Elle est en première forme normale</para>
            </listitem>

            <listitem>
              <para>Toutes ses propriétés sont en dépendance fonctionnelle
              élémentaire de l’identifiant</para>
            </listitem>
          </itemizedlist>

          <para>Soient les propriétés P1, P2 et P3. Une dépendance
          fonctionnelle (P1 → P2) est dite élémentaire si et seulement si il
          n’existe pas de propriété (P3) incluse dans P1 en dépendance
          fonctionnelle avec P2 (P3 → P2).</para>
        </sect3>

        <sect3>
          <title>Troisième Forme Normale (3 FN) :</title>

          <para>Une entité est en troisième forme normale si et seulement si
          :</para>

          <itemizedlist>
            <listitem>
              <para>Elle est en deuxième forme normale</para>
            </listitem>

            <listitem>
              <para>Toutes ses propriétés sont en dépendance fonctionnelle
              élémentaire directe de l’identifiant</para>
            </listitem>
          </itemizedlist>

          <para>Soient les propriétés P1, P2 et P3. Une dépendance
          fonctionnelle (P1 → P2) est dite directe si et seulement si il
          n’existe pas de propriété (P3) telle que P1 → P3 et P3 → P2.</para>
        </sect3>
      </sect2>

      <sect2>
        <title>Exercices</title>

        <sect3>
          <title>Base archéologique</title>

          <para>Vous gérez une base de données archéologique dans laquelle
          vous voulez mettre les informations suivantes. Un objet est trouvé
          par une équipe donnée, dans un site donné. L’équipe est reconnue par
          le nom de son directeur, et le site par son numéro, sa longueur, sa
          largeur. Le site appartient à une zone de fouille qui peut en
          contenir plusieurs. La zone de fouille porte le nom de la ville la
          plus proche. L’objet est identifié par un numéro, une désignation
          (qui le décrit), une catégorie (par exemple, meuble, accessoire,
          élément d’architecture, manuscrit...), par un état de complétude
          (s’il est total ou s’il est partiel comme un pied de table, un
          tesson de bouteille ou un nez de gargouille, etc...) et par un état
          de conservation ( intact, bon, à restaurer, mauvais état, très
          mauvais). Plusieurs équipes peuvent fouiller simultanément la même
          zone de fouille, mais pas le même site. En revanche les équipes
          tournent, d’un site à l’autre, chaque jour. <emphasis>QUESTION
          </emphasis>: proposez un modèle entité-association (ou modèle
          conceptuel des données MCD) représentant cet énoncé, en justifiant
          les cardinalités des couples entité-association, ainsi que les clés
          des entités.</para>
        </sect3>

        <sect3>
          <title>Jeu de cartes</title>

          <para>On souhaite modéliser les données pour écrire un programme qui
          simule un jeu de cartes entre plusieurs joueurs. Voici, en résumé,
          ce dont vous disposez comme information : 1) un joueur est connu par
          un nom qui l’identifie. 2) Le jeu peut être fait en équipe, par
          conséquent, une équipe peut être formée, ou pas, selon le désir des
          joueurs. Il est évident que l’équipe n’a de sens que si une partie
          doit être jouée. L’équipe possèdera un numéro qui permet de la
          reconnaître. Les équipes peuvent être composées d’un nombre
          quelconque de joueurs supérieur ou égal à 2. Si des équipes jouent,
          alors il ne peut pas y avoir simultanément des joueurs isolés et des
          équipes effectuant la même partie. 3) le jeu se déroule durant une
          session (une partie), qui est faite à une date donnée, entre des
          équipes composées pour ce jeu, ou des joueurs (si ceux-ci n’ont pas
          constitué d’équipe). Ce qui est utile pour caractériser le jeu,
          c’est de connaître : - la nature de la partie jouée : par exemple,
          belote, tarot, poker, rami... - pour chaque tour, quel est le score
          des différents joueurs ou des équipes 4) Une partie comprend un
          nombre quelconque de tours. Elle est terminée dès que le score d’une
          des équipes dépasse une valeur qui est dépendante de la nature de la
          partie jouée, ou si les différents joueurs décident d’y mettre fin.
          <emphasis>Question</emphasis> : Faire le modèle entité-association
          des données (statiques) de ce programme. Proposer des clés pour les
          entités. Mettez les cardinalités des couples entité-association, en
          fonction des hypothèses que vous devrez formuler pour compléter cet
          énoncé.</para>
        </sect3>
      </sect2>
    </sect1>

    <sect1>
      <title>Modèle relationnel</title>

      <para>Au chapitre précédent, nous avons vu le <emphasis>Modèle
      Conceptuel des Données</emphasis>. Nous allons maintenant examiner le
      niveau logique des données, et un de ses formalismes particulièrement
      adapté aux bases de données relationnelles, le <emphasis>modèle
      relationnel.</emphasis> Nous examinerons également les règles de passage
      du MCD vers le modèle relationnel. De ce type de formalisme, nous
      verrons qu’il est aisé de passer à la représentation physique des
      données, et à la mise en œuvre du SI sur un système de gestion de base
      de données relationnelles (SGBDR).</para>

      <sect2>
        <title>Concepts du relationnel</title>

        <sect3>
          <title>Relations</title>

          <para>Comme pour le modèle entité – association, on définit des
          domaines dans lesquels des attributs prennent leur valeur. Une
          relation est un ensemble d’entités et sa description peut prendre la
          forme d’un tableau dans lequel chaque ligne représente une
          occurrence d’entité et chaque colonne un attribut.</para>

          <para><example>
              <title>Relation</title>

              <para>La relation <emphasis>COUREUR(nom, prénom,
              dateNaissance)</emphasis> peut se représenter par <table>
                  <title>Coureur</title>

                  <tgroup cols="3">
                    <tbody>
                      <row>
                        <entry><emphasis role="bold">Nom</emphasis></entry>

                        <entry><emphasis role="bold">Prénom</emphasis></entry>

                        <entry><emphasis
                        role="bold">DateNaissance</emphasis></entry>
                      </row>

                      <row>
                        <entry>Payet</entry>

                        <entry>Jacques</entry>

                        <entry>01/02/1970</entry>
                      </row>

                      <row>
                        <entry>Hoarau</entry>

                        <entry>Philippe</entry>

                        <entry>10/03/1972</entry>
                      </row>
                    </tbody>
                  </tgroup>
                </table></para>
            </example><example>
              <title>Relation</title>

              <para>La relation ETAPES (NuméroEtape, VilleDépart,
              VilleArrivée, NbKm) peut se représenter par</para>

              <para><table>
                  <title>Etapes</title>

                  <tgroup cols="4">
                    <tbody>
                      <row>
                        <entry><emphasis
                        role="bold">NuméroEtape</emphasis></entry>

                        <entry><emphasis
                        role="bold">VilleDepart</emphasis></entry>

                        <entry><emphasis
                        role="bold">VilleArrivee</emphasis></entry>

                        <entry><emphasis role="bold">NbKm</emphasis></entry>
                      </row>

                      <row>
                        <entry>1</entry>

                        <entry>St-Denis</entry>

                        <entry>St-Paul</entry>

                        <entry>50</entry>
                      </row>

                      <row>
                        <entry>2</entry>

                        <entry>St-Paul</entry>

                        <entry>St-Leu</entry>

                        <entry>30</entry>
                      </row>
                    </tbody>
                  </tgroup>
                </table></para>
            </example></para>
        </sect3>

        <sect3>
          <title>N-Uplets</title>

          <para>Un n-uplet est une occurrence d’une relation. Plus
          concrètement, il représente une ligne du tableau. On dit aussi
          <emphasis>t-uple</emphasis> au lieu de <emphasis>n-uplet</emphasis>.
          <emphasis role="bold">Exemple</emphasis> : (1,St Denis, StPaul, 50)
          est un <emphasis>n-uplet</emphasis> de la relation
          <emphasis>ETAPES</emphasis></para>
        </sect3>

        <sect3>
          <title>Cardinalité</title>

          <para>La cardinalité d’une relation est son nombre d’occurrence.
          Dans l’exemple précédent, la cardinalité de la relation
          <emphasis>COUREUR</emphasis> est de 2.</para>
        </sect3>

        <sect3>
          <title>Degré d'une relation</title>

          <para>Le degré d’une relation est son nombre d’attribut. . Dans
          l’exemple précédent, le degré de la relation
          <command>COUREUR</command> est de 3.</para>
        </sect3>

        <sect3>
          <title>Clef primaire</title>

          <para>Une clef primaire est constituée d’un ou plusieurs attributs
          de la relation. Elle permet d’identifier sans équivoque chaque
          n-uplet de la relation.</para>

          <para><emphasis>Dans la relation Coureur, NOM peut ne pas être
          suffisant pour distinguer les occurrences, en cas d’homonymie. On
          peut rajouter un attribut à la relation, un numéro de coureur, qui
          devient clef primaire </emphasis></para>
        </sect3>

        <sect3>
          <title>Clef étrangère</title>

          <para>Selon les dépendances fonctionnelles observées, il peut être
          nécessaire de connaître la clef primaire d’une relation pour
          identifier un n-uplet d’une autre relation. Dans ce cas, la clef
          primaire de la première devient clef étrangère de la seconde.
          <emphasis role="bold"></emphasis></para>

          <para><emphasis><emphasis role="bold">Exemple</emphasis></emphasis>
          : soit la nouvelle relation qui permet de modéliser les temps des
          coureurs : <emphasis>TEMPS(NumCoureur, NumeroEtape,
          tempsrealisé)</emphasis>. Les clefs <emphasis>NumCoureur</emphasis>
          et <emphasis>NuméroEtape,</emphasis> clefs primaires des relations
          <emphasis>COUREUR</emphasis> et <emphasis>ETAPES,</emphasis>
          permettent d’identifier chaque n-uplet de la relation. En effet, un
          coureur ne participe qu’une seule fois à une étape ! Ce sont donc
          les clefs étrangères de <emphasis>COUREUR.</emphasis></para>
        </sect3>

        <sect3>
          <title>Formalisme</title>

          <para>On représente chaque relation de la modélisation par :
          <command>NOMRELATION (clefPrimaire1, clePrimaire2, …., attribut1,
          Attribut2, ….. ,#clefEtrangère1,#clefEtrangère1 ….)</command></para>

          <para><emphasis role="bold">Exemple</emphasis> : <emphasis>TEMPS
          (#NumCoureur,#NumeroEtape, tempsrealisé)</emphasis></para>

          <para><emphasis>COUREUR (NumCoureur, (nom, prénom,
          dateNaissance)</emphasis></para>

          <para><emphasis>ETAPES (NuméroEtape, VilleDépart, VilleArrivée,
          NbKm)</emphasis></para>
        </sect3>
      </sect2>

      <sect2>
        <title>Normalisation</title>

        <para>Le modèle relationnel est une modélisation des données. Nous
        pouvons le normaliser, de la même manière que nous avions normalisé le
        MCD. Ainsi, nous allons reprendre les règles de formes normales
        :</para>

        <sect3>
          <title>Première Forme Normale (1FN)</title>

          <para>Pour être en 1FN, une relation doit avoir une clef et chaque
          attribut doit être une donnée élémentaire.</para>

          <para><emphasis role="bold">Exemple</emphasis> :</para>

          <para><emphasis>EMPLOYE (NomEmployé, PrénomEmployé, AdresseEmployé,
          DateEmbauche).</emphasis></para>

          <para>Cette table pose des problèmes d’homonymie, deux employés
          peuvent avoir le même nom, donc le même identifiant !! Pour passer
          le modèle en 1FN, il faut rajouter un matricule :</para>

          <para><emphasis>EMPLOYE (MatriculeEmploye, NomEmployé,
          PrénomEmployé, AdresseEmployé, DateEmbauche)</emphasis></para>
        </sect3>

        <sect3>
          <title>Deuxième Forme Normale (2FN)</title>

          <para>Pour être en 2FN, une relation doit être en 1FN et tout
          attribut non-clef ne doit pas dépendre d’une partie de la clef.
          Seules les relations dont la clef est composée de plusieurs
          attributs sont concernés.</para>

          <para><emphasis role="bold">Exemple</emphasis> :</para>

          <para><emphasis>COMMANDE (#N°Client, #N°Produit, Qte, Nomclient)
          CLIENT (N°Client, Adr, VilleClient)</emphasis></para>

          <para>Dans la relation commande, NomClient dépend seulement de la
          partie de la clef <emphasis>N°Client</emphasis>. Pour normaliser le
          modèle en 2FN, il faut donc mettre <emphasis>NomClient</emphasis>
          dans la relation <emphasis>CLIENT</emphasis> :</para>

          <para><emphasis>COMMANDE (#N°Client, #N°Produit, Qte) CLIENT
          (N°Client, Adr, VilleClient, Nomclient)</emphasis></para>
        </sect3>

        <sect3>
          <title>Troisième Forme Normale (3FN)</title>

          <para>Pour être en 3FN, une relation doit être en 2FN et tout
          attribut non clef ne doit pas dépendre d’un autre attribut non clef.
          (pas de transitivité)</para>

          <para><emphasis role="bold">Exemple</emphasis> :</para>

          <para><emphasis>FACTURE(N°Facture, dateFact, N°Fournisseur,
          RSFournisseur, AdrFournisseur, VillFournisseur)</emphasis></para>

          <para>Les attributs AdrFournisseur et VilleFournisseur dépendent de
          la propriété <emphasis>N°Facture</emphasis>, mais aussi de
          <emphasis>RSFournisseur</emphasis>, qui elle-même dépend de la clef.
          On a donc 2 dépendances fonctionnelles transitives, qu’on peut
          supprimer en créant une nouvelle relation.</para>

          <para><emphasis>FACTURE (N°Facture, dateFact, N°Fournisseur,
          #RSFournisseur) FOURNISSEUR (RSFournisseur, AdrFournisseur,
          VillFournisseur)</emphasis></para>
        </sect3>

        <sect3>
          <title>Forme Normale de Boyce – Codd (BCFN)</title>

          <para>La normalisation de Boyce - Codd a pour but de supprimer les
          dépendances fonctionnelles autre que celles de la clé vers les
          attributs non-clefs.</para>

          <para><emphasis role="bold">Exemple</emphasis> :</para>

          <para>Dans une entreprise de production qui travaille à la commande
          de on veut pouvoir comptabiliser le temps consacré par chaque
          employé à chaque commande. Un employé n’est pas affecté d’une
          manière fixe à un atelier et un atelier est entièrement consacré à
          une commande. Soit la relation suivante :</para>

          <para><emphasis>ATTRIBUTION (#N°employé, #N°Commande, NbHeures,
          N°Atelier) </emphasis></para>

          <para>La DF fonctionnelle à supprimer dans cette relation est
          <emphasis>N°Atelier -&gt; N°Commande</emphasis>. L’application de la
          BCFN se traduit par les relations suivantes :</para>

          <para><emphasis>ATTRIBUTION (#N°employé, #N°Commande, NbHeures)
          ATELIER (N°Atelier, N°Commande)</emphasis></para>
        </sect3>
      </sect2>

      <sect2>
        <title>Passage du MCD au MPD</title>

        <para>Le passage du MCD vers le modèle relationnel se base sur
        l’application de trois règles simples, énoncées ci-dessous. Il est à
        noter que cette transformation peut se faire en sens inverse, en
        appliquant les mêmes règles.</para>

        <sect3>
          <title>Règle 1</title>

          <para><emphasis role="bold">Toute entité du MCD est traduite en une
          table dont la clef primaire et les attributs proviennent de
          l’entité</emphasis><figure>
              <title>Règle 1</title>

              <mediaobject>
                <imageobject>
                  <imagedata fileref="regle1.jpg" />
                </imageobject>
              </mediaobject>
            </figure></para>
        </sect3>

        <sect3>
          <title>Règle 2</title>

          <para><emphasis role="bold">Une association qui a une cardinalité
          égale à 0,1 ou 1,1 pour une entité est traduite par une clef
          étrangère ajoutée à la table qui traduit cette entité. Cette clef
          étrangère est la clef primaire de l’entité
          associée.</emphasis><figure>
              <title>Règle 2</title>

              <mediaobject>
                <imageobject>
                  <imagedata fileref="regle2.jpg" />
                </imageobject>
              </mediaobject>
            </figure></para>
        </sect3>

        <sect3>
          <title>Règle 3</title>

          <para><emphasis role="bold">Une association qui n’a pas de
          cardinalité égale à 0,1 ou 1,1 est traduite en une table dont la
          clef primaire est constituée de l’ensemble des identifiants des
          entités qui y participent.</emphasis></para>

          <figure>
            <title>Règle 3</title>

            <mediaobject>
              <imageobject>
                <imagedata fileref="regle3.jpg" />
              </imageobject>
            </mediaobject>
          </figure>
        </sect3>
      </sect2>
    </sect1>

    <sect1>
      <title>Génération d'une base de données avec SQL</title>

      <para>Nous disposons maintenant d'un modèle logique des données conforme
      à Merise. Le modèle relationnel est directement transposable à un
      <emphasis>Système de Gestion de Base de Données Relationnel,
      </emphasis>tel que MySQL. En effet, chaque table du modèle relationnel
      donnera une table dans la base de données. Il nous reste maintenant à
      préciser les types de chaque données de notre modèle et de créer les
      tables.</para>

      <para>Le langage de manipulation des données pour créer, utiliser et
      maintenir une base de données est le <emphasis
      role="bold">SQL</emphasis> pour <emphasis>Structured Query
      Langage</emphasis>. Nous allons maintenant examiner les instructions de
      ce langage pour créer la base de données et les tables qui lui sont
      associées. Volontairement, nous utiliserons en priorité les instructions
      utilisables sur MySQL.</para>

      <sect2>
        <title>Présentation de MySQL</title>

        <para>Le logiciel MySQL est un serveur de base de données SQL très
        rapide, multi−threadé, multi−utilisateur et robuste. Le serveur MySQL
        est destiné aux missions stratégiques et aux systèmes de production à
        forte charge, ainsi qu'à l'intégration dans des logiciels déployés à
        grande échelle. MySQL est une marque déposée de MySQL AB .</para>

        <para>MySQL version 3.22 a une limite de 4Go par table. Avec le
        nouveau format de table MyISAM , disponible avec MySQL version 3.23,
        la taille maximale des tables a été poussée à 8 millions de teraoctets
        (2 ^ 63 octets).</para>

        <para>Extrait du manuel de référence de MySQL :</para>

        <para><emphasis>MySQL est un serveur de bases de données
        relationnel.</emphasis> <emphasis>Un serveur de bases de données
        stocke les données dans des tables séparées plutôt que de tout
        rassembler dans une seule table. Cela améliore la rapidité et la
        souplesse de l'ensemble. Les tables sont reliées par des relations
        définies, qui rendent possible la combinaison de données entre
        plusieurs tables durant une requête. Le SQL dans `` MySQL '' signifie
        `` Structured Query Language '' : le langage standard pour les
        traitements de bases de données</emphasis>.</para>

        <para><emphasis>MySQL est Open Source .</emphasis> <emphasis>Open
        Source (Standard Ouvert) signifie qu'il est possible à chacun
        d'utiliser et de modifier le logiciel. Tout le monde peut télécharger
        MySQL sur Internet, et l'utiliser sans payer aucun droit. Toute
        personne en ayant la volonté peut étudier et modifier le code source
        pour l'adapter à ses besoins propres. Le logiciel MySQL utilise la
        licence GPL ( GNU General Public License ), pour définir ce que vous
        pouvez et ne pouvez pas faire avec ce logiciel, dans différentes
        situations. Si vous ne vous sentez pas confortable avec la licence GPL
        ou bien que vous devez intégrer MySQL dans une application
        commerciale, vous pouvez acheter une licence commercial auprès de
        MySQL AB. Licences MySQL . </emphasis></para>

        <para><emphasis>Pourquoi utiliser le serveur de bases de données MySQL
        ?</emphasis> <emphasis>Le serveur de bases de données MySQL est très
        rapide, fiable et facile à utiliser. Si c'est ce que vous recherchez,
        vous devriez faire un essai. Le serveur de bases de données MySQL
        dispose aussi de fonctionnalités pratiques, développées en coopération
        avec nos utilisateurs. Vous pouvez trouver une comparaison des
        performances du serveur MySQL avec d'autres systèmes de bases de
        données dans nos pages de tests de performances. La suite de tests
        comparatifs de MySQL .Le serveur MySQL a été développé à l'origine
        pour gérer de grandes bases de données plus rapidement que les
        solutions existantes, et a été utilisé avec succès dans des
        environnements de production très contraints et très exigeants, depuis
        plusieurs années. Bien que toujours en développement, le Le serveur
        MySQL offre des fonctions nombreuses et puissantes. Ses possibilités
        de connexions, sa rapidité et sa sécurité font du serveur MySQL une
        serveur hautement adapté à Internet. </emphasis></para>

        <para><emphasis>Les caractéristiques techniques du serveur MySQL
        .</emphasis> <emphasis>Le logiciel de bases de données MySQL est un
        système client/serveur, constitué d'un serveur SQL multi−threadé qui
        supporte différents systèmes de stockage, plusieurs logiciels clients
        et librairies, outils d'administration, ainsi que de nombreuses
        interfaces de programmation (des API ).Nous fournissons aussi le
        serveur MySQL sous la forme d'une librairie multi−threadé que vous
        pouvez inclure dans vos applications, pour obtenir un produit plus
        compact, plus rapide et plus facile à gérer. </emphasis></para>
      </sect2>

      <sect2>
        <title>Création d'une base de données</title>

        <sect3>
          <title>Accès à MysQL</title>

          <para>Il existe plusieurs méthodes pour accéder au SGBD MySQL. En
          voici quelques unes :</para>

          <itemizedlist>
            <listitem>
              <para><emphasis role="bold">Directement sur un serveur
              </emphasis>: il suffit pour cela de lancer la commande
              <command>MySQL.</command> L'accès à la base se fait alors
              <emphasis>via</emphasis> des lignes de commandes, en particulier
              avec des instructions SQL directement exécutées sur le
              serveur.</para>
            </listitem>

            <listitem>
              <para><emphasis role="bold">Depuis un ordinateur distant
              </emphasis>: nous pouvons utiliser le module
              <guilabel>PhPMyAdmin</guilabel>, qui fournit une interface Web
              pour accèder au système de gestion de base de données. Cet outil
              propose entre autre de créer - <emphasis>via</emphasis> des
              formulaires - des bases de données, des tables, des
              enregistrements, des requêtes, etc..</para>
            </listitem>
          </itemizedlist>
        </sect3>

        <sect3>
          <title>Création et suppression d'une base de données</title>

          <sect4>
            <title>Instruction CREATE DATABASE</title>

            <para><command>CREATE DATABASE [IF NOT EXISTS]
            db_name</command></para>

            <para>Cette instruction crée une base de données avec le nom
            donné. Une erreur survient si la base de données existe déjà et
            que vous n'avez pas spécifié <command>IF NOT EXISTS</command> .Les
            bases de données MySQL sont implémentées comme des répertoires
            contenant des fichiers qui correspondent aux tables dans les bases
            de données. Puisqu'il n'y a pas de tables dans une base de données
            lors de sa création, la requête <command>CREATE DATABASE</command>
            créera seulement le dossier dans le répertoire de données de
            MySQL.</para>
          </sect4>

          <sect4>
            <title>nstruction DROP DATABASE</title>

            <para><command>DROP DATABASE [IF EXISTS] db_name</command></para>

            <para>Cette instruction détruit toutes les tables dans la base de
            données et l'efface elle même. Si vous utilisez la commande
            <command>DROP DATABASE</command> sur un lien symbolique pointant
            sur la base de données, le lien et la base seront effacés.
            <command>DROP DATABASE</command> retourne le nombre de fichiers
            qui ont été effacés du dossier de la base de données. Normalement,
            c'est égal à trois fois le nombre de tables.</para>
          </sect4>
        </sect3>
      </sect2>

      <sect2>
        <title>Création des tables</title>

        <sect3>
          <title>Instruction CREATE TABLE</title>

          <para><command>CREATE TABLE nom_table ( </command></para>

          <para><command>nom_champ1 type [NOT NULL | NULL] [DEFAULT
          valeur_par_defaut] [AUTO_INCREMENT] [PRIMARY KEY] [FOREIGN
          KEY],</command></para>

          <para><command>nom_champ2 type [NOT NULL | NULL] [DEFAULT
          valeur_par_defaut] [AUTO_INCREMENT] [PRIMARY KEY] [FOREIGN
          KEY],</command></para>

          <para><command>nom_champ2 type [NOT NULL | NULL] [DEFAULT
          valeur_par_defaut] [AUTO_INCREMENT] [PRIMARY KEY] [FOREIGN
          KEY],</command></para>

          <para><command>...)</command></para>

          <para>Cette instruction SQL permet de créer une table contenant une
          série de champs de données. Pour chaque champ, nous allons pouvoir
          préciser son type, indiquer à MySQL si sa valeur peut être nulle,
          éventuellement si il s'agit d'un champ auto-incrémenté, et spécifier
          les clefs primaires et étrangères de la table.</para>

          <para>L'exécution de l'instruction CREATE TABLE par MySQL crée trois
          fichiers dans le répertoire de la base de données :</para>

          <itemizedlist>
            <listitem>
              <para><command>nom_de_table.FRM</command> : Fichier de
              définition de la table</para>
            </listitem>

            <listitem>
              <para><command>nom_de_table.MYD</command> : Fichier de
              données</para>
            </listitem>

            <listitem>
              <para><command>nom_de_table.MYI </command> : Fichier
              d'index</para>
            </listitem>
          </itemizedlist>
        </sect3>

        <sect3>
          <title>Types de données dans MySQL</title>

          <para><emphasis role="bold">MySQL</emphasis> supporte un grand
          nombre de types de colonnes, qui peuvent être rassemblés en trois
          groupes : les nombres, les dates et les chaînes de caractères. Les
          types de données de MySQL sont listés ci-dessous. Les codes suivants
          sont utilisés dans les descriptions :</para>

          <itemizedlist>
            <listitem>
              <para><emphasis role="bold">M </emphasis>: Indique la taille
              maximale d'affichage. Le maximum légal est 255.</para>
            </listitem>

            <listitem>
              <para><emphasis role="bold">D</emphasis> : S'applique aux
              nombres à virgule flottante, et indique le nombre de décimales
              qui suivent la virgule. Le nombre maximum est de 30, mais ne
              doit pas être plus grand que M -2.</para>
            </listitem>

            <listitem>
              <para><emphasis role="bold">UNSIGNED</emphasis> : Indique si la
              propriété optionnelle indiquant si un type de données est
              toujours positif est autorisée. Si <emphasis>UNSIGNED</emphasis>
              est présent, le nombre est toujours positif.</para>
            </listitem>

            <listitem>
              <para><emphasis role="bold">ZEROFILL</emphasis> : la présence de
              cette propriété optionnelle indique que des zéros doivent être
              placés comme caractère de remplissage. Par exemple, pour un type
              <command>INT(5) ZEROFILL</command>, la valeur <command>4
              </command>sera lue <command>0004</command>.</para>
            </listitem>
          </itemizedlist>

          <sect4>
            <title>Types numériques</title>

            <para>Le tableau ci-dessous cite les différents types de données
            numériques sous MySQL. M indique la taille d'affichage, et D
            (valable pour les nombres en virgule flottante), représente le
            nombre de chiffres après la virgule.</para>

            <table>
              <title>Types numériques sous MySQL</title>

              <tgroup cols="3">
                <tbody>
                  <row>
                    <entry><emphasis role="bold">Type</emphasis></entry>

                    <entry><emphasis role="bold">De</emphasis></entry>

                    <entry><emphasis role="bold">1</emphasis></entry>
                  </row>

                  <row>
                    <entry><emphasis>TINYINT(M)</emphasis></entry>

                    <entry>-128</entry>

                    <entry>127</entry>
                  </row>

                  <row>
                    <entry><emphasis>SMALLINT(M)</emphasis></entry>

                    <entry>-32768</entry>

                    <entry>32767</entry>
                  </row>

                  <row>
                    <entry><emphasis>MEDIUMINT(M)</emphasis></entry>

                    <entry>-8388608</entry>

                    <entry>8388607</entry>
                  </row>

                  <row>
                    <entry><emphasis>INT(M)</emphasis></entry>

                    <entry>-2147483648</entry>

                    <entry>2147483647</entry>
                  </row>

                  <row>
                    <entry><emphasis>BIGINT(M)</emphasis></entry>

                    <entry>-9223372036854775808</entry>

                    <entry>9223372036854775807</entry>
                  </row>

                  <row>
                    <entry><emphasis>FLOAT[(M,D)]</emphasis></entry>

                    <entry>-3.402823466E+38</entry>

                    <entry>3.402823466E+38</entry>
                  </row>

                  <row>
                    <entry><emphasis>DOUBLE[(M,D)]</emphasis></entry>

                    <entry>-1.7976931348623157E+308</entry>

                    <entry>1.7976931348623157E+308</entry>
                  </row>
                </tbody>
              </tgroup>
            </table>
          </sect4>

          <sect4>
            <title>Types Date et heure</title>

            <itemizedlist>
              <listitem>
                <para>Type <command>TIME</command> : MySQL lit et affiche les
                colonnes de type <emphasis>TIME</emphasis> au format
                'HH:MM:SS'. Les valeurs TIME non valides sont transformées en
                date zéro '00:00:00'</para>
              </listitem>

              <listitem>
                <para>Type <command>DATE</command> : Le type
                <emphasis>DATE</emphasis> est prévu lorsque vous souhaitez
                stocker une date. MySQL affiche les valeurs de type
                <emphasis>DATE</emphasis> au format '
                <emphasis>AAAA-MM-JJ</emphasis> '. L'intervalle de validité va
                de '1000-01-01' à '9999-12-31'. Les dates non valides sont
                transformées en "0000-00-00"</para>
              </listitem>

              <listitem>
                <para>Type <command>DATETIME</command> : Le type
                <emphasis>DATETIME</emphasis> est prévu lorsque vous souhaitez
                stocker une date et une heure. MySQL affiche les valeurs de
                type <emphasis>DATETIME</emphasis> au format '
                <emphasis>AAAA−MM−JJ HH:MM:SS</emphasis>'</para>
              </listitem>

              <listitem>
                <para>Type <command>TIMESTAMP</command> : Le type
                <emphasis>TIMESTAMP</emphasis> est prévu pour stocker
                automatiquement l'heure courante lors d'une commande
                <emphasis>INSERT</emphasis> ou <emphasis>UPDATE</emphasis> .
                Si vous avez plusieurs colonnes de type
                <emphasis>TIMESTAMP</emphasis> , seule la première colonne
                sera mise à jour automatiquement.</para>
              </listitem>
            </itemizedlist>
          </sect4>
        </sect3>

        <sect3>
          <title>Chaînes de caractères</title>

          <para>Les types chaînes sont <command>CHAR , VARCHAR ,
          TEXT</command> . Il en existe d'autres, mais nous nous intéresserons
          en priorité à ceux-ci.</para>

          <para>Ces types de données vous permettent de définir des chaînes de
          longueur comprise entre 1 et 255 caractères.</para>

          <para><command>CHAR(L) </command>: dans ce cas, quelque soit la
          longueur effective de la chaîne, elle sera toujours stockés sur un
          nombre d'octets fixe, L. Par exemple, si vous définissez
          <command>CHAR (10)</command> et que vous entrez la chaîne "Bonjour",
          elle sera complétée par trois espace dans la table.</para>

          <para><command>VARCHAR(L) </command>: dans ce cas, MySQL stocke la
          chaîne, plus un octet définissant la longueur effecctive de
          l'enregistrement. Dans notre exemple "bonjour", cette chaîne
          occupera 7+1 octets dans la base.</para>

          <para><command>TEXT </command>: ce type de données peut en fait être
          considéré comme un <command>VARCHAR</command> de longueur indéfini.
          Il n'y a pas de limitation de taille pour ce type, insensible à la
          casse. Dans l'absolu, ce sont les capacités du serveur qui
          déterminent la longueur maximale d'un TEXT.</para>
        </sect3>
      </sect2>
    </sect1>
  </chapter>

  <chapter>
    <title>Insertion, modification et suppression de N-Uplets</title>

    <para>Pour aborder les différentes notions d'insertion, de modifications
    et de suppression d'enregistrements dans les tables des bases de données,
    nous allons créer une base de données qui servira de support aux
    différents exemple. Cette base de données est représentée par le MCD
    suivant :</para>

    <figure>
      <title>MCD - LOCATION DE PLANCHES A VOILE</title>

      <mediaobject>
        <imageobject>
          <imagedata fileref="mcd_planche.jpg" />
        </imageobject>
      </mediaobject>
    </figure>

    <para>En applicant les règles de transformation propres au MCD, on obtient
    ainsi le modèle relationnel suivant :</para>

    <para><command>PLANCHE(PLA_NUM, PLA_MARQUE, PLA_MODELE, PLA_ANNEE,
    PLA_TAILLE, PLA_POIDS)</command></para>

    <para><command>CLIENT(CLI_ID, CLI_NOM, CLI_PRENOM, CLI_ADR,
    CLI_TEL)</command></para>

    <para><command>LOUE(#PLA_NUM, #CLI_ID, LOU_DEBUT,
    LOUE_FIN)</command></para>

    <para>Ce modèle logique des données nous amène au modèle physique suivant
    :</para>

    <figure>
      <title>MPD - LOCATION DE PLANCHES A VOILE</title>

      <mediaobject>
        <imageobject>
          <imagedata fileref="mpd_planche.jpg" />
        </imageobject>
      </mediaobject>
    </figure>

    <para>Enfin, le script de création des tables est le suivant :</para>

    <para><command>/*==============================================================*/
    /* Table : CLIENT */
    /*==============================================================*/ create
    table CLIENT ( CLI_ID int not null, CLI_NOM varchar(100), CLI_PRENOM
    varchar(100), CLI_ADR varchar(200), CLI_TEL varchar(12), primary key
    (CLI_ID) );
    /*==============================================================*/ /*
    Table : LOUE */
    /*==============================================================*/ create
    table LOUE ( PLA_NUM smallint not null, CLI_ID int not null, LOU_DEBUT
    time, LOU_FIN time, primary key (PLA_NUM, CLI_ID) );
    /*==============================================================*/ /*
    Table : PLANCHE */
    /*==============================================================*/ create
    table PLANCHE ( PLA_NUM smallint not null, PLA_MARQUE varchar(50),
    PLA_MODELE varchar(50), PLA_ANNEE int, PLA_TAILLE real, PLA_POIDS real,
    primary key (PLA_NUM) ); </command></para>

    <para><remark>Comme nous l'avons souligné dans le chapitre précédent,
    MySQL ne gère pas les clef étrangères, ni l'intégrité référentielle.
    Ainsi, notre modèle physique des données nous indiquait que les clefs
    primaires de CLIENT et PLANCHE devaient devenir clef étrangères de LOUE,
    mais nous n'avons pas la possibilité de la faire sous MySQl version
    3.x.</remark></para>

    <sect1>
      <title>Insertion de N-Uplets</title>

      <para>Nous souhaitons maintenant entrer des données dans les tables de
      la bases de données. Une fois de plus, nous allons être obligé de gérer
      nous même l'intégrité référentielle, et prendre partciulièrement soin de
      rentrer des données valides dans nos tables : par exemple, les
      occurences de la table LOUE devront faie référence à des clients et des
      planches qui existent ! MySQL ne nous renverra pas d'erreur si nous n'y
      prenont pas garde.</para>

      <para>La documentation de MySQL nous fournit la syntaxe de la commande
      SQL permettant d'insérer des enregistrements dans une table :</para>

      <para><command>INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO]
      nom_de_table [(nom_colonne,...)] VALUES ((expression |
      DEFAULT),...),(...),...</command></para>

      <para>Nous retiendrons de cette définition que pour insérer des données
      dans une table, nous devons avoir une instruction SQl du type :</para>

      <para><command>INSERT INTO NOM_TABLE (LISTE DES COLONNES) VALUES (LISTE
      DES VALEURS)</command></para>

      <para>Dans notre exemple, nous voulons insérer deux planches à voiles
      :</para>

      <para><command> INSERT INTO `planche` (`PLA_NUM`, `PLA_MARQUE`,
      `PLA_MODELE`, `PLA_ANNEE`, `PLA_TAILLE`, `PLA_POIDS`) VALUES ('1',
      'TIGA', 'SLALOM 260', '1997', '2,60', '9');</command></para>

      <para><command> INSERT INTO `planche` (`PLA_NUM`, `PLA_MARQUE`,
      `PLA_MODELE`, `PLA_ANNEE`, `PLA_TAILLE`, `PLA_POIDS`) VALUES ('2',
      'EXOCET', 'WAVE 259', '1999', '2,59', '7');</command></para>

      <para>Un client se présente maintenant. Nous souhaitons l'enregistrer
      :</para>

      <para><command> INSERT INTO `client` (`CLI_ID`, `CLI_NOM`, `CLI_PRENOM`,
      `CLI_ADR`, `CLI_TEL`) VALUES ('1', 'KURZWEG', 'Ivan', 'Rue des
      mouettes', '0692012345');</command></para>

      <para>Il désire louer la planche de vagues Exocet. Nous devons donc
      enregistrer une ligne dans la table LOUE, en y mettant l'heure courante
      :</para>

      <para><command> INSERT INTO `loue` (`PLA_NUM`, `CLI_ID`, `LOU_DEBUT`,
      `LOU_FIN`) VALUES ('2', '1', NOW(), NULL);</command></para>

      <para>Dans ce cas, nous avons insérer l'heure courante en utilisant la
      fonction SQL NOW(), qui nous renvoie l'heure au format TIME. Pour
      l'heure de retour, nous n'avons rien mis, en indiquant à MySQL de
      remplir ce champ avec NULL.</para>

      <para>Ici, nous devons bien prendre le soin de mettre des clefs
      étrangères existantes. En effet, l'instruction suivante ne nous renvoie
      pas d'erreur :</para>

      <para><command> INSERT INTO `loue` (`PLA_NUM`, `CLI_ID`, `LOU_DEBUT`,
      `LOU_FIN`) VALUES ('3', '1', NOW(), NULL)</command></para>

      <para>Or, nous n'avons pas entrer de planches ayant le numéro 3. Il y a
      donc incohérence avec notre modèle des données, et MySQL ne le détecte
      pas !</para>
    </sect1>

    <sect1>
      <title>Modification de N-Uplets</title>

      <para>Notre client a terminé sa session de navigation. Il nous ramène
      donc la planche à voile, et nous devons maintenant mettre à jour l'heure
      de retour du matériel. Pour ceci, nous allons utiliser l'instruction de
      modification de N-Uplet, donc la syntaxe est précisée par la
      documentation MySQL :</para>

      <para><command>UPDATE [LOW_PRIORITY] [IGNORE] nom_de_table SET
      nom_colonne1=expr1 [, nom_colonne2=expr2, ...] [WHERE where_definition]
      [ORDER BY ...] [LIMIT #]</command></para>

      <para>Nous retiendrons pour le moment que la mise à jour
      d'enregistrements se fait en utilisant une requête SQL de la
      forme</para>

      <para><command>UPDATE NOM_TABLE SET NOM_COL = VALEUR WHERE NOM_COL =
      VALEUR;</command></para>

      <para>Nous reviendrons plus tard sur la manière de rédiger des requêtes
      plus complexes, en utilisant des clauses <command>WHERE</command> plus
      conséquentes. Pour le moment, nous considérons que la mise à jour se
      fera sur un enregistrement dont nous connaissons l'identifiant.</para>

      <para>Pour mettre à jour l'occurence de la table LOUE représentant que
      le client numéro 1 a ramené la planche numéro 2 à l'instant :</para>

      <para><command>UPDATE LOUE SET LOU_FIN = NOW() WHERE PLA_NUM = 2 AND
      CLI_ID = 1;</command></para>

      <para>Pour le moment, cette instruction marche correctement, puisque le
      client 1 n'a jamais loué la planche 2 auparavant. Dans le cas contraire,
      nous aurions surement eu quelques problèmes ...</para>
    </sect1>

    <sect1>
      <title>Suppression de N-Uplets</title>

      <para>La suppression de données en SQL se fait en exécutant
      l'instruction SQL DELETE :</para>

      <para><command>DELETE [LOW_PRIORITY] [QUICK] FROM nom_de_table [WHERE
      clause_where] [ORDER BY ...] [LIMIT lignes]</command></para>

      <para>Nous retriendrons de cette définition que pour supprimer un
      enregistrement d'une table, nous utiliserons une instruction de la forme
      :</para>

      <para><command>DELETE FROM NOM_TABLE WHERE CONDITION</command></para>

      <para>Dans notre exemple, supposons que nous souhaitons supprimer la
      planche numéro 2. Nous devons prendre soin de supprimer les
      enregistrement de la table LOUE correspondant, pour conserver
      l'intégrité référentielle.</para>

      <para>Nous commençons donc par supprimer les enregistrements de la table
      LOUE contenant une référence de planche égale à 2 :</para>

      <para><command>DELETE FROM LOUE WHERE PLA_NUM = 2;</command></para>

      <para>Une fois ces enregistrements effacés, nous pouvons donc effacer
      l'enregistrement de la table PLANCHE :</para>

      <para><command>DELETE FROM PLANCHE WHERE PLA_NUM = 2;</command></para>

      <para>Nous avons bien effacé tous nos enregistrements, et conservé
      l'intégrité référentielle.</para>
    </sect1>

    <sect1>
      <title>Une première approche de la clause WHERE</title>

      <para>Nous avons vu dans les instructions SQL précédentes que nous
      pouvons employer une clause WHERE, qui nous permet de sélectionner les
      enregistrements que nous souhaitons manipuler.</para>

      <para>Nous verrons plus en détail les caractéristiques de ces clauses de
      sélection de données, mais nous pouvons déjà remarquer que le WHERE nous
      permet de "trier" les enregistrements sur des critères appliqués aux
      valeurs des colonnes.</para>

      <para>Ces différents critères vont par exemple être une égalité avec une
      valeur fixée ou calculée, ou au contraire une différence par rapport à
      une valeur entrée, etc ...</para>
    </sect1>
  </chapter>

  <chapter>
    <title>Sélection de données</title>

    <sect1>
      <title>Recherche simple de données</title>

      <sect2>
        <title>Accès aux tables de la base</title>

        <para>Nous avons vu dans les chapitres précédents que les tables
        étaient des regroupements d'enregistrements, encore appelés lignes ou
        occurences.</para>

        <para>Nous avons également étudié les requêtes SQL permettant
        d'insérer, de modifier ou de supprimer des enregistrements. Dans ce
        chapitre, nous allons maintenant étudier la manière de sélectionner
        les lignes d'une table, en utilisant la commande SQL
        <command>SELECT</command>. Même si cette commande peut paraître simple
        au premier abord, elle devient vite complexe dans certains cas. Dans
        le prochain chapitre, nous verrons en effet comment sélectionner des
        données dans plusieurs tables à la fois.</para>

        <para>Dans ce chapitre, nous utiliserons pour nos exemples la base de
        location de planches à voiles vue dans le chapitre précédent. Cette
        base de données a été légèrement modifiée pour prendre en compte la
        gestion des locations dans le temps : un identifiant a été rajouté
        dans la table LOUE. Le système peut maintenant conserver l'historique
        des locations.</para>
      </sect2>
    </sect1>

    <sect1>
      <title>Sélection simple et conditionnelle</title>

      <para>La commande <command>SELECT</command> est définie par la syntaxe
      suivante :</para>

      <para><programlisting>SELECT [DISTINCT ou ALL] * ou liste de colonnes
FROM nom de table ou de la vue
[WHERE prédicats]
[GROUP BY ordre des groupes]
[HAVING condition]
[ORDER BY ] liste de colonnes</programlisting></para>

      <itemizedlist>
        <listitem>
          <para>SELECT : permet de définir les colonnes résultats, le signe *
          retournant toutes les colonnes des enregistrements
          sélectionnés</para>
        </listitem>

        <listitem>
          <para>FROM : définit la table sur laquelle porte la requête</para>
        </listitem>

        <listitem>
          <para>WHERE : le filtre portant sur les données (conditions à
          remplir pour que les lignes soient présentes dans le résultat</para>
        </listitem>

        <listitem>
          <para>GROUP BY : définition d'un sous-ensemble</para>
        </listitem>

        <listitem>
          <para>HAVING : filtre portant sur les résultats (conditions de
          regroupement des lignes)</para>
        </listitem>

        <listitem>
          <para>ORDER BY : tri des résultats</para>
        </listitem>
      </itemizedlist>

      <para>La commande permettant d'afficher l'ensemble des lignes d'une
      table est donc : SELECT * FROM CLIENT</para>

      <para>Donc, afficher l'ensemble des lignes de notre table
      <command>PLANCHE</command> est donc :</para>

      <para><programlisting>SELECT * FROM planche </programlisting></para>

      <para><programlisting>PLA_NUM     PLA_MARQUE     PLA_MODELE     PLA_ANNEE     PLA_TAILLE     PLA_POIDS        
1  TIGA  SLALOM 260  1997  2  9   
2  EXOCET  WAVE 259  2000  2  7     
3  MISTRAL  BEAST  2003  2  5     
4  BIC  SAXO  2000  2  </programlisting></para>

      <para>Pour afficher des lignes avec certains champs, et renommer ces
      champs pour l'affichage des résultats, nous pouvons exécuter la requête
      suivante :</para>

      <para><programlisting>SELECT PLA_MARQUE AS MARQUE, PLA_MODELE AS MODELE FROM planche</programlisting></para>

      <para><programlisting>MARQUE     MODELE        
TIGA  SLALOM 260     
EXOCET  WAVE 259     
MISTRAL  BEAST     
BIC  SAXO</programlisting></para>

      <para>Nous pouvons égalemennt classer ces résultats par ordre
      alphabétique par exemple : un premier tri sur le nom de la marque, et un
      deuxième sur le modèle de la planche.</para>

      <para><programlisting>SELECT PLA_MARQUE AS MARQUE, PLA_MODELE AS MODELE FROM planche ORDER BY PLA_MARQUE ASC, PLA_MODELE ASC</programlisting></para>

      <para><programlisting>MARQUE     MODELE       
BIC  SAXO     
EXOCET  WAVE 259     
MISTRAL  BEAST     
TIGA  SLALOM 260</programlisting></para>

      <para>MySQL nous propose aussi de limiter l'affichage des résultats :
      nous pouvons par exemple afficher les deux premières lignes des
      résultats :</para>

      <para><programlisting>SELECT PLA_MARQUE AS MARQUE, PLA_MODELE AS MODELE FROM planche ORDER BY PLA_MARQUE ASC, PLA_MODELE ASC LIMITS 0,2</programlisting></para>

      <para>ou les lignes à partir de la troisième jusque la denière :</para>

      <para><programlisting>SELECT PLA_MARQUE AS MARQUE, PLA_MODELE AS MODELE FROM planche ORDER BY PLA_MARQUE ASC, PLA_MODELE ASC LIMITS 2,-1
</programlisting></para>

      <para>Nous pouvons aussi supprimer les doublons dans les résultats en
      utilisant l'opérateur <emphasis role="bold">DISTINCT </emphasis></para>

      <para><programlisting>SELECT DISTINCT CLI_PRENOM AS PRENOM FROM client </programlisting></para>

      <para><programlisting>PRENOM
Ivan
Paul
Jean
Marc</programlisting> Il est également possible d'afficher des calculs dans
      les résultats. La calcul de la masse volumique des planches donnerait
      par exemple :</para>

      <para><programlisting>SELECT PLA_MARQUE, PLA_MODELE, PLA_POIDS / PLA_VOLUME AS MASSE_VOLUMIQUE FROM planche</programlisting></para>

      <para><programlisting>PLA_MARQUE     PLA_MODELE     MASSE_VOLUMIQUE      
TIGA  SLALOM 260  0.1   
EXOCET  WAVE 259  0.088607594936709   
MISTRAL  BEAST  0.045454545454545   
BIC  SAXO  0.08</programlisting></para>
    </sect1>

    <sect1>
      <title>Prédicats de sélection</title>

      <para>L'interêt d'une base de données ne se limite heureusement pas à un
      simple listage des données. Il est généralement nécessaire de donner des
      conditions ou filtres. Seules seront sélectionnées les lignes
      satisfaisant aux conditions situées après la clause
      <command>WHERE</command>.</para>

      <para>La sélection des clients habitant à <emphasis>ST-PAUL
      </emphasis>peut donc se faire avec la requête :</para>

      <para><programlisting>SELECT * FROM client WHERE CLI_VILLE = "ST-PAUL"</programlisting></para>

      <para><programlisting>CLI_ID     CLI_NOM     CLI_PRENOM     CLI_ADR     CLI_VILLE     CLI_TEL       
1  KURZWEG  Ivan  Rue des mouettes  ST-PAUL  0692012345     
3  PAYET  Jean  6 rue des hortensias  ST-PAUL  0262010203     
5  GRONDIN  paul  23 rue des rosiers  ST-PAUL  0263708090</programlisting></para>

      <para>Nous allons voir dans les paragraphes suivants l'ensemble des
      opérateurs permettant de réaliser les prédicats de sélection,
      c'est-à-dire les fonctions qui vous nous permettre d'appliquer des
      filtres sur les champs des enregistrements.</para>

      <sect2>
        <title>Opérateurs</title>

        <para>Nous avons à notre disposition l'ensemble des opérateurs
        mathématiques et logiques courants :+ - * /</para>

        <table>
          <title>Opérateurs</title>

          <tgroup cols="2">
            <tbody>
              <row>
                <entry><emphasis role="bold">Opérateur</emphasis></entry>

                <entry><emphasis role="bold">Symbole</emphasis></entry>
              </row>

              <row>
                <entry>Addition</entry>

                <entry>+</entry>
              </row>

              <row>
                <entry>Soustraction</entry>

                <entry>-</entry>
              </row>

              <row>
                <entry>Multiplication</entry>

                <entry>*</entry>
              </row>

              <row>
                <entry>Division</entry>

                <entry>/</entry>
              </row>

              <row>
                <entry>ET logique</entry>

                <entry>AND</entry>
              </row>

              <row>
                <entry>OU logique</entry>

                <entry>OR</entry>
              </row>

              <row>
                <entry>NON logique</entry>

                <entry>NOT</entry>
              </row>

              <row>
                <entry>INFERIEUR</entry>

                <entry>&lt;</entry>
              </row>

              <row>
                <entry>SUPERIEUR</entry>

                <entry>&gt;</entry>
              </row>

              <row>
                <entry>EGALITE</entry>

                <entry>=</entry>
              </row>

              <row>
                <entry>Comparaison de chaînes</entry>

                <entry>LIKE</entry>
              </row>

              <row>
                <entry>Intervalle</entry>

                <entry>BETWEEN</entry>
              </row>
            </tbody>
          </tgroup>
        </table>

        <para>Nous pouvons ainsi sélectionner les planches qui datent d'avant
        2003 :</para>

        <para><programlisting>SELECT * FROM PLANCHE WHERE PLA_ANNEE &lt; 2003</programlisting></para>

        <para><programlisting>PLA_NUM     PLA_MARQUE     PLA_MODELE     PLA_ANNEE     PLA_TAILLE     PLA_POIDS     PLA_VOLUME       
1  TIGA  SLALOM 260  1997  2  9  90     
2  EXOCET  WAVE 259  2000  2  7  79     
4  BIC  SAXO  2000  2  8  100</programlisting></para>

        <para>En combinant les filtres, on peut récupérer les enregistrements
        des planches antérieures à 2003 et d'un volume inférieur à 100 litres
        :</para>

        <para><programlisting>SELECT * FROM PLANCHE WHERE PLA_ANNEE &lt; 2003 AND PLA_VOLUME &lt; 100</programlisting></para>

        <para><programlisting>PLA_NUM     PLA_MARQUE     PLA_MODELE     PLA_ANNEE     PLA_TAILLE     PLA_POIDS     PLA_VOLUME        
1  TIGA  SLALOM 260  1997  2  9  90     
2  EXOCET  WAVE 259  2000  2  7  79</programlisting></para>

        <para>La sélection des clients dont on a un numéro de GSM donnerait
        :</para>

        <para><programlisting>SELECT * FROM CLIENT WHERE CLI_TEL LIKE "06%"</programlisting></para>

        <para><programlisting>CLI_ID     CLI_NOM     CLI_PRENOM     CLI_ADR     CLI_VILLE     CLI_TEL      
1   KURZWEG  Ivan  Rue des mouettes  ST-PAUL  0692012345     
2  HOARAU  Paul  2 rue des Lilias  ST-PIERRE  0692101112</programlisting></para>

        <para>Ici, le caractères % permet de pérciser à MySQL de sélectionner
        les enregistrements dont le numéro de téléphone est composé de laa
        manière suivante : la chaîne "06" suivie de n'importe quel
        caractère.</para>
      </sect2>

      <sect2>
        <title>Fonctions sur les chaînes</title>

        <para>En plus des différents opérateurs que nous avons vu au
        paragraphe précédent, nous pouvons également utiliser des fonctions
        sur les valeurs des champs. Nous n'en détaillerons que certaines, la
        liste complète de ces fonctions étant disponible dans la documentation
        de MySQL :</para>

        <itemizedlist>
          <listitem>
            <para><command>TRIM ([LEADING ou TRAILING ou BOTH] [caractère]
            FROM nom de colonne) </command>: permet de supprimer les espaces
            ou tout autre caractère spécifié avant (LEADING) ou après
            (TRAILING) le champ.</para>
          </listitem>

          <listitem>
            <para><command>UPPER(colonne) LOWER(colonne)</command> : passent
            respectivement en majuscule et minuscules les valeurs de la
            colonne</para>
          </listitem>

          <listitem>
            <para><command>SUBSTRING ( nom de colonne,M,N) </command>: extrait
            la sous-chaîne de caractère commençant à la
            M<emphasis>ième</emphasis> lettre et de longueur N.</para>

            <para><programlisting>SELECT CLI_NOM, CLI_PRENOM, UPPER(CONCAT(SUBSTRING(CLI_NOM,1,1) , SUBSTRING(CLI_PRENOM,1 ,1))) AS INITIALES FROM CLIENT</programlisting></para>

            <para><programlisting>CLI_NOM     CLI_PRENOM     INITIALES      
KURZWEG  Ivan  KI   
HOARAU  Paul  HP   
PAYET  Jean  PJ   
PAYET  Marc  PM   
GRONDIN  paul  GP</programlisting></para>
          </listitem>
        </itemizedlist>
      </sect2>

      <sect2>
        <title>Fonctions sur les dates</title>

        <para>De la même manière, il est possible de travailler sur les dates
        :</para>

        <itemizedlist>
          <listitem>
            <para><command>EXTRACT ( YEAR ou MONTH ou DAY FROM nom de colonne
            ) </command>: permet d'extraire l'année, le numéro du mois ou le
            numéro du jour d'une date</para>
          </listitem>

          <listitem>
            <para><command>NOW()</command> : permet de récupérer la date et
            l'heure courante</para>
          </listitem>

          <listitem>
            <para><command>TO_DAYS(date) </command>: renvoie le nombre de
            jours depuis la date 0 jusque la date
            <emphasis>date</emphasis></para>
          </listitem>

          <listitem>
            <para><command>FROM_DAYS(date)</command> : renvoie le nombre de
            jours écoulées depuis la date <emphasis>date</emphasis></para>
          </listitem>
        </itemizedlist>

        <para>La sélection de toutes les locations effectuées pendant le mois
        d'octobre peut donc s'écrire :</para>

        <para><programlisting>SELECT * FROM loue WHERE MONTH(LOU_DATE) = 10</programlisting></para>

        <para><programlisting>LOU_ID     PLA_NUM     CLI_ID     LOU_DEBUT     LOU_FIN     LOU_DATE
1 1 2 14:10:00 15:12:00 2003-10-06
2 1 2 16:08:00 17:35:00 2003-10-15
3 2 2 13:36:00 14:35:00 2003-10-25
</programlisting></para>

        <para>Il existe de nombreuses autres fonctions de travail sur les
        dates, mais nous ne les passerons pas toutes en revue. Elles sont
        décrites précisément dans la documentation de MySQL.</para>
      </sect2>
    </sect1>

    <sect1>
      <title>Fonctions d'aggrégats</title>

      <para>Il existe des fonctions de statistiques permettant par exemple de
      calculer le nombre de lignes qu'une requête renvoie. L'utilisation de
      ces fonctions nécessite souvent la présence de la clause <command>GROUP
      BY</command>, permettant de créer des sous-ensembles de lignes : les
      enregistrements sont groupés selon la valeur des colonnes de la clause
      <command>GROUP BY</command>.</para>

      <para>Par exemple, nous souhaitons calculer le nombre de planche du
      magasin :</para>

      <para><programlisting>SELECT COUNT(PLA_MODELE) FROM PLANCHE

COUNT(PLA_MODELE)
4</programlisting></para>

      <para>Mais si notre requête vise désormais à compter le nombre de
      planche par marque, nous devons grouper les lignes par marque, pour les
      compter :</para>

      <para><programlisting>SELECT COUNT(PLA_MODELE), PLA_MARQUE FROM planche GROUP BY PLA_MARQUE

COUNT(PLA_MODELE) PLA_MARQUE
1 BIC
1 EXOCET
1 MISTRAL
2 TIGA</programlisting></para>

      <para>La longueur moyenne des planches serait obtenue par la requête
      suivante : <programlisting>SELECT AVG(PLA_TAILLE), PLA_MARQUE FROM PLANCHE GROUP BY PLA_MARQUE</programlisting></para>

      <programlisting>AVG(PLA_TAILLE)     PLA_MARQUE      
2.7799999713898  BIC   
2.5899999141693  EXOCET   
2.5699999332428  MISTRAL   
2.6749999523163  TIGA</programlisting>

      <para>la durée moyenne de location pourrait être obtenue par :</para>

      <para><programlisting>SELECT SEC_TO_TIME( AVG(TIME_TO_SEC(LOU_FIN) - TIME_TO_SEC(LOU_DEBUT)) ) 
AS MOYENNE FROM loue</programlisting></para>

      <para><programlisting>MOYENNE      
01:09:20</programlisting></para>

      <para>Nous verrons dans le chapitre suivant qu'il est également possible
      de filtrer les résultats d'une requête en utilisant la clause
      <command>HAVING</command>.</para>
    </sect1>
  </chapter>

  <chapter>
    <title>Utilisation d'une Base de Données</title>

    <sect1>
      <title>Index</title>

      <sect2>
        <title>Définition</title>

        <para>Les index ne font pas partie du SQL, même si c'est bien ce
        langage qui permet de créer les index dans les SGBDR, et dans MySQL en
        particulier.</para>

        <para>Un index permet de spécifier à MySQL de créer structure de
        données afin de stocker les données dans un ordre précis, afin d'en
        accélérer les recherches et les comparaisons. En terme de rapidité, le
        gain est considérable ! Ce gain est également appréciable lors des
        tris et des insertions de données.</para>

        <para>Il est possible d'indexer plusieurs colonnes d'une table à la
        fois, mais MySQL crée automatiquement un index par table, celui
        relatif à la clef primaire, afin d'accélérer les accès directs à la
        table.</para>

        <para>Plus généralement, il est conseillé de créer des index pour les
        cas suivants :</para>

        <itemizedlist>
          <listitem>
            <para>Les colonnes composant la clef primaire (automatique sous
            MySQL)</para>
          </listitem>

          <listitem>
            <para>Les colonnes composant les clefs étangères (obligatoire sous
            Mysql 5)</para>
          </listitem>

          <listitem>
            <para>Les colonnes les plus sollicitées par les recherches</para>
          </listitem>
        </itemizedlist>
      </sect2>

      <sect2>
        <title>Création d'index</title>

        <para>La création d'index se fait par la requête SQL suivante :</para>

        <para><programlisting>CREATE INDEX Nom_Index ON Nom_Table(Nom_col1, Nom_col2, ...)</programlisting></para>

        <para>Reprenons l'exemple des locations de planches à voile. MySQL a
        créé automatiquement les index sur les clefs primaires de chaque
        table. Ainsi, nous avons par défaut les index suivants :</para>

        <para>Table CLIENT : Index sur CLI_ID</para>

        <para>Table PLANCHE : Index sur PLA_NUM</para>

        <para>Table LOUE : Index sur LOU_ID</para>

        <para>Si l'on suit les recommandations listées dans le paragraphe
        précédent, nous allons donc devoir créer par exemple l'index
        supplémentaire :</para>

        <para><programlisting>CREATE INDEX CLI_NOM ON CLIENT(CLI_NOM) </programlisting>Création
        d'un index sur le nom des clients et ainsi accélérer certaines
        recherches.</para>
      </sect2>
    </sect1>

    <sect1>
      <title>Manipulation de tables</title>

      <sect2>
        <title>Sous requêtes</title>

        <para>Avec SQL, il est possible d'imbriquer des requêtes, et MySQL
        gère ce type de requêtes, depuis sa version 4.2.</para>

        <para>Sur l'exemple de la base de données Location de planche, nous
        voulons savoir quelle est la planche qui a le plus gros volume : la
        requête SQL donne</para>

        <para><programlisting>SELECT * FROM t_planche WHERE pla_taille 
= (
SELECT MAX(pla_taille) FROM t_planche)</programlisting></para>

        <para>Quand la sous requête renvoie une seule valeur, il est sûr
        possible d'utiliser tous les opérateurs de comparaison :</para>

        <para><programlisting>SELECT * FROM t_planche WHERE pla_annee 
&gt; 
(SELECT AVG(pla_annee) FROM t_planche)</programlisting><programlisting>SELECT * FROM t_planche WHERE pla_poids 
&lt; 
(SELECT AVG(pla_poids) FROM t_planche)</programlisting>Quand la sous requête
        renvoie une liste de valeur (une colonne), ll est alors possible de
        manipuler les sous requêtes avec des opérateurs d'existence : IN et
        NOT IN</para>

        <programlisting>SELECT * FROM t_planche WHERE pla_num 
NOT IN 
(SELECT pla_num FROM t_loue)</programlisting>

        <programlisting>SELECT * FROM t_planche WHERE pla_num 
IN 
(SELECT pla_num FROM t_loue, t_client WHERE t_loue.cli_id = t_client.cli_id AND cli_nom like 'Ivan' )
</programlisting>
      </sect2>

      <sect2>
        <title>Jointure</title>

        <para>Nous avons vu dans le chapitre précédent la sélection de données
        dans une seule table. Cependant, il est souvent nécessaire de
        manipuler plusieurs tables simultanément afin de faire des recherches
        plus complexes. Les jointures exploitent le modèle relationnel, et
        permettent d'utiliser la notion de clef étrangère. La plupart des
        jointures sont des equi-jointures, qui imposent de regrouper les
        enregistrements de plusieurs tables en fonction de l'égalité des
        valeurs d'une colonne.</para>

        <para></para>

        <para>La syntaxe générale est :</para>

        <para><computeroutput>SELECT nom_chp1, …, nom_chpN
        </computeroutput></para>

        <para><computeroutput>FROM table1, table2, …, tableN
        </computeroutput></para>

        <para><computeroutput>WHERE table1. nom_chp1 = table2.nom_chp2 …
        </computeroutput></para>

        <para><computeroutput>AND table2.nom_chp2 = tableN.nom_chpN …
        ;</computeroutput></para>

        <para>Dans notre exemple, si nous souhaitons avoir la liste des
        locations effectuées par les clients, il nous faut donc récupérer
        l'identifiant du client, puis sélectionner dans la table <emphasis
        role="bold">T_LOUE</emphasis> les enregistrements ayant les mêmes
        numéros de client. une première solution est de filtrer la requête
        :</para>

        <para><programlisting>SELECT * FROM t_client,t_loue WHERE t_client.cli_id = t_loue.cli_id</programlisting></para>

        <para>Dans de telles requêtes, aucune référence de colonne ne doit
        être ambiguë. Si deux tables différentes contiennent deux colonnes de
        même nom auxquelles la requête fait référence, il faut faire précéder
        le nom du champ par le nom de la table :
        <literal>nom_table.nom_champ</literal>. SQL permet de renommer, dans
        la requête, les différentes tables utilisées : c’est le même procédé
        que celui utilisé pour les alias (renommer les champs).</para>

        <para>Cette requête nous renvoie bien la liste de toutes les locations
        effectuées, en rajoutant les champs de tous les clients. Il est
        également possible de passer par des jointures dites naturelles, sous
        la syntaxe suivante.</para>

        <para><programlisting>SELECT * FROM t_loue INNER JOIN t_client ON t_client.cli_id = t_loue.cli_id</programlisting></para>

        <para>Cette requête affiche donc la liste des champs des tables LOUE
        et CLIENT en liant les deux tables sur le critère du numéro client. Il
        est également possible de faire des requête RIGHT OUTER JOIN, qui
        permettent de renvoyer les enregistrement des tables ne satisfaisant
        pas la condition d'équi-jointure :</para>

        <para><programlisting>SELECT * FROM t_loue RIGHT OUTER JOIN t_client ON t_client.cli_id = t_loue.cli_id</programlisting></para>

        <para>On recherche toutes les valeurs satisfaisant la condition de
        jointure précisée dans<emphasis> prédicat</emphasis>, puis on rajoute
        toutes les lignes de la table <emphasis>TDroite</emphasis> qui n'ont
        pas été prises en compte au titre de la satisfaction du critère.
        Ainsi, on dispose dans notre exemple des locations effectuées, avec en
        plus les clients enregistrés mais n'ayant fait aucune location.</para>

        <para>MySQL préconise de se limiter aux jointures droites (RIGHT), et
        si besoin de modifier une jointure gauche (LEFT) en droite en
        inversant le sens des tables.</para>
      </sect2>

      <sect2>
        <title>Requêtes sur plusieurs tables</title>

        <para>Plus que des requêtes d'équi-jointures (c'est-à-dire joignant
        des champs de deux tables sur un critère d'égalité), il est bien sûr
        possible de sélectionner des champs de plusieurs tables distinctes sur
        des critères différents.</para>

        <para>Par exemple, nous souhaitons dans notre base de location de
        planches à voiles sélectionner l'ensemble des données des locations
        portant sur des planches de plus de 2,65 mètres. La requête SQL
        pourrait donner :</para>

        <para><programlisting>SELECT * FROM LOUE, CLIENT, PLANCHE WHERE CLIENT.CLI_ID = LOUE.CLI_ID AND LOUE.PLA_NUM = PLANCHE.PLA_NUM AND PLA_TAILLE &gt; 2.65</programlisting></para>

        <para>Nous avons dans cette requête :</para>

        <itemizedlist>
          <listitem>
            <para>deux jointures : sur le numéro de client et sur le numéro de
            planche, qui correspondent aux clefs étangères. Les champs ayant
            le même nom dans les tables, nous sommes obligés de préciser à
            chaque fois de quelle table nous voulons sortir le champ, en
            faisant précéder le nom du champ du nom de la table.</para>
          </listitem>

          <listitem>
            <para>un filtre : il s'agit ensuite filtrer les enregistrements
            provenant des jointures, en utilisant la condition fixée : la
            longeur de la planche doit être inférieure à 2,65 mètres.</para>
          </listitem>
        </itemizedlist>
      </sect2>
    </sect1>
  </chapter>

  <chapter>
    <title>Optimisation et sécurisation</title>

    <sect1>
      <title>Sécurite d'accès</title>

      <sect2>
        <title>Notion d'utilisateur et de groupe</title>

        <para>Sous MySQL comme sous la plupart des SGBDR, il est possible de
        définir des groupes et des utilisateurs, afin d'adopter une stratégie
        de sécurité. En effet, nous allons pouvoir restreindre certaines
        opérations sur la base de données à certains groupes ou certains
        utilisateurs. Ainsi, il sera possible d'autoriser la mise à jour des
        tables pour certains utilisateurs, et la refuser pour d'autres
        !</para>

        <para>Dans le cas d'applications WEB, il est bien sûr possible de
        créer autant d'utilisateurs MySQL que d'utilisateurs du site ou de
        l'Intranet. Mais nous verrons dans le paragraphe consacré à
        l'optimisation de MySQL que multiplier les utilisateurs peut avoir
        pour conséquence de ralentir fortement le serveur de base de
        données.</para>

        <para>Il est donc généralement préférable de créer un compte
        utilisateur permettant d'administrer la base de données, et un ou deux
        comptes utilisateurs n'ayant pas de droits de modification de la
        structure de la base (ne pouvant pas supprimer de tables, d'en créer,
        etc..), mais pouvant réaliser des insertions, des modifications ou des
        suppressions d'enregistrements.</para>

        <para>Nous allons voir dans le paragraphe suivant comment créer avec
        le langage SQL de comptes MySQL et leur affecter des droits.</para>
      </sect2>

      <sect2>
        <title>Ajout et suppression de droits</title>

        <para>Il est possible de créer des utilisateurs en modifiant
        directement la table <command>USERS </command>dans la base de données
        MySQL. Ainsi, en ajoutant un nouvel enregistrement dans cette table,
        un utilisateur est directement créé. Cependant, cette méthode est
        source d'erreurs de syntaxe et d'attribution des droits.</para>

        <para>Ainsi, et comme le recommande la documentation de MySQL, il vaut
        mieux effectuer les opérations de mise à jour des utilisateurs et des
        droits avec la commande MySQL <command>GRANT</command>. La syntaxe de
        cette requête est la suivante :</para>

        <para><programlisting>GRANT priv_type [(liste_colonnes)] [, priv_type [(liste_colonnes)] ...] 
ON nom_de_table | * | *.* | nom_base.* 
TO nom_utilisateur [IDENTIFIED BY [PASSWORD] 'password']</programlisting></para>

        <para>L'ajout d'un utilisateur sur la base de données
        <command>LOCATION_PLANCHE</command> serait donc :</para>

        <para><programlisting>GRANT USAGE ON * .Location_planches TO "util2"@ "%"IDENTIFIED BY "********";
GRANT SELECT , INSERT , UPDATE , DELETE ON `Location_planches` . * TO "util1"@ "%";</programlisting></para>

        <para>Créer un nouvel utilisateur sur la machine locale, ayant tous
        les droits sur toutes les bases donnerait :</para>

        <para><programlisting>GRANT ALL PRIVILEGES ON *.* TO ikare@localhost IDENTIFIED BY 'motdepasse' WITH GRANT OPTION;</programlisting></para>

        <para>La révocation des privilèges se fait par la commande
        <command>REVOKE</command>, dont la syntaxe est la suivante : </para>

        <para><programlisting>REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ...
    ON {tbl_name | * | *.* | db_name.*}
    FROM user [, user] ...

REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...</programlisting></para>

        <para>Une fois les droits ajoutés (ou enlevés) pour un (des)
        utilisateur(s), il ne faut pas oublier de les
        <quote>recharger</quote>, en utilisant la commande
        <command>FLUSH</command> : </para>

        <para><programlisting>FLUSH PRIVILEGES;</programlisting></para>

        <para>Enfin, un moyen simple et efficace de créer des utilisateurs et
        de leur attribuer des droits, est de passer par l'outil
        <emphasis>PhpMyAdmin</emphasis> ! En effet,
        <emphasis>PhpMyAdmin</emphasis> (généralement disponible chez la
        plupart des fournisseurs d'accès), propose sous son interface
        graphique une gestion simple et complète des utilisateurs : ajout d'un
        nouvel utillisateur, mise à jour de ses droits, etc..</para>
      </sect2>

      <sect2>
        <title>Types de privilèges sous MySQL</title>

        <para>Dans la commande <command>GRANT</command> ou
        <command>REVOKE</command>, les droits peuvent être définis selon la
        liste suivante, selon les privilèges désirés.</para>

        <table>
          <title>Privilèges MySQL</title>

          <tgroup cols="2">
            <thead>
              <row>
                <entry align="center">Droit</entry>

                <entry align="center">Signification</entry>
              </row>
            </thead>

            <tbody>
              <row>
                <entry>ALL [PRIVILEGES] </entry>

                <entry>Tous les droits sauf WITH GRANT OPTION</entry>
              </row>

              <row>
                <entry>ALTER</entry>

                <entry>Autorise l'utilisation de ALTER TABLE</entry>
              </row>

              <row>
                <entry>CREATE</entry>

                <entry>Autorise l'utilisation de CREATE TABLE</entry>
              </row>

              <row>
                <entry>CREATE TEMPORARY TABLES</entry>

                <entry>Autorise l'utilisation de CREATE TEMPORARY
                TABLE</entry>
              </row>

              <row>
                <entry>DELETE</entry>

                <entry>Autorise l'utilisation de DELETE</entry>
              </row>

              <row>
                <entry>DROP</entry>

                <entry>Autorise l'utilisation de DROP TABLE</entry>
              </row>

              <row>
                <entry>EXECUTE</entry>

                <entry>Autorise l'utilisateur à exécuter des procédures
                stockées (pour MySQL 5.0)</entry>
              </row>

              <row>
                <entry>RELOAD</entry>

                <entry>Autorise l'utilisation de FLUSH</entry>
              </row>

              <row>
                <entry>INDEX </entry>

                <entry>Autorise l'utilisation de CREATE INDEX et DROP
                INDEX</entry>
              </row>

              <row>
                <entry>SELECT</entry>

                <entry>Autorise l'utilisation de SELECT</entry>
              </row>

              <row>
                <entry>SHOW DATABASES</entry>

                <entry>SHOW DATABASES affiche toutes les bases de
                données</entry>
              </row>

              <row>
                <entry>SHUTDOWN</entry>

                <entry>Autorise l'utilisation de mysqladmin shutdown</entry>
              </row>

              <row>
                <entry>UPDATE</entry>

                <entry>Autorise l'utilisation de UPDATE</entry>
              </row>

              <row>
                <entry>USAGE</entry>

                <entry>Synonyme de ``pas de droits''</entry>
              </row>

              <row>
                <entry>GRANT OPTION</entry>

                <entry>Synonyme pour WITH GRANT OPTION</entry>
              </row>
            </tbody>
          </tgroup>
        </table>
      </sect2>
    </sect1>

    <sect1>
      <title>Optimisation</title>

      <sect2>
        <title>Optimisation des requêtes</title>

        <para>Nous avons vu que les requêtes SQL de sélection de données
        peuvent s'écrire de multiples manières.</para>

        <para>Ainsi, une requête peut s'effectuer plus ou moins rapidement
        selon l'ordre des conditions de sélection. De manière générale, il est
        conseillé de placer les conditions les plus restrictives en début de
        requêtes.</para>

        <para>Nous avons également vu que nous avions la possibilité d'ajouter
        des index aux tables. Ainsi, si des requêtes manipulent souvent des
        colonnes de certaines tables, il peut être intéressant de créer des
        index sur ces colonnes.</para>

        <para>Il existe d'autres moyens plus technique d'optimiser les
        requêtes sur MySQL, mais il faut généralement accéder directement au
        serveur. La documentation de MySQL détaille ces différents
        points.</para>
      </sect2>

      <sect2>
        <title>Optimisation de la base de données</title>

        <para>Outre la bonne rédaction des requêtes, c'est au niveau même de
        la conception que nous pouvons agir. En effet, un découpage cohérent
        des tables dans la base de données peut accélérer considérablement
        l'accès aux données :</para>

        <para>en effet, si un index n'est pas créé sur une colonne, MySQL doit
        lire l'ensemble des données de la table pour accéder à un
        enregistrement. Plus la taille des enregistrements sera réduite, plus
        la lecture sera rapide.</para>

        <para>Cette taille peut être diminué en concevant un modèle
        relationnel efficace, et en choisissant avec précaution les types de
        données des colonnes.</para>
      </sect2>

      <sect2>
        <title>Ce que ne peut faire MySQL (ne pouvait pas ...)</title>

        <para>Le mode transactionnel permet de gérer les requêtes par lot, et
        ainsir de garantir une certaine intégrité dans la base de données en
        cas de problèmes sur le serveur (panne, etc..), et de gérer les
        conséquences des accès concurrentiels : comment doit se comporter le
        SGBDR dans le cas d'une sélection et d'une suppression intervenant en
        même temps par exemple.</para>

        <para>MySQL ne gère pas par défaut le mode transactionnel : il faut en
        effet recompiler le moteur du SGBD avec l'option InnoDB pour
        bénéficier des avantages des transactions. Peu de fournisseurs Web
        propose cette implémentation, mais elle devrait être présente dans la
        version 5.0 de MySQL.</para>

        <para>MySQL ne gère pas l'intégrité référentielle, nous l'avons vu
        dans les chapitres précédents. C'est un problème majeur pour les
        puristes.</para>

        <para>MySQL ne gère pas les sous-requêtes, mais ce sera fait dans
        MySQL 5.0</para>

        <para>MySQL ne peut pas gérer les procédures stockées, qui augmentent
        la rapidité des requêtes.</para>

        <para>D'une manière générale, on peut dire que MySQL est relativement
        rapide pour les lectures de données, et capable de supporter quelques
        dizines connexions simultanées. Mais ce SGBDR est souvent critiqué
        pour ses faiblesses (choix défendus par les créateurs de MySQL) et de
        nombreux développeurs se tournent vers PostGreSQL. </para>

        <para></para>
      </sect2>
    </sect1>
  </chapter>
</book>
