Créer une requête suppression basé sur 2 tables

Les requêtes peuvent être de deux types : Requêtes sélection et requêtes action. Les requêtes sélection ne modifient pas les données. Les requêtes action, c'est une autre histoire : il s'agit non pas de renvoyer des enregistrements en visualisation, mais de les traiter. Il peut y avoir plusieurs types de requêtes action. Lorsque vous créez une nouvelle requête, voici les choix possible d'action lorsque vous êtes dans une requête :

Nous allons ici nous occuper de la requête suppression. Vous avez la possibilité de télécharger ici la base de données qui a servi à l'élaboration de cette page.

Nous sommes donc en possession de deux tables :

T_Client

T_Pays

Client Pays Pays Continent
André Chili Chili Amérique
Bernard France Belgique Europe
Charles Chili Yémen Afrique
Daniel France France Europe
Eugène   Allemagne Europe
François Belgique Iran Afrique
Gaston Yémen    

Ces deux tables ne sont pas liées avec le menu Outils/Relations. Ce sont 4 simples champs texte.

Problème : Comment effacer dans la table T_Client les clients Européens ?

Sans le faire manuellement un par un bien sûr. Il va falloir créer une requête suppression.

Avant de se lancer au coeur du problème, simplifions : comment supprimer tous les clients en provenance de France ? Ca, c'est facile.

Avant de créer cette requête et de l'exécuter, je vous conseille de faire une copie de T_Client, ou de la base de données tout entière, parce qu'après, les clients de France seront supprimés pour de bon dans la table, et si on veut pouvoir faire d'autres tests, on a simplement intérêt à retrouver la table telle qu'elle était à l'origine, car avec Access, pas question de faire Edition/Annuler !

Demandez une nouvelle requête, choisissez T_Client, et requête de type suppression.

Lancez cette requête avec . Un message d'avertissement nous prévient :

Si vous répondez Oui, vous allez effectivement supprimer Bernard et Daniel de T_Client. Tout va bien ! Si vous le faites, il vous faudra récupérer ensuite T_Client avant la suppression, ou remettre à la main Bernard et Daniel.

Là où ça se corse, c'est que nous désirons effacer les clients européens. Maintenant, il va nous falloir ajouter T_Pays (). Une fois la table ajoutée, il va falloir tirer Client de T_Client sur Client de T_Pays pour créer la relation temporairement : .

Et dans la grille, il nous faut préciser qu'on désire "Europe" comme critère : . Mais dès maintenant, lorsque vous lancez la requête, vous obtenez le message : . Le fait de cliquer sur "Aide" ne vous aidera pas beacuoup...

Il est vrai qu'Access n'est pas censé être au courant de la table dans laquelle on veut supprimer les enregistrements... Et si on ajoute l'étoile dans la colonne à côté, comme ceci : , le message d'erreur est un peu différent, mais tout aussi antipathique : .

A partir de là, c'est la véritable prise de tête : j'ai tout essayé : changer les critères, cliquer avec le bouton droit pour demander les propriétés de la requête ou des champs, double-cliquer sur la relation, tenter de comprendre l'aide intégrée d'Access, cherché sur le Web, fouiner méticuleusement dans le menus à la recherche désespérée de l'endroit ou pouvait bien se cacher la réponse à "", mais rien de rien ! Qu'il s'agisse d'Access 2000 ou 2003 d'ailleurs.

Je remercie ici Caroline, qui connaît très bien Access qui m'a donné la solution.

Pour la mettre en oeuvre, parlons du mot-clé "IN". Imaginons une requête basée uniquement sur T_Client ou nous désirons la liste des clients en provenance de France ou du Chili. Voici une alternative :

Et en voici une autre :

Cette 2ème alternative est très intéressante, car à la place de "France";"Chili", il est possible d'intégrer une instruction SQL !

Je m'explique :

Vous pouvez fermer cette requête. Imaginons que nous désirons la liste de tous les pays Européens, créez une nouvelle requête, comme ceci : . Constatez que j'ai enlevé la coche de "Continent". C'est voulu, car je ne veux QUE la liste des pays. Ca donne ceci : .

C'est maintenant que ça devient intéressant : Si je voulais, à l'aide d'une requête basée sur T_Client SEULEMENT la liste de tous les pays européens, je pourrais écrire comme critère :

IN("Belgique";"France";"Allemagne")

Mais ce n'est pas dynamique ! Pour que ça le devienne, allez en mode SQL de cette requête que vous venez de créer (). Voici le code que vous allez rencontrer :

SELECT T_Pays.Pays
FROM T_Pays
WHERE (((T_Pays.Continent)="Europe"));

Sélectionnez ce code et copiez-le (Edition/Copier).

Maintenant, quittez cette requête. Pas besoin de la sauvegarder.

Créez une nouvelle requête basée UNIQUEMENT sur T_Client : . JUste après avoir écris IN(, bouton droit de la souris, et COLLER, pour coller l'instruction SQL que vous aviez copié avant : . Pensez a refermer la parenthèse :

WHERE (((T_Pays.Continent)="Europe"));)

Lorsque vous appuyez sur la touche ENTER, vous ne voyez plus que le début de l'instruction : . EN fait, il a copié l'instruction SQL sur 3 lignes. Il suffit de cliquer à la fin du mot Pays et d'appuyer sur la touche DELETE, et ensuite ESPACE () Répétez la même opération à la fin de la ligne pour finalement obtenir :

Si vous lancez cette requête, vous obtiendrez la liste des clients Européens (sans les noms des clients puisque je n'y ai pas mis la colonne correspondante)

Lorsqu'on compare avec la table, on constate que c'est bien exact :

Maintenant, transformons cette requête en requête suppression :

Et voilà : Lorsque vous l'exécutez, le message d'erreur insupportable est maintenant remplacé par le sympathique message d'attention :

Si vous téléchargez la base de données qui a servi à la conception de cette page, la requête finale suppression qui fonctionne s'appelle R_SuppressionClientFinale

Merci a Vincent Deboos pour son épurage en mode SQL. En effet la commande :

DELETE T_Client.Pays AS Expr1, [T_Client].[Pays]
FROM T_Client
WHERE ((([T_Client].[Pays]) In (SELECT T_Pays.Pays FROM T_Pays WHERE (((T_Pays.Continent)="Europe"));)));

Se résume à celle ci avec autant d'efficacité :

DELETE *
FROM T_Client
WHERE Pays IN (SELECT Pays FROM T_Pays WHERE continent="Europe");

---Fin---