Les différentes relations possibles entre les tables

Ah ces relations ! A moins que vous ne soyez un développeur aguerri ou un fin connaisseur des bases de données, elles vous ont certainement déjà donné du fil à retordre. Je ne vais pas ici expliquer les bases des relations, car ce n'est pas le but, mais les différentes relations possible entre les tables. des informations basiques sont données dans mon cours en ligne, à la leçon 16 (payant).

Le prérequis pour suivre ce didacticiel est de savoir au moins un peu jouer avec les relations avec le menu Outils/Relations

Les exemples cités dans ce didacticiel

se reposent sur cette base de données.

Exemple 1 : Le plus courant, la relation 1 à plusieurs
Exemple 2 : une même table se rattache à plusieurs champs, de 1 à plusieurs
Exemple 3 : la relation de 1 à 1
Exemple 4 : la relation sans intégrité référentielle
Exemple 5 : Deux tables sans relation
Exemple 6 : Une table en relation avec elle-même

Exemple 1 : Le plus courant, la relation 1 à plusieurs

Ca, c'est vraiment LA relation la plus courante.

Imaginez la table Rel1_T_Client avec 2 champs : NomClient et PaysOrigine. NomClient est en clé primaire. Bon, ce n'est pas une bonne idée de mettre NomClient en Clé primaire puisque dans la vie courante, plusieurs clients peuvent avoir le même nom, mais c'est pour simplifier.

Nous avons un 2ème champ PaysOrigine qui n'est pas en clé primaire, forcément, puisqu'il peut y avoir plusieurs fois le même (2 fois Belgique dans notre cas).

L'autre table s'appelle Rel1_T_Pays, et ne contient qu'un seul champ Pays, en clé primaire (oui, cette fois, il ne peut pas y avoir 2 fois le même pays)... Constatez que Les champs Pays et PaysOrigine que nous allons lier ensemble ne portent pas le même nom, ce qui ne gêne en rien le mécanisme relationnel..

On peut bien évidemment créer une liste déroulante dans la table Rel1_T_Client, sur le champ PaysOrigine, qui se basera sur le champ Pays de Rel1_T_Pays. Je ne m'appesantis pas sur ces listes pour rester vraiment dans cette histoire de relations pure et dure.

On peut donc avoir un client qui n'a pas de pays (Daniel), et des clients qui ont le même pays (Alice et Charles). MAIS, il sera impossible de dire que Daniel vient du Chili par exemple, car le Chili n'existe pas dans Rel1_T_Pays.

C'est dans Outils/Relations que nous allons faire glisser PaysOrigine de Rel1_T_Client sur Pays de Rel1_T_Pays. (Dans un sens ou dans l'autre, aucune importance)

Et nous obtenons :

Les champs en gras NomClient et Pays sont simplement les clés primaires. Et le petit 1 et le 8 couché (signe qui veut dire "Infini") sont la preuve que l'intégrité référentielle a bien été appliquée... Si nous avions eu des clients qui provenaient du Chili par exemple, c'est à dire s'il y avait "Chili" indiqué pour un des clients, alors, Access n'aurait pas accepté de faire l'intégrité référentielle.

Il peut y avoir d'autres soucis, comme le fait de ne pas fermer une table avant d'aller dans les relations, qui provoque des erreurs, mais à nouveau, référez-vous à mon cours pour des renseignements plus basiques.

Exemple 2 : une même table se rattache à plusieurs champs, de 1 à plusieurs

Ce 2ème exemple ressemble énormément au premier, mais il y a cette fois deux champs qui demandent à être rattachés à une seule table externe :

Nous avons cette fois un champ PaysOrigine et un champ PaysHabitation...

Vous savez quoi ? ça ne pose pas du tout de problème ! Dans outils/Relations, il suffit d'ajouter deux fois Rel2_T_Pays, comme ceci :

J'INSISTE : Rel2_T_Pays_1 n'est PAS une copie de la table Rel2_T_Pays ! C'est simplement la manière d'Access de préciser que la même table est utilisée deux fois.

Exemple 3 : la relation de 1 à 1

La relation 1 à 1 est vraiment plus rare que la relation 1 à plusieurs. Il est même possible que vous n'en ayiez jamais besoin. Mais il est bien de savoir à quoi elle peut servir !

