¿Cómo creo una consulta parametrizada PDO con una declaración LIKE?

107

Aquí está mi intento de hacerlo:

$query = $database->prepare('SELECT * FROM table WHERE column LIKE "?%"');

$query->execute(array('value'));

while ($results = $query->fetch()) 
{
    echo $results['column'];
}
Andrew G. Johnson
fuente

Respuestas:

124

Lo descubrí justo después de publicar:

$query = $database->prepare('SELECT * FROM table WHERE column LIKE ?');
$query->execute(array('value%'));

while ($results = $query->fetch())
{
    echo $results['column'];
}
Andrew G. Johnson
fuente
1
@Andrew: ¿y si likese usa múltiple ? ¿Cómo debería ejecutarse la matriz de ejecución en orden?
Logan
Gracias. tuvo un problema similar con csharp + Mysql + ODBC usando como si no devolviera ninguna fila usando "seleccionar * de la tabla donde la columna como '%?%';" pero lo haré si hago como lo hizo "seleccionar * de la tabla donde la columna como?" y establezca la cadena del parámetro así: string frag = $ "% {searchFragment}%"; luego use frag para el valor del parámetro. Extraño
sdjuan
2
PDO debería escapar de ese% en la llamada de ejecución. La respuesta de Kaqai es mejor
Peter Bagnall
Vale la pena señalar que la nota principal aportada por el usuario en la página de documentación de PDOStatement :: bindParam ofrece un enfoque diferente: agregue el (los) signo (s) de porcentaje a la variable antes de vincularla.
Dan Robinson
Eche un vistazo a la solución de Gavin, tomada de la página de Your Common Sense, cerca del final de este hilo. Sencillo. Lógico.
RationalRabbit
85

Para aquellos que usan parámetros con nombre, aquí se explica cómo usar LIKEcon %coincidencia parcial para bases de datos MySQL :

DONDE column_name LIKE CONCAT ('%',: dangerousrousstring, '%')

donde está el parámetro nombrado :dangerousstring.

En otras palabras, use %signos explícitamente sin escape en su propia consulta que estén separados y definitivamente no sean la entrada del usuario.

Editar: la sintaxis de concatenación para bases de datos Oracle usa el operador de concatenación:, ||por lo que simplemente se convertirá en:

DONDE column_name LIKE '%' || : cuerda peligrosa || '%'

Sin embargo, hay advertencias como @bobince menciona aquí que:

La dificultad surge cuando desea permitir un literal %o _carácter en la cadena de búsqueda, sin que actúe como comodín.

Entonces, eso es algo más a tener en cuenta al combinar Me gusta y parametrización.

Kzqai
fuente
6
+1: esto me parece un buen enfoque ya que toda la concatenación ocurre en la base de datos después de que se ha sustituido el marcador de posición, y significa que se pueden usar marcadores de posición con nombre. Vale la pena mencionar que la sintaxis anterior es para Oracle; en MySQL, la sintaxis es LIKE CONCAT('%', :something, '%'). Referencia: stackoverflow.com/a/661207/201648
Aaron Newton
1
Esto no funcionó para mí exactamente, pero me puso en el camino correcto. Tuve que hacer LIKE '%': algo '%' para que funcione.
Christopher Smit
Sé que esto no está relacionado con el tema, pero pude realizar la inyección de SQL incluso usando esta declaración, ¿por qué?
Thiago Dias
Esto no funcionó para mí, también lo probé con el comando SQL, SELECT * FROM calculation WHERE ( email LIKE '%' || luza || '%' OR siteLocation LIKE '%'|| luza ||'%' OR company LIKE '%' ||luza ||'%' )esto me daría un error.
Luzan Baral
@AaronNewton and it means named placeholders can be used. ¿Cómo es incluso un problema con los marcadores de posición con nombre cuando concatenas en PHP? Obviamente, la concatenación en PHP admite tanto el nombre como el posicional y es más portátil, ya que puede usar la misma consulta para cualquier base de datos. Realmente no entiendo por qué tanta gente piensa que existe alguna diferencia entre los marcadores de posición con nombre y posicionales.
Tu sentido común
18
$query = $database->prepare('SELECT * FROM table WHERE column LIKE ?');
$query->bindValue(1, "%$value%", PDO::PARAM_STR);
$query->execute();

