La cadena de consulta MySQL contiene

307

He estado tratando de descubrir cómo puedo hacer una consulta con MySQL que verifique si el valor (cadena $haystack) en una determinada columna contiene ciertos datos (cadena $needle), como este:

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

En PHP, la función se llama substr($haystack, $needle), así que tal vez:

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

Respuestas:

437

Bastante simple en realidad:

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

El %es un comodín para cualquier conjunto de caracteres (ninguno, uno o muchos). Tenga en cuenta que esto puede ser lento en conjuntos de datos muy grandes, por lo que si su base de datos crece, deberá usar índices de texto completo.

Wolph
fuente
1
Esto solo funcionará si está utilizando una consulta preparada. Si está usando una cadena real allí (por ejemplo, script de actualización de liquibase sql), considere INSTR mencionado a continuación). Esto se debe a que si su cadena contiene un%, comenzará a hacer coincidir las cosas con ella.
Ryan Shillington
2
Sé acerca de consultas similares, y sin embargo, hoy quería saber si existe cierto valor en la cadena en alguna columna que estaba buscando en Google. ¿Por qué nunca pensé en eso antes?
Código chisporroteo
1
¿Es este caso sensible?
Kiwi enojado
2
@angry_kiwi: con column LIKE '...'mayúsculas y minúsculas, con column LIKE BINARY '...'mayúsculas y minúsculas
Wolph
2
Me sorprende que LIKEse proponga verificar cualquier subcadena ya que este operador utiliza dos caracteres comodín: %y _. Esto significa que si su cadena $ needle contiene uno de estos caracteres especiales, los resultados no son los esperados. (-1) para esta respuesta y (+1) para la respuesta INSTR.
Skrol29
144

Utilizar:

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

Referencia:

Ponis OMG
fuente
seguramente LIKE es más rápido que INSTR?
Chris
17
@Oedo: Depende. LIKE %...%no usará un índice si hay uno presente, por lo que deberían ser equivalentes; LIKE ...%usaría un índice si está presente. Si el rendimiento es una preocupación real, la búsqueda de texto completo (FTS) sería un mejor enfoque.
OMG Ponis
Perfecto. Justo lo que estaba buscando.
arik
2
Me gusta esta solución, ya que de hecho no hay forma de ordenar las cosas según la presencia de una subcadena con el likeoperador. Con instruna frase se puede ordenar asíselect * from table order by instr(col1,"mystring")
Radacina
Quería buscar _ en un campo y funcionó. Gracias
Safeer Ahmed
53
WHERE `column` LIKE '%$needle%'
Chris
fuente
2
al buscar el carácter _ (guión bajo) la consulta LIKE '% _%' no funciona, por alguna razón devuelve todas las cadenas incluso sin _
Wojtek
1
@Wojtek _ es un comodín para cualquier carácter individual, por lo que si desea buscar un guión bajo literal, deberá escapar de él. Vea la consulta MySQL LIKE con guión bajo .
jkmartindale
29

El mío está usando LOCATEen mysql:

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

Esta función es segura para varios bytes y distingue entre mayúsculas y minúsculas solo si al menos un argumento es una cadena binaria.

En tu caso:

mysql_query("
SELECT * FROM `table`
WHERE LOCATE('{$needle}','column') > 0
");
risnandar
fuente
11
'column' debe ser column (sin comillas)
Wojtek
10

Además de la respuesta de @WoLpH.

Al usar la LIKEpalabra clave, también tiene la capacidad de limitar en qué dirección coincide la cadena. Por ejemplo:

Si estabas buscando una cadena que comience con tu $needle:

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

Si estabas buscando una cadena que termina con $needle:

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

Tenga en cuenta que esto es peligroso:

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

hacer primero:

$needle = mysql_real_escape_string($needle);

así evitará posibles ataques.

Alejandro Moreno
fuente
77
* Algunos posibles ataques. Además, mysql_real_escape_stringquedará en desuso en futuras versiones de PHP.
Jack Tuck
11
Debe usar declaraciones preparadas y dejar el escape a PHP. $stmt = $dbh->prepare("Where 'column' LIKE '{:needle}'"); $stmt->bindParam(':needle', $needle); $stmt->execute();
cloudworks
3

Probablemente estés buscando la find_in_setfunción:

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

Esta función actúa como in_arrayfunción en PHP

Andres
fuente