Saviez-vous qu'Access ne gère pas un nombre illimité de champs ? Eh non ! A partir d'une centaine de champs, il faut s'attendre à ce qu'il vous dire que la table comporte de trop nombreux champs ! Ca vous intéresse, les limites d'Access ? Cliquez ici !

Imaginez que vous avez une table absolument gigantesque gérant par exemple l'état de patient d'un hôpital... Il y aura bien entendu son nom, son age, son poids, puis son taux de cholestérol, de glycémie, et ensuite son nombre de globules rouges, blancs, machins bidules, trucs... bref, je ne suis pas médecin, mais je peux imaginer qu'on a besoin de 200 informations différentes pour un même patient... Alors donc, comme vous n'arriverez pas à mettre 200 champs dans une même table, vous créerez deux tables, qui seront liées de 1 à 1.

Vous comprenez le principe ? Bon, pour ne pas nous attarcder sur le milieu médical, nous allons prendre un exemple tout bête : Nous allons créer une table avec les données générales des clients, et une 2ème table avec les données Telecom (Téléphone, fax, e-mail, ...)

Il est très important que les deux champs liés (Ici NomClient et NomClient) soient en clé primaire, sinon, si l'un des deux ne l'est pas, ça ne fera pas une relation 1 à 1 mais 1 à plusieurs.

ATTENTION : Normalement, le sens dans lequel vous tirez un champ pour aller vers l'autre n'a aucune importance... En tout cas pour tout ce qui concerne les champs de 1 à plusieurs. Mais dans le cas des champs reliés de 1 à 1, ça A VRAIMENT de l'importance. Il FAUT bien tirer de la table principale (ici Rel3_T_Client) VERS la ou les autres tables liées de 1 à 1 (ici Rel3_T_ClientTelecom).

La raison en est que comme les deux tables sont liées avec intégrité référentielle, il FAUT donc qu'un client qui existe dans une table doit exister dans l'autre... Mais dans le cas d'un NOUVEAU client, comment pourrait-il être lié puisque le temps de le créer dans une table, il n'existe pas dans l'autre, vous comprenez ?

Si je crée François comme nouveau client dans Rel3_T_Client, le temps que je ferme la table, et que j'aie le rajouter dans Rel3_T_:Telecom, Access va hurler : "Hè ! Vous ne pouvez pas rajouter François dans la première table, puisqu'il n'existe pas dans la 2ème !" Et réciproquement !

Et on fait comment alors ???

Eh bien, en faisant bien gaffe de tirer les champs de la table principale vers l'autre et pas l'inverse, vous POUVEZ alors créer un nouveau client dans Rel3_T_Client sans pour autant qu'il y ait de relation avec l'autre table Rel3_T_Telecom. C'est d'ailleurs de que j'ai fait.

MAIS vous ne pouvez PAS créer de nouveau client dans Rel3_T_Telecom avant de l'avoir créé dans Rel3_T_Client.

A part ça, ne créez pas de tables multiples "pour faire joli" ou pour la jouer style genre "Je sais utiliser les relations 1 à 1"... Tant que vous pouvez tout stocker dans une même table, ça facilite les choses... d'autant que vous pouvez créer des requêtes qui affichent tels ou tels champs...

Exemple 4 : la relation sans intégrité référentielle

On peut dire d'une manière générale que "normalement", toutes les tables d'une base de données sont reliées "1 à plusieurs", les unes avec les autres. Les relations 1 à 1 sont rares.

Les relations sans intégrité référentielle peuvent se faire n'importe comment : vous pouvez tirez n'importe quel champ de n'importe quelle table, même si leur type de données est différents, du moment que vous ne cochez pas "intégrité référentielle". Lorsque vous créez une liste déroulante basée sur une autre table, à la fin de l'assistant, il vous dit "Voulez-vous que les relations soient créées ?". Si vous répondez Oui, vous aurez une relation sans intégrité référentielle.

Si vous entrez dans une base de données dans laquelle vous constatez que la quasi totalité des tables sont liées les unes aux autres sans intégrité, vous pouvez être presque certain qu'elle a été créée par quelqu'un qui ne connait pas le fonctionnement des relations.