if (!$query->rowCount() == 0) 
{
    while ($results = $query->fetch()) 
    {
        echo $results['column'] . "<br />\n";
    }       
} 
else 
{
    echo 'Nothing found';
}
Chaqueta de sport
fuente
1
¿Hay alguna ventaja de usar esto sobre la respuesta aceptada? ¿El uso bindValueprotege contra los ataques de inyección? La respuesta aceptada básicamente niega el valor de usar ?marcadores de posición al concatenar la cadena de búsqueda a Me %gusta en los días de antaño.
Felwithe
¿Cuál es el punto de usar la negación antes de $ query-> rowCount () == 0? ¿Tiene esto realmente sentido?
ssi-anik
14

También puedes probar este. Me enfrento a un problema similar pero obtuve un resultado después de la investigación.

$query = $pdo_connection->prepare('SELECT * FROM table WHERE column LIKE :search');

$stmt= $pdo_connection->prepare($query);

$stmt->execute(array(':search' => '%'.$search_term.'%'));

$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

print_r($result);
Vijaysinh Parmar
fuente
Edité tu publicación para poner el código en un bloque de código; puedes leer más sobre el formato de publicaciones en stackoverflow.com/help/formatting . Otro usuario eligió rechazar su respuesta sin dejar un comentario, por lo que no estoy seguro de la causa del voto negativo.
josliber
2
Repito, no voté sobre su pregunta; alguien más votó en contra.
josliber
3

Esto funciona:

search `table` where `column` like concat('%', :column, '%')
kjdion84
fuente
2

Obtuve esto de php delirios

$search = "%$search%";
$stmt  = $pdo->prepare("SELECT * FROM table WHERE name LIKE ?");
$stmt->execute([$search]);
$data = $stmt->fetchAll();

Y funciona para mí, muy simple. Como él dice, primero debes "preparar nuestro literal completo" antes de enviarlo a la consulta.

Gavin
fuente
0

PDO escapa "%" (puede conducir a una inyección de sql) : el uso del código anterior dará los resultados deseados al buscar coincidencias con cadenas parciales, PERO si un visitante escribe el carácter "%", aún obtendrá resultados incluso si no lo hace t tener algo almacenado en la base de datos (puede dar lugar a inyecciones de sql)

Probé muchas variaciones, todas con el mismo resultado. PDO está escapando "%" de los principales resultados de búsqueda no deseados / no emocionados.

Pensé que valía la pena compartirlo si alguien ha encontrado una palabra al respecto, por favor compártelo

Ozkar R
fuente
1
Esto es del Manual: us3.php.net/manual/en/pdo.prepared-statements.php Esta es otra publicación sobre el tema: stackoverflow.com/questions/22030451/… Realmente me gustaría saber tu opinión sobre este problema.
Ozkar R
1
Posible solución (No probado) Use CONCAT , como: $ sql = “SELECT item_title FROM item WHERE item_title LIKE CONCAT ('%',?, '%')”; Referencia: blog.mclaughlinsoftware.com/2010/02/21/php-binding-a-wildcard
Ozkar R
3
La DOP no escapa al%. Es tu código el que lo hace mal. Para obtener la solución, se supone que debe leer las respuestas ya proporcionadas aquí
su sentido común
Gracias por tus sugerencias. De todos modos, el código probado fue el código del manual, usando un marcador de posición para evitar la inyección de SQL, sigo obteniendo el mismo resultado. Ejemplo # 6 El uso no válido del marcador de posición PDO escapa% usando el código anterior, no mi código. Soy nuevo en el foro y es posible que no entienda cómo funciona el proceso de comentarios, publicaciones y reputación aquí, lo tendré en cuenta para el próximo, porque según el comentario anterior necesitas reputación para ayudar a otros o hacer comentarios. Gracias.
Ozkar R