0. Introduction▲
L'opérateur logique IN est un opérateur d'égalité strictement réservé à SQL. Il permet de déterminer si la valeur d'une expression est égale à l'une des valeurs comprises dans une liste donnée.
L'opérateur IN ne doit être confondu ni avec la clause de SQL qui détermine une source de données ni avec le mot clef VBA de la syntaxe For.
I. La syntaxe▲
La syntaxe est la suivante :
WHERE
NomChamp IN
(
valeur1, valeur2, ... , valeurX )
La liste d'éléments à comparer est placée entre parenthèses.
On peut également trouver sa forme négative :
WHERE
NomChamp NOT
IN
(
valeur1, valeur2, ... , valeurX )
Il faut savoir que dans sa forme négative, il ne bénéficie pas de l'optimisation Rushmore. Pour en savoir plus sur la technologie Rushmore consultez le tutoriel sur l'optimisation des bases de données Microsoft Access.
https://loufab.developpez.com/tutoriels/access/optimisation/
On peut également utiliser une requête comme liste d'éléments à comparer, à condition que cette dernière ne renvoie qu'un champ.
SELECT
*
FROM
TableA WHERE
NomChamp IN
(
SELECT
ChampId FROM
TableB)
Cette forme de relation est intéressante par la souplesse de sa rédaction.
I-A. IN vs. =▲
Les exemples suivants démontrent l'avantage de l'opérateur IN.
Avec l'opérateur d'égalité la requête aura cette forme :
SELECT
*
FROM
TableA WHERE
champId =
1
or
champId =
3
or
champId =
10
;
La même requête simplifiée grâce à l'opérateur IN :
SELECT
*
FROM
TableA WHERE
champId IN
(
1
,3
,10
)
;
II. En pratique▲
Nous allons voir comment l'opérateur s'intègre parfaitement au fonctionnement d'une application pour créer des filtres à moindre coût.
II-A. Zone liste, IN et état▲
La zone de liste est un contrôle sympathique, encore faut-il pouvoir tirer parti de sa sélection multiple.
Pour la mise en pratique vous avez besoin d'une table contenant au moins un identifiant unique de type numérique et un champ de type texte.
Commencez par créer un formulaire composé d'une zone de liste et d'un bouton de commande.
La zone de liste doit être réglée de la manière suivante :
Nom | Zliste |
Nbre Colonnes | 2 |
Largeurs colonnes | 0 ;5 |
Contenu | SELECT TCategorie.IdCategorie, TCategorie.Nom FROM TCategorie ORDER BY TCategorie.Nom; |
Sélection Multiple | Simple (ou Étendue) |
Voici le résultat.
Créez ensuite un état nommé Test contenant les champs de cette même table. Peu importe la mise en page, c'est pour l'exemple.
Grâce à l'opérateur IN nous allons imprimer les éléments choisis dans la liste.
Dans l'événement Sur clic du bouton de commande insérez le code suivant :
Private
Sub
Commande2_Click
(
)
Dim
itm As
Variant
' l'item choisi
Dim
lstval As
String
' la liste des id sélectionnés
For
Each
itm In
Me.Zliste.ItemsSelected
' parcourt les items
lstval =
lstval &
Me.Zliste.ItemData
(
itm) &
","
' insère chaque id dans la variable
Next
lstval =
Left
(
lstval, Len
(
lstval) -
1
) ' supprime la dernière virgule
DoCmd.OpenReport
"Test"
, acViewPreview, , "IdCategorie IN ("
&
lstval &
")"
' imprime la sélection
End
Sub
La méthode est simple, cependant elle ne gère pas l'erreur levée lorsqu'il n'y a pas de choix.
Sélectionnez quelques éléments et cliquez sur le bouton.
II-A-1. Variante avec du texte▲
La syntaxe est pratiquement identique à une différence près. Comme nous utilisons des éléments texte il faut utiliser le séparateur texte dans la liste de l'opérateur IN.
Changez la propriété de la liste :
Colonne Liée | 2 |
Modifiez le code du bouton :
lstval =
lstval &
""""
&
Me.Zliste.ItemData
(
itm) &
""","
' insère chaque id dans la variable
Modifiez l'appel de l'état pour intégrer le nouveau nom de champ.
DoCmd.OpenReport "Test", acViewPreview, , "Nom IN (" & lstval & ")" ' imprime la sélection
La syntaxe SQL sera donc :
WHERE
NOM IN
(
"coiffeur"
,"concerts"
)
II-A-2. Variante avec des dates▲
Construisez un nouvel état avec cette source contenant une date et un champ texte. Indiquez la même source pour la zone de liste.
La ligne de construction de la liste change. Il faut mettre le symbole dièse (#) qui est le séparateur de dates et le format de date US.
lstval =
lstval &
"#"
&
Format
(
Me.ZListe.ItemData
(
itm), "mm/dd/yyyy"
) &
"#,"
' insère chaque date
Les dates dans VBA doivent toujours être au format anglo-saxon.
L'appel du formulaire change également pour utiliser le bon nom de champ.
DoCmd.OpenReport
"Test2"
, acViewPreview, , "DateOperation IN ("
&
lstval &
")"
' imprime la sélection
La syntaxe SQL sera donc :
WHERE
DateOperation IN
(
#10/02/2011#
,#12/12/2010#
)
III. Limitation▲
Hormis le problème avec la forme négative de l'opérateur IN (Not IN) les limitations ne sont pas légion. En effet la liste peut compter plusieurs centaines d'éléments.
La valeur NULL doit être considérée avec précaution. Comparée à un élément de la liste elle peut produire des effets inattendus.
La liste est un ensemble de 1 à x éléments. On peut donc utiliser ce code quel que soit le nombre de sélections.
IV. Conclusion▲
Utiliser l'opérateur IN simplifie grandement la construction des requêtes SQL. Il évite de longs et complexes algorithmes de construction de clause WHERE ou HAVING et facilite l'écriture des requêtes de vérifications de clefs externes.
V. Remerciement▲
Je remercie Claude LELOUP pour ses corrections, ainsi que f_leb et philben pour leurs remarques.