Il existe toutefois des cas ou deux tables ont intérêt à être reliées sans intégrité référentielle.

Imaginons une table Rel4_T_Client, avec le nom du client, et sa ville d'origine qui est une liste déroulante qui va puiser les données dans Rel4_T_Ville :

La plupart des gens proviennent d'une vilel Suisse, mais de temps en temps, il y en a un qui vient d'une ville française, voire italienne ou finalement de n'importe quelle ville du monde...

Dans ce cas, créer une table des villes avec toutes les villes du monde, ça va le faire moyen ! Mais une table avec toutes les villes de Suisse, ou les principales villes utilisées, pourquoi pas !

Mais du coup, il faudrait que l'onpuisse soit choisir dans la liste déroulante la ville désirée, ou simplement écrire la vilel de son choix... mais alors, il n'est donc pas question de créer une relation avec intégrité référentielle entre les deux tables... C'est ce que je propose ici, justement :

Exemple 5 : Deux tables sans relation

Oui oui, c'est possible... Ce sont des cas complètement marginaux, mais pourquoi pas... J'insiste bien : c'est réellement exceptionnel qu'il existe des tables isolées de tout !

Imaginons par exemple un représentant d'une régie immobilière qui doit visiter quelques appartements dont les locataires vont bientôt quitter les lieux. Il s'agit donc de faire un état de sortie pour les différents appartements :

C'est à dire que pour chacun des 3 appartements, il va falloir faire les 5 vérifications de la table Rel5_T_Inventaire. Il n'y a absolument rien qu'on puisse lier entre les deux tables... Le champ Lieu et AFaire n'ont rien à voir l'un avec l'autre.

Par contre, lorsqu'on crée une requête basée sur deux tables qui ne sont pas liées ensemble, Access fait ce qu'on appelle un "Produit cartésien", c'est à dire qu'il multiplie une table avec l'autre... Vous n'avez pas compris ? Regardez la requête en mode création :

Nous installons les champs des deux tables, triés par ordre croissant les deux. Lançons la requête :

C'est ça, le produit cartésien, c'est prendre tous les enregistrements d'une table, et les mettre, chacun à leur tour, en relation avec chacun des enregistrements de l'autre table.

Maintenant, attention : Il n'est pas question de rajouter un champ Texte, par exemple pour écrire le résultat du contrôle.. Par exemple, "Fonctionnement des stores" pour "22, avenue du Mail", on ne peut écrire nulle part "3ème lamelle cassée"... EH non.. Il n'y a pas de place dans les tables pour accueillir cette valeur...

Donc, tout ce qu'on peut faire avec cette requête, c'est l'imprimer, et écrire les infos à la main...

Ou alors la copier coller dans Excel, et écrire les résultats du contrôle dans la 3ème colonne (C).. On pourra ensuite sauvegarder ce fichier Excel..

Ou encore transformer cette requête en requête de type "Création de table", et rajouter un champ "Resultat" dans la table nouvelle créée, mais nous nous éloignons ici du but initial qui était de parler des différentes relations possibles entre le tables.

Exemple 6 : Une table en relation avec elle-même

Bizarre, non ? Et pourtant, oui, on peut mettre une table en relation avec elle-même avec intégrité référentielle, en plus !

Ce n'est pas une relation très courante, mais imaginez la table suivante :

Chaque employe est dirigé par quelqu'un. Et on doit pouvoir choisir le chef de chaque personne dans la même table... Alice et Bob sont dirigés par Charles. Charles n'est dirigé par personne (C'est le grand patron), Daniel est dirigé par Alice et Eugène par Daniel.

On mettant deux fois la table Rel6_T_Employe dans les relations, on peut alors créer cette relation :

Et voilà, c'est aussi simple que ça.

ATTENTION : Lorsque vous allez créer la liste déroulante dans "DirigePar", et que vous allez vouloir demander la même table, Access ne va simplement pas vous la montrer ! C'est comme ça ! Il croit que vous vous trompez... L'astuce consiste à copier coller la table Rel6_T_Employe sous le nom Rel6_T_EmployeX, et créer la liste déroulante sur cette nouvelle table avec le X à la fin. Une fois terminée, vous allez dans les propriétés de la liste de choix, et vous enlevez les "X", comme ceci :

Et ça marche !