Sélection avec IN

biggief
Invité n'ayant pas de compte PHPfrance

23 nov. 2006, 11:33

Bonjour,

Ma base de données MySql est alimentée par diverses sources dont je n'ai pas forcement le contrôle. Résultat des courses, pour certaines informations qui s'y trouvent, j'ai des caractères invisibles (ou spéciaux - j'ai du mal à les identifier) qui viennent fausser mes résultats de requête.

Je vous explique : je fais un SELECT sur une liste d'emails (via un IN).

ex : SELECT * FROM inscrit WHERE email IN ('[email protected]','[email protected]','[email protected]','[email protected]')

Ma requête va par exemple me sortir les résultat pour email1, email2 et email3, mais rien pour [email protected]

Pour vérifier je fais un SELECT sur email='[email protected]' et en effet je n'ai rien. Par contre si je fais email LIKE '%[email protected]%', là j'ai des résultats.

Dans mon PHPMyAdmin, la valeur apparaît bien sous [email protected]. J'ai donc l'impression qu'il y a des caractères spéciaux invisibles qui l'entourent.

Le problème est que je suis obligé de passer par un IN car je dois pouvoir traiter un grand nombre d'emails.

J'aimerais donc savoir de quelle alternative je dispose (l'idéal serait un mix entre IN et LIKE). Auriez-vous une solution à me proposer.

Pour info ma donnée email est un varchar(255)

Merci d'avance

Mammouth du PHP | 19672 Messages

23 nov. 2006, 11:40

Il suffirait qu'il y ait un espace avant ou après l'adresse pour fausser les résultats. Donc, le plus simple, c'est au moment de l'insertion des données qu'il faut les traiter avec par exemple trim() qui va supprimer les espaces de début et de fin de la chaine.
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Invité
Invité n'ayant pas de compte PHPfrance

23 nov. 2006, 16:42

Malheureusement, comme j'expliquais dans mon message ma base "est alimentée par diverses sources dont je n'ai pas forcement le contrôle".

Pour ma part, les données que j'insère sont "propres". Mais ce n'est pas systématiquement le cas pour les autres...

C'est pour ça que j'ai besoin plus d'une solution au niveau de ma sélection et que de mon insertion.

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

23 nov. 2006, 17:13

J'ai bien peur que tu ne trouves pas de solution au niveau de SELECT. Tu peux toujours essayer de corriger tes données en effaçant les espaces en début et fin de chaîne avec ça:

Code : Tout sélectionner

UPDATE inscrit SET email = TRIM(email)
...mais s'il y a d'autres caractères il faudra les enlever également. Si tu ne peux en aucun cas contrôler les données entrantes, il te faut impérativement trouver un moyen de les corriger et il faut donc commencer par identifier le type de "corruption". (quels caractères en trop par exemple)

ViPHP
ViPHP | 1961 Messages

23 nov. 2006, 17:29

Bonjour,

Une solution, pas très élégante, certes

Code : Tout sélectionner

SELECT * FROM inscrit WHERE email LIKE '%[email protected]%' OR email LIKE '%[email protected]%' OR email LIKE '%[email protected]%' OR email LIKE '%[email protected]%';
Deux choses sont infinies, l'Univers et la sottise humaine!!
Mais je ne suis pas sur de ce que j'affirme au sujet de l'Univers.

A. Einstein

Invité
Invité n'ayant pas de compte PHPfrance

24 nov. 2006, 12:27

J'ai identifié les caractères superflues. Il s'agit de \r\n.

Du coup j'ai réadapté ma requête comme ceci :

SELECT * FROM inscrit WHERE REPLACE(email,'\r\n','') IN ('[email protected]','[email protected]','[email protected]','[email protected]')

Il semblerait que cela fonctionne.

Que pensez-vous de cette solution ?

ViPHP
ViPHP | 1961 Messages

24 nov. 2006, 12:37

Bonjour,

Elle peut être viable, personnellement, je couplerais ta solution avec celle proposée par Hubert Roksor

A condition d'être sur que ce sont ces caractères, et seulement ceux là qui te posent PB.
Deux choses sont infinies, l'Univers et la sottise humaine!!
Mais je ne suis pas sur de ce que j'affirme au sujet de l'Univers.

A. Einstein

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

24 nov. 2006, 15:56

Que pensez-vous de cette solution ?
En utilisant une fonction au moment du SELECT, tu as la garantie que les performance se dégraderont au fur et à mesure que la table grossira. Un jour, quelqu'un aura à réparer tes requêtes SELECT et les requêtes INSERT des autres...

Si tu utilisais MySQL 5, tu pourrais utiliser un TRIGGER BEFORE INSERT (et BEFORE UPDATE) pour corriger les données qui entrent dans la base de données. Après ça, c'est comme le loup dans la bergerie, une fois entré vous pouvez toujours donner des kevlar aux moutons il y aura un jour où un drame arrivera.

Invité
Invité n'ayant pas de compte PHPfrance

24 nov. 2006, 17:22

Bon, au final, j'ai nettoyé toute ma base en faisant un update sur les infos email.

Le TRIM ne m'apportant pas les résultats escomptés, j'ai fait un REPLACE(email,'\r\n','')

Merci à tous pour votre aide.