Mes Conseils pour créer une Base de Données
Voici en vrac mes conseils pour la création d'une base de données.Cette page n'est pas un cours (pour ceux-ci, je vous invite à parcourir mes favoris - rubriques "Word,Excel,Access,VBA").En effet, il est préférable de suivre un cheminement identique entre chaque création; de manière à s'y retrouver plus facilement.
- Avant de se lancer dans Access, il faut prendre un petit moment de réflexion, éventuellement prendre un bout de papier et un crayon, de manière à normaliser nos données. "Normaliser", voilà un mot important. Il faut entrevoir l'agencement des données dans la base. Le but étant d'encoder une seule fois une donnée (même si plus tard, on remarquera que l'on duplique certains champs, ces reproductions seront remplies automatiquement par Access). Déterminer les infos qui seront uniques et celles qui ne le seront pas (exemple : Si je crées une BD de données pour gérer ma collection de CD musicaux, je sais que le nom d'un artiste ne sera repris qu'une seule fois, par contre, si je veux relier les noms des albums à cet artiste, je sais qu'il y aura plusieurs albums correspondant à ce chanteur). Séparez ces infos dans des tables différentes...
- Faire une distinction entre des tables qui seront reliées (par une "Relation") entre elles et des tables qui ne servent qu'à remplir de manière uniforme le champ d'une autre table (Exemple, j'ai un champ intitulé "Pays" dans une table T_Timbres - pour philatélistes - et pour éviter que je n'encode le nom des pays de manière incohérente - une fois, "Belgique", une autre "Belgïe", "BE", "Belgium" , "B" etc.... je peux créer une table T_PaysDuMonde où j'aurai encodé d'une manière unique le nom des pays. Je transforme alors (on verra par la suite comment) le champ "Pays" de ma T_Timbres en liste déroulante et j'utilise comme référence le champ "Pays" de T_PaysDuMonde...). Dans cet exemple, la seconde table NE doit PAS être reliée (par une "Relation") à la première table.
- Les professionnels parlent de schéma EA (Entité - Association) . C'est ce que l'on pourra voir dans le menu "Outils de Base de Données - Relations"
Voilà pour clôturer ce sujet
- Vous avez remarqué sans doute que j'utilise une façon spéciale pour nommer mes tables. Voici donc une excellente habitude (apprise chez les grands maîtres de la programmation)... En effet, il est plus facile d'identifier les objets si l'on en détermine le type. Ainsi, une T_Voiture (Table), une Q_Voiture (Query - Requête en anglais), un F_Voiture (Formulaire), un R_Voiture (Rapport), une Mac_Voiture (Macro) et un Mod_Voiture (Module) m'inclineront à penser que l'on parle bien d'un même sujet. Il me sera plus facile d'identifier les objets lorsque je taperai du code VBA; je saurais immédiatement, si je manipule un formulaire ou un rapport ou autre...le signe "_" (underscore) permet de bien visualiser la différence entre le type et le nom de l'objet. Vous pourriez retrouver le même conseil vous détaillant une annotation comme tblVoiture, frmVoiture etc... j'ai abandonné cette écriture, l'emploi du caractère de soulignement me semble plus clair, plus visuel mais chacun fait son choix.
- L'ordre de citation des différents objets d'une base de données (non seulement, c'est celui dans lequel Access vous les présente) n'est pas anodin... Il faut toujours le respecter et savoir que les tables contiennent les données "brutes", qu'il faut éviter de travailler directement sur les tables, mais de créer des requêtes même si ces dernières sont des copies conformes des premières. En effet, à longue échéance, vous remarquerez que la maintenance de la BD en sera facilitée. Si vous faites une mauvaise manipulation sur la structure de la requête cela n'altère généralement pas vos données (j'ai bien parlé de la structure, pas des actions exécutées par les requêtes). Ensuite créez vos formulaires et vos rapports sur les requêtes et non sur les tables. Macro et modules sont des objets indépendants...
Agrémentons nos explications avec des images
Plusieurs remarques
- Remarquez le champ "CodePostal", voici la démonstration de ce que j'expliquais tout à l'heure, la T_Villes ne sert qu'à remplir le champ CodePostal; il n'y a pas de relation
- D'abord, évitez l'utilisation de champs à numérotation automatique, il faut savoir qu'en principe, les numéros automatiques ne sont générés qu'une seule fois, et que si vous effacez un ou plusieurs enregistrements, ces numéros disparaissent à jamais. On peut utiliser cette astuce mais autant l'éviter si on le peut. Cela risque de poser des problèmes s'il existe des "relations" entre les tables.
- Evitez également dans le nom des champs, d'y mettre des accents: Ecrivez "Prenoms" et non "P"rénoms". Evitez les espaces et utilisez les majuscules pour différencier les "séparations entre les mots: Ecrivez "CodePostal". Evitez tous caractères spéciaux comme "°" : Ecrivez "NuIdentite" au lieu de "N° Identité"... Ceci vous facilitera la tâche lorsque vous utiliserez le VBA. Si malgré tout, vous souhaitez voir sur l'écran les accents, espaces et caractères spéciaux, utilisez la propriété "Légende" (Caption en anglais)
- Utilisez la description des champs. N'oubliez pas, vous n'êtes pas seul au monde, une autre personne peut reprendre votre application, elle doit pouvoir la comprendre et savoir à quoi servent les objets; cela facilite la maintenance. Vous-mêmes, dans 6 mois, vous risquez que votre mémoire vous fasse défaut; vient alors la question "Qu'est-ce que j'ai encore voulu réaliser ici ?" (perte de temps pour refaire le cheminement de votre pensée!) Si un champ comme "Noms" est souvent explicite, il n'en va pas de même avec d'autres plus spécifiques. Notez d'où il "vient" et où il "va" peut être d'un grand secours
- Idem pour la base de données, décrivez l'utilisation des objets (Tables, Requêtes, Formulaires, etc..). Avec l'arrivée du tableau de bord, il faut faire un clic droit sur l'objet et choisir la commande "Propriétés"
Il est temps de nous préoccuper de cette fameuse "relation". Cliquez sur l'icône ad hoc dans la barre d'outils. Enfoncer le bouton ajouter pour sélectionner les tables qui seront concernées. Dans les versions avec ruban, on retrouve cette icône dans les "Outils de Base de Données"
En "tirant" (sélectionner, garder le bouton gauche enfoncé sur l'objet) le champ NuIdentite de la T_Professeurs sur le champ "NuProfesseur" de T_Eleves, on provoque l'affichage de nouvelles fenêtres qui vont nous permettre de créer une Relation entre les 2 tables et de nous permettre de régler le type de jointure que l'on souhaite
C'est ici que la période de "Normalisation" va démontrer son utilité. Appliquer toujours l'intégrité référentielle, la mise à jour en cascade, et l'effacement en cascade, Ceci donnera plus de cohérence à votre base de donnée et vous évitera du travail. Tâchez de fixer vos relations AVANT de commencer l'encodage de données. La relation vérifiera ainsi la cohérence de l'organisation de vos tables.
Une fois la relation établie, on voit apparaître les symboles suivant le type "un à plusieurs" ou "un à un" etc...
Voyons les requêtes... Certains s'étonnent d'obtenir ce résultat (ci-dessous): il est impossible d'ajouter des enregistrements. Sachez que ceci trahit une incohérence et qu'il faut trouver une autre solution... Parfois, passer par une requête intermédiaire peut vous permettre d'obtenir un résultat
Nous créons deux simples requêtes sur nos tables T_Professeurs et T_Eleves, et sur chacune nous bâtissons un formulaire. Sur T_Professeurs, choisissez le mode "Colonne Simple"...Pour T_Eleves, choisissez mode "Tabulaire"
Passez en mode construction du formulaire, sélectionnez tous les champs, agrandissez le volet "Entête du formulaire", faites un couper (CTRL+X), cliquez sur le titre du volet "Entête du formulaire" et collez les champs (CTRL+C). Réduisez le formulaire et placez les 2 fenêtres côte à côte, et avec la souris faites un drag and drop de F_Eleves dans la partie "Détails" de F_Professeurs
Éditez les propriétés du SF_Eleves (c'est le bord du SF qui doit être sélectionné pour obtenir la bonne fenêtre). Sur les propriétés "Champs fils" et "Champs pères", il y a trois petits points, faites apparaître la fenêtre pour les désigner
Après quelques modifications au niveau de l'affichage, mise en place de l'interface graphique (pour faire joli) on peut commencer à travailler, et l'on constate que l'on relie bien un professeur à ces élèves, pour autant que ceux-ci n'en fréquentent qu'un seul. Le cas des études primaires mais ce système connaîtra ses limites lorsque l'on affrontera les classes supérieures, où un élève suit les cours de professeurs différents (quand je vous disais qu'il fallait réfléchir avant de se lancer dans la conception d'une BD - que doit-on considérer comme "unique" le professeur qui a DES élèves ou l'élève qui a DES professeurs ?)
La plupart du temps, c'est pourtant bien cette organisation qu'il faudra choisir. Nous sommes ici face à un cas spécial. Alors comment s'en sortir ? Et bien, il faut balayer tout ce que je viens de dire ou presque ....
Examinons nos contraintes
- Il nous faut bien une table reprenant les élèves de l'établissement et cela une seule fois - tout le monde est d'accord là-dessus
Il nous faut bien une table reprenant les professeurs de l'établissement et cela une seule fois - ceci signifie donc une clé primaire dans chacune des tables et ceci sans doublons. c'est indispensable si on veut connaître par exemple, le nombre d'élèves dans l'établissement, si on autorise les doublons dans l'index, on finira par encoder plusieurs fois la même personne...On n'est toujours pas sorti du guêpier dans lequel on se trouve...
Solution : quelques transformations dans la BD
- On copie/colle notre T_Eleves en T_Ecoliers (cette dernière table sera notre fichier où cette population sera recensée de manière unique.
- De plus, elle va nous servir à remplir les champs de la T_Eleves à la manière de T_Villes. On transforme donc les champs T_Eleves.Noms, T_Eleves.Prenoms en liste déroulante basées sur les champs T_Ecoliers.Noms, T_Ecoliers.Prenoms
- On se débarasse du champ T_Eleves.NuEleves, il n'a plus de raison de se trouver dans cette table, il remplit son rôle dans T_Ecoliers
- Idem dans T_Ecoliers on supprime T_Ecoliers.NuProfesseur, on ne peut rien en faire dans ce domaine
- On corrige nos requêtes, on en crée une pour T_Ecoliers
- On corrige nos formulaires, on en crée un pour Q_Ecoliers
- On se crée quelques boutons de navigation entre les formulaires et un petit nouveau (formulaire indépendant) sur lequel on se crée un petit menu
On désigne ce menu comme formulaire de démarrage
Et Voilà ! cette solution n'est pas parfaite... En effet, on risque de créer des frères et soeurs à nos élèves (en se trompant de prénoms par exemple) et puis, il y a toujours des "fainéant(e)s" ou des "inquièt(e)s" qui n'ont pas envie de se casser la tête à réflèchir, à réencoder... Crénom!$%?!/ !!! de nom!§& !, mais bon, ils n'ont pas tort... bref! comment contourner cet obstable ...bin, il va falloir faire appel au VBA.
Appel au VBA
Pour se rafraîchir un peu la mémoire, on peut aller relire cette page (notamment ce qui concerne les références de l'environnement VBA - DAO)
- On va ajouter du code sur l'événement double-clic dans le champ Noms (ce qui nous permet d'ouvrir F_Ecoliers)
Private Sub Noms_DblClick(Cancel As Integer) 'On ouvre simplement le second Formulaire DoCmd.OpenForm ("F_Ecoliers") End Sub
- On ajoute un bouton sur notre F_Ecoliers et bien entendu du code
Private Sub Commande10_Click() Dim vNom As String, vPrenom As String, vCP As String Dim Db As DAO.Database, rs As DAO.Recordset, vSql As String 'Parce que l'on en rencontrera toujours bien une erreur On Error GoTo Err_Commande10_Click 'Récupération des infos essentielles Dim vNuProf As Integer vNuProf = Forms!F_Professeurs![NuIdentite] vNom = [Noms] vPrenom = [Prenoms] vCP = [CodePostal] 'Initialisation du recordset temporaire Set Db = CurrentDb vSql = "SELECT * FROM T_Eleves" Set rs = Db.OpenRecordset(vSql) 'On ajoute un nouvel enregistrement dans T_Eleves rs.AddNew rs("NuProfesseur") = vNuProf rs("Noms") = vNom rs("Prenoms") = vPrenom rs("CodePostal") = vCP rs.Update 'Il faut nettoyer la mémoire rs.Close Set Db = Nothing 'Obligatoire si on veut visualiser les changements Forms!F_Professeurs.Refresh 'On ferme ce que l'on a plus besoin DoCmd.Close acForm, "F_Ecoliers" 'Traitement d'une erreur Exit_Commande10_Click: Exit Sub Err_Commande10_Click: MsgBox "Le F_Professeurs n'est pas ouvert" Resume Exit_Commande10_Click End Sub
Enfin, ça marche ! j'espère n'avoir rien oublié !
Cliquez ici pour télécharger le fichier zip : Classe