1. Introduction
Le défi de la recherche de données séparées par des virgules dans MySQL
Lorsque vous travaillez avec des bases de données, vous pouvez rencontrer des cas où plusieurs valeurs sont stockées dans une seule colonne séparées par des virgules. Par exemple, une colonne peut contenir une chaîne comme "1,3,5", et vous pouvez vouloir extraire uniquement les enregistrements qui incluent la valeur « 3 ».
Dans de tels cas, l’utilisation de l’opérateur standard = ou de la clause IN ne produit souvent pas les résultats attendus. En effet, une chaîne séparée par des virgules est traitée comme une seule valeur de chaîne, ce qui signifie que les comparaisons sont évaluées par rapport à la chaîne entière plutôt qu’aux éléments individuels qu’elle contient.
Qu’est‑ce que la fonction FIND_IN_SET ?
Dans des situations comme celle‑ci, la fonction MySQL FIND_IN_SET devient très utile.
Cette fonction vous permet de déterminer facilement si une valeur spécifiée existe dans une chaîne séparée par des virgules.
Par exemple, considérez la requête SQL suivante :
SELECT * FROM users WHERE FIND_IN_SET('3', favorite_ids);
Dans cette requête, vous pouvez extraire les enregistrements où la chaîne séparée par des virgules dans la colonne favorite_ids (par ex. "1,2,3,4") contient la valeur « 3 ».
Objectif de cet article et public cible
Cet article explique comment utiliser la fonction FIND_IN_SET depuis les bases jusqu’à des cas avancés, de manière claire et structurée. Des syntaxes de base aux exemples pratiques, en passant par les comparaisons avec d’autres méthodes de recherche, les points importants et les FAQ, ce guide fournit des connaissances pratiques pour le développement réel.
Cet article s’adresse à :
- Ingénieurs web et développeurs backend qui utilisent régulièrement MySQL
- Développeurs qui doivent travailler avec des systèmes existants stockant des données séparées par des virgules
- Débutants en SQL confrontés aux correspondances partielles et aux recherches basées sur des valeurs
2. Syntaxe de base et comportement de la fonction FIND_IN_SET
Syntaxe de FIND_IN_SET
FIND_IN_SET est une fonction MySQL utilisée pour déterminer si une valeur spécifique existe dans une chaîne séparée par des virgules. La syntaxe de base est la suivante :
FIND_IN_SET(search_value, comma_separated_string)
Par exemple :
SELECT FIND_IN_SET('3', '1,2,3,4'); -- Result: 3
Dans cet exemple, comme « 3 » apparaît à la troisième position, la fonction renvoie la valeur numérique 3.
Règles de valeur de retour
La fonction FIND_IN_SET se comporte selon les règles suivantes :
| Condition | Result |
|---|---|
| The search value exists in the list | Its position in the list (starting from 1) |
| The search value does not exist | 0 |
| Either argument is NULL | NULL |
Exemple (renvoi de la position)
SELECT FIND_IN_SET('b', 'a,b,c'); -- Result: 2
Exemple (valeur non trouvée)
SELECT FIND_IN_SET('d', 'a,b,c'); -- Result: 0
Exemple (NULL inclus)
SELECT FIND_IN_SET(NULL, 'a,b,c'); -- Result: NULL
Exemple d’utilisation dans une clause WHERE
Cette fonction est le plus souvent utilisée pour filtrer dans une clause WHERE.
SELECT * FROM users WHERE FIND_IN_SET('admin', roles);
Dans cet exemple, seules les lignes où la colonne roles contient la chaîne « admin » seront retournées. Si la colonne contient une valeur comme "user,editor,admin", elle correspondra.
Remarques importantes sur les nombres et les chaînes
FIND_IN_SET effectue les comparaisons en tant que chaînes, ce qui signifie qu’elle se comporte comme suit :
SELECT FIND_IN_SET(3, '1,2,3,4'); -- Result: 3
SELECT FIND_IN_SET('3', '1,2,3,4'); -- Result: 3
Bien qu’elle fonctionne avec des valeurs numériques et des chaînes, des types de données peu clairs peuvent entraîner un comportement inattendu. Il est donc recommandé de gérer les valeurs explicitement comme des chaînes chaque fois que possible.
3. Exemples pratiques
Recherche dans une colonne qui stocke des chaînes séparées par des virgules
Dans les systèmes réels, vous pouvez rencontrer des cas où plusieurs valeurs (telles que des ID ou des permissions) sont stockées dans une seule colonne sous forme de chaîne séparée par des virgules. Par exemple, considérez la table users suivante.
| id | name | favorite_ids |
|---|---|---|
| 1 | Taro | 1,3,5 |
| 2 | Hanako | 2,4,6 |
| 3 | Jiro | 3,4,5 |
Lorsque vous souhaitez « récupérer les utilisateurs qui incluent 3 », la fonction FIND_IN_SET est extrêmement pratique.
SELECT * FROM users WHERE FIND_IN_SET('3', favorite_ids);
L’exécution de ce SQL renverra les enregistrements pour « Taro » et « Jiro ».
Fonctionne correctement même lorsque les valeurs semblent numériques
Même lorsque favorite_ids semble contenir des nombres, FIND_IN_SET effectue des comparaisons basées sur des chaînes, il est donc plus sûr de passer l’argument sous forme de chaîne entre guillemets.
-- OK
SELECT * FROM users WHERE FIND_IN_SET('5', favorite_ids);
-- Works, but strictly speaking not recommended
SELECT * FROM users WHERE FIND_IN_SET(5, favorite_ids);
Pour que les requêtes restent lisibles et le comportement prévisible, il est recommandé de spécifier explicitement la valeur sous forme de chaîne.
Recherches dynamiques (espaces réservés et variables)
Lors de la génération dynamique de SQL depuis une application web, il est courant d’utiliser des variables ou des paramètres liés.
Si vous utilisez une variable MySQL, cela ressemble à ceci :
SET @target_id = '3';
SELECT * FROM users WHERE FIND_IN_SET(@target_id, favorite_ids);
Lors de la liaison depuis la couche application (comme PHP, Python ou Node.js), vous pouvez gérer cela de façon similaire en utilisant des espaces réservés.
Comment gérer la recherche de plusieurs valeurs
Malheureusement, FIND_IN_SET ne peut rechercher qu’une seule valeur à la fois.
Si vous souhaitez récupérer les enregistrements contenant « 3 ou 4 », vous devez l’écrire plusieurs fois en utilisant OR.
SELECT * FROM users
WHERE FIND_IN_SET('3', favorite_ids) OR FIND_IN_SET('4', favorite_ids);
Si les conditions deviennent plus complexes, vous devez soit construire dynamiquement le SQL dans votre application, soit envisager de migrer vers une structure de table normalisée.
4. Comparaison de FIND_IN_SET avec d’autres méthodes de recherche
Alternatives courantes : IN et LIKE
Dans MySQL, en plus de FIND_IN_SET, vous pouvez également voir la clause IN ou la clause LIKE utilisées pour vérifier si une valeur est incluse. Cependant, chaque méthode se comporte différemment, et l’utiliser de manière inappropriée peut entraîner des résultats de requête incorrects.
Ici, clarifions comment elles diffèrent de FIND_IN_SET et quand utiliser chaque approche.
Comparaison avec la clause IN
La clause IN est généralement utilisée pour vérifier si une valeur correspond à l’une de plusieurs valeurs constantes.
-- Example of IN (this does NOT search inside "favorite_ids" for the value 3)
SELECT * FROM users WHERE favorite_ids IN ('3');
Dans ce cas, seuls les enregistrements où favorite_ids correspond exactement à « 3 » seront retournés. Cela signifie que des valeurs comme « »1,3,5″ » ne correspondront pas —seul une ligne dont la valeur de la colonne est exactement « »3″ » correspondra.
En revanche, FIND_IN_SET vérifie la position d’un élément dans une liste séparée par des virgules, vous permettant de récupérer avec précision les enregistrements qui incluent « 3 » comme suit :
SELECT * FROM users WHERE FIND_IN_SET('3', favorite_ids);
✅ Directive d’utilisation clé :
IN: À utiliser avec des tables normalisées (par ex.,SELECT * FROM posts WHERE category_id IN (1, 3, 5))FIND_IN_SET: À utiliser avec des chaînes dénormalisées séparées par des virgules
Comparaison avec la clause LIKE
Techniquement, vous pouvez utiliser LIKE pour une correspondance partielle, mais cela comporte d’importants pièges.
-- A common mistake with LIKE
SELECT * FROM users WHERE favorite_ids LIKE '%3%';
Cette requête ne signifie pas réellement « contient la valeur 3 » —elle correspond à toute chaîne contenant le caractère « 3 », ce qui peut entraîner des correspondances incorrectes comme « »13″ », « »23″ » ou « »30″ ».
Cela rend impossible la détection fiable de la présence de 3 en tant que valeur autonome.
✅ Directive d’utilisation clé :
LIKE: Utile pour les recherches textuelles floues, mais ne peut pas reconnaître les limites séparées par des virgulesFIND_IN_SET: Vérifie avec précision les correspondances de valeurs autonomes dans des listes séparées par des virgules
Différences de performance
| Method | Uses Index | Search Target | Speed |
|---|---|---|---|
IN | Yes | Number or single value | ◎ Very fast |
LIKE | Depends on pattern | Text scan | △ Can become slow depending on conditions |
FIND_IN_SET | No | Full scan | × May be slow |
En particulier, FIND_IN_SET ne peut pas utiliser d’index et déclenche souvent des scans complets de table. Si vous travaillez avec de grands ensembles de données, il peut être nécessaire de repenser le schéma.
5. Remarques importantes et bonnes pratiques
Non compatible avec les valeurs contenant des virgules
La fonction FIND_IN_SET suppose une liste simple de valeurs séparées par des virgules. Par conséquent, si un élément individuel de la liste contient lui‑même une virgule, la fonction ne se comportera pas comme prévu.
Exemple incorrect :
SELECT FIND_IN_SET('1,2', '1,2,3,4'); -- Result: 1
L’utiliser de cette façon peut produire des correspondances incorrectes parce que la chaîne entière est évaluée de manière inappropriée.
Vous ne devez utiliser cette fonction que lorsque vous pouvez garantir que les valeurs individuelles ne contiennent pas de virgules.
Problèmes de performance
Comme FIND_IN_SET ne peut pas utiliser d’index, il effectue un scan complet de la table. En conséquence, lorsqu’il est utilisé sur de grandes tables, les performances des requêtes peuvent se dégrader de manière significative.
Solutions de contournement :
- Au lieu de stocker des valeurs séparées par des virgules, normalisez la relation et gérez‑la dans une table séparée.
- Dans les environnements où la performance est critique, envisagez l’expansion de tables temporaires ou des stratégies basées sur les JOIN .
Par exemple, si vous créez une table intermédiaire telle que user_favorites, vous pouvez profiter des index pour des recherches plus rapides :
SELECT users.*
FROM users
JOIN user_favorites ON users.id = user_favorites.user_id
WHERE user_favorites.favorite_id = 3;
Lisibilité et maintenabilité
Bien que FIND_IN_SET puisse sembler pratique, il comporte plusieurs inconvénients :
- Les requêtes ne sont pas intuitives (elle renvoie des valeurs de position)
- Ajouter ou supprimer des valeurs est fastidieux
- L’intégrité des données est difficile à garantir (plusieurs significations dans une seule colonne)
Ainsi, lorsque la maintenabilité et l’intégrité des données sont importantes, revoir le schéma lui‑même est souvent la meilleure pratique.
Quand vous devez utiliser FIND_IN_SET
Il existe des situations où vous n’avez pas d’autre choix que de travailler avec des colonnes séparées par des virgules — comme les systèmes hérités ou les produits tiers. Dans ces cas, envisagez les précautions suivantes :
- Appliquez d’abord d’autres conditions de filtrage pour réduire le champ de recherche
- Prévenez les erreurs de formatage telles que les doubles virgules ou les espaces en début ou fin de chaîne
- Effectuez un traitement supplémentaire au niveau de l’application lorsque cela est possible
6. Questions fréquemment posées (FAQ)
FIND_IN_SET peut‑il utiliser des index ?
Non, FIND_IN_SET ne peut pas utiliser d’index. En interne, il découpe et évalue la chaîne, il ne bénéficie donc pas de l’optimisation d’index de MySQL.
En conséquence, l’utiliser sur de grandes tables peut ralentir les performances des requêtes. Pour les systèmes où la performance est critique, envisagez de redessiner le schéma ou de normaliser les données.
Fonctionne‑t‑il correctement avec des nombres et des chaînes mélangés ?
En général, oui — mais gardez à l’esprit que les comparaisons sont effectuées en tant que chaînes. Si des valeurs numériques et des chaînes sont mélangées, un comportement inattendu peut survenir.
Par exemple, les deux cas suivants renvoient une correspondance pour 3 :
SELECT FIND_IN_SET(3, '1,2,3,4'); -- Result: 3
SELECT FIND_IN_SET('3', '1,2,3,4'); -- Result: 3
Cependant, dans des cas comme FIND_IN_SET('03', '01,02,03'), le format avec zéro initial peut affecter le comportement de correspondance.
Il est plus sûr de standardiser le format des valeurs.
Comment rechercher plusieurs valeurs à la fois ?
Parce que FIND_IN_SET n’accepte qu’une seule valeur de recherche, si vous souhaitez rechercher des enregistrements contenant « 3 ou 4 », vous devez l’appeler plusieurs fois en utilisant OR :
SELECT * FROM users
WHERE FIND_IN_SET('3', favorite_ids)
OR FIND_IN_SET('4', favorite_ids);
Si les conditions deviennent plus complexes, envisagez de construire dynamiquement le SQL au niveau de l’application ou de migrer vers une structure de table normalisée.
FIND_IN_SET cause des problèmes de performance. Que faire ?
Les stratégies suivantes sont efficaces :
- Passer à une conception de table normalisée
- Appliquer d’abord des conditions de filtrage pour réduire le champ de recherche
- L’utiliser uniquement avec de petits ensembles de données
- Envisager de migrer vers des formats structurés tels que la recherche en texte intégral ou les types de données JSON
Les versions modernes de MySQL prennent en charge les types de données JSON. Par exemple, si vous gérez la colonne roles comme un tableau JSON, vous pouvez utiliser JSON_CONTAINS() pour des recherches flexibles et efficaces.
FIND_IN_SET sera-t-il déprécié à l’avenir ?
À partir de MySQL 8.0, FIND_IN_SET n’est pas officiellement déprécié. Cependant, les structures de données dénormalisées (colonnes séparées par des virgules) ne sont pas recommandées, de sorte que l’utilisation pratique de cette fonction devrait diminuer avec le temps.
Lors de la refonte de votre base de données, il est idéal d’adopter des structures normalisées ou des conceptions basées sur JSON.
7. Conclusion
Revoir les fonctionnalités et les avantages de FIND_IN_SET
La fonction FIND_IN_SET est extrêmement utile dans MySQL pour rechercher des chaînes séparées par des virgules. Elle est particulièrement utile lorsque vous devez extraire des enregistrements contenant une valeur spécifique au sein d’une seule colonne stockant plusieurs valeurs.
Grâce à sa syntaxe simple, elle permet de vérifier des correspondances de valeurs isolées qui sont difficiles à obtenir avec précision à l’aide des clauses LIKE ou IN. Cette capacité à détecter des éléments distincts dans une liste séparée par des virgules est sa plus grande force.
Considérations importantes lors de son utilisation
En même temps, il existe plusieurs limitations et considérations importantes, il ne faut donc pas en abuser sans réflexion soigneuse :
- Les index ne peuvent pas être utilisés (ce qui peut ralentir les recherches)
- Incompatible avec les valeurs contenant des virgules
- Suppose une structure dénormalisée
- Ne prend en charge que les recherches à valeur unique (les recherches multiples nécessitent des conditions
OR)
Comprendre ces caractéristiques est essentiel pour utiliser la fonction de manière appropriée.
Quand vous devez — et ne devez pas — l’utiliser
| Situation | Should You Use It? | Reason |
|---|---|---|
| Small dataset, infrequent searches | ✅ Yes | Easy to implement and low development cost |
| Dependent on a legacy system structure | ✅ Use selectively | Useful when refactoring is difficult |
| Large dataset, high-frequency access | ❌ Not recommended | Performance degradation becomes significant |
| Schema can be normalized | ❌ Avoid | JOINs or intermediate tables are more efficient |
Comment appliquer cela en pratique
- Le considérer comme un outil flexible pour travailler au sein des structures de bases de données existantes
- L’utiliser comme point de référence lors de la décision d’adopter une conception de données normalisée à l’avenir
- Plutôt que de l’employer comme une solution rapide, comprendre clairement ce que fait réellement la fonction
Pour les développeurs qui privilégient la maintenabilité et la lisibilité, il est préférable de considérer cela comme une fonction que vous pouvez « utiliser temporairement—mais dont vous finirez par vous détacher ».


