Pourquoi «_» (trait de soulignement) correspond-il à «-» (trait d'union)?

110

Je dois chercher un manuel PDF en utilisant cette requête:

root@localhost:test> select * from a where name like '%taz_manual%.pdf%';
+--------------------+------------------+-------------+
| name               | description      |        size | 
+--------------------+------------------+-------------+
| taz-manual-1.1.pdf | Manual v1.0 TA-Z |    31351902 |
| taz-manual-0.2.pdf | Manual v1.0 T1-A |     3578278 |
| taz_manual-2.0.pdf | Manual v2.0 GA-X |   542578278 |
etc........
+--------------------+------------------+-------------+
132 row in set (0.00 sec)

Pourquoi est-ce que je vois celui avec des tirets lorsque je spécifie le nom à être taz_manual%.pdf?

PAR EXEMPLE
la source

Réponses:

231

Parce que le trait de soulignement _est un caractère générique comme le pourcentage %, sauf qu'il ne recherche qu'un seul caractère.

La correspondance de modèle SQL vous permet d'utiliser "_" pour faire correspondre n'importe quel caractère unique et "%" pour correspondre à un nombre arbitraire de caractères (y compris zéro caractère).

(De la section 3.3.4.7. Pattern Matching dans la documentation MySQL.)

Si vous souhaitez utiliser le trait de soulignement likecomme littéral, vous devez l'échapper:

select * from a where name like '%taz\_manual%.pdf%';
Livre de Zeus
la source
afaik cela n'est pertinent que lorsque vous êtes dans un contexte de modèle. par exemple à l'intérieur d'une LIKEdéclaration. Lors du remplacement de tous _avec -: UPDATE sys_file set identifier = REPLACE(identifier, '_', '-') WHERE identifier LIKE '%\_%';. Remarquez la fuite à l'intérieur LIKEet aucune fuite à l'intérieur REPLACE. (Je trouve étrange cependant que vous ne soyez pas dans un contexte de modèle à l'intérieur de replace ...)
Hafenkranich
@Hafenkranich du doc ​​mysql: "utiliser les opérateurs de comparaison LIKE or NOT LIKE"
Book Of Zeus
2

J'ai eu un problème similaire avec l'espace et les traits d'union lors de la correspondance des chaînes avec une correspondance exacte:

SELECT id FROM location WHERE name = 'IND - HQ';

La requête ci-dessus n'a renvoyé aucun enregistrement dans MySQL. J'ai dû échapper aux espaces et aux traits d'union et utiliser LIKEau lieu de la correspondance exacte avec égal (=) comme suit:

SELECT id FROM location WHERE name LIKE 'IND_\-_HQ';
NBhat
la source
Êtes-vous sûr que cela est lié? Peut-être qu'il n'y avait pas de ligne d'emplacement avec ce nom exact ... ???
Nico Haase
oui, il y avait des lignes avec location = 'IND - HQ' et ce qui précède a
résolu
Et vous le savez parce que vous avez posé la question à la personne qui avait cette question cinq ans avant de publier votre réponse?
Nico Haase