La chaîne de requête MySQL contient

307

J'ai essayé de comprendre comment je peux faire une requête avec MySQL qui vérifie si la valeur (chaîne $haystack) dans une certaine colonne contient certaines données (chaîne $needle), comme ceci:

mysql_query("
SELECT *
FROM `table`
WHERE `column`.contains('{$needle}')
");

En PHP, la fonction est appelée substr($haystack, $needle), alors peut-être:

WHERE substr(`column`, '{$needle}')=1
arik
la source

Réponses:

437

Assez simple en fait:

mysql_query("
SELECT *
FROM `table`
WHERE `column` LIKE '%{$needle}%'
");

Le %est un caractère générique pour n'importe quel jeu de caractères (aucun, un ou plusieurs). Notez que cela peut devenir lent sur de très grands ensembles de données, donc si votre base de données grandit, vous devrez utiliser des indices de texte intégral.

Wolph
la source
1
Cela ne fonctionnera que si vous utilisez une requête préparée. Si vous utilisez une chaîne réelle (par exemple, un script de mise à niveau sql liquibase), considérez INSTR comme mentionné ci-dessous). En effet, si votre chaîne contient un%, vous commencerez à faire correspondre les choses avec.
Ryan Shillington
2
je connais des requêtes similaires, et pourtant aujourd'hui je voulais savoir si une certaine valeur existe dans une chaîne dans une colonne, je cherchais pour ça .. Pourquoi je n'y avais jamais pensé avant ??
Code grésillant du
1
cette casse est-elle sensible?
kiwi en colère
2
@angry_kiwi: avec column LIKE '...'elle est insensible à la casse, avec column LIKE BINARY '...'elle est sensible à la casse
Wolph
2
Je suis surpris qu'il LIKEsoit proposé de vérifier toute sous-chaîne car cet opérateur utilise deux caractères génériques: %et _. Cela signifie que si votre chaîne $ needle contient l'un de ces caractères spéciaux, le résultat n'est pas du tout attendu. (-1) pour cette réponse et (+1) pour la réponse INSTR.
Skrol29
144

Utilisation:

SELECT *
  FROM `table`
 WHERE INSTR(`column`, '{$needle}') > 0

Référence:

Poneys OMG
la source
LIKE est sûrement plus rapide que INSTR?
chris
17
@oedo: Ça dépend. LIKE %...%n'utilisera pas d'index s'il en existe un, ils devraient donc être équivalents; LIKE ...%utiliserait un index s'il était présent. Si les performances sont un réel problème, la recherche en texte intégral (FTS) serait une meilleure approche.
OMG Ponies
parfait. juste ce que je cherchais.
arik
2
J'aime cette solution car en fait il n'y a aucun moyen de trier les choses en fonction de la présence d'une sous-chaîne avec likeopérateur. Avec instrune phrase peut être commandée comme ceciselect * from table order by instr(col1,"mystring")
Radacina
Je voulais rechercher _ dans un champ et cela a fonctionné. Merci
Safeer Ahmed
53
WHERE `column` LIKE '%$needle%'
chris
la source
2
lors de la recherche du caractère _ (souligné), la requête LIKE '% _%' ne fonctionne pas, pour une raison quelconque, elle renvoie toutes les chaînes même sans _
Wojtek
1
@Wojtek _ est un caractère générique pour n'importe quel caractère, donc si vous voulez rechercher un trait de soulignement littéral, vous devrez l'échapper. Voir Requête LIKE MySQL avec trait de soulignement .
jkmartindale
29

Le mien utilise LOCATEdans mysql:

LOCATE (substr, str), LOCATE (substr, str, pos)

Cette fonction est sûre sur plusieurs octets et ne respecte la casse que si au moins un argument est une chaîne binaire.

Dans ton cas:

mysql_query("
SELECT * FROM `table`
WHERE LOCATE('{$needle}','column') > 0
");
risnandar
la source
11
'colonne' doit être une colonne (sans guillemets)
Wojtek
10

En plus de la réponse de @WoLpH.

Lorsque vous utilisez le LIKEmot - clé, vous avez également la possibilité de limiter la direction dans laquelle la chaîne correspond. Par exemple:

Si vous cherchiez une chaîne commençant par votre $needle:

... WHERE column LIKE '{$needle}%'

Si vous cherchiez une chaîne qui se termine par $needle:

... WHERE column LIKE '%{$needle}'
Joshua Powell
la source
3

sachez que cela est dangereux:

WHERE `column` LIKE '%{$needle}%'

faire en premier:

$needle = mysql_real_escape_string($needle);

il empêchera ainsi d'éventuelles attaques.

Alejandro Moreno
la source
7
* Quelques attaques possibles. En outre, mysql_real_escape_stringva être obsolète dans les futures versions de PHP.
Jack Tuck
11
Vous devez utiliser des instructions préparées et laisser l'échappement à PHP. $stmt = $dbh->prepare("Where 'column' LIKE '{:needle}'"); $stmt->bindParam(':needle', $needle); $stmt->execute();
cloudworks
3

Vous recherchez probablement une find_in_setfonction:

Where find_in_set($needle,'column') > 0

Cette fonction agit comme une in_arrayfonction en PHP

Andres
la source