Uso de comodines "me gusta" en la declaración preparada


176

Estoy usando declaraciones preparadas para ejecutar consultas de bases de datos mysql. Y quiero implementar una funcionalidad de búsqueda basada en una especie de palabra clave.

Para eso necesito usar LIKEpalabras clave, eso lo sé. Y también he usado declaraciones preparadas antes, pero no sé cómo usarlo LIKEporque, desde el siguiente código, ¿dónde agregaría el 'keyword%'?

¿Puedo usarlo directamente en el pstmt.setString(1, notes)as (1, notes+"%")o algo así? Veo muchas publicaciones sobre esto en la web, pero no hay una buena respuesta en ningún lado.

PreparedStatement pstmt = con.prepareStatement(
      "SELECT * FROM analysis WHERE notes like ?");
pstmt.setString(1, notes);
ResultSet rs = pstmt.executeQuery();

Respuestas:


281

Debe establecerlo en el valor en sí, no en la cadena SQL de la declaración preparada.

Entonces, esto debería hacer para una coincidencia de prefijo:

notes = notes
    .replace("!", "!!")
    .replace("%", "!%")
    .replace("_", "!_")
    .replace("[", "![");
PreparedStatement pstmt = con.prepareStatement(
        "SELECT * FROM analysis WHERE notes LIKE ? ESCAPE '!'");
pstmt.setString(1, notes + "%");

o una coincidencia de sufijo:

pstmt.setString(1, "%" + notes);

o una coincidencia global:

pstmt.setString(1, "%" + notes + "%");

18
+1 El OP podría "configurarlo" en el SQL, como por ... LIKE '%' || ? || '%'o similar, pero eso es mucho menos flexible.
Pilcrow

¿Cómo lo hago con el modo SENSIBLE NO EN CASO? :)
Alpha Gabriel V. Timbol

2
Todavía no se distingue entre mayúsculas y minúsculas WHERE UPPER(?) LIKE UPPER(?)cuando se usapstmt.setString(2, "%" + notes + "%")
Zig

1
@Alain: Gracias. Me pregunto si esto se aplica a todos los RDBMS que el mundo conoce. ¿Tal vez '%' || ? || '%'como se menciona en el primer comentario fue mejor, después de todo? No tengo la oportunidad de experimentar en este momento.
BalusC

2
@BalusC esto se aplica a MSSQL, Postgres y MySQL en mis pruebas. La cadena que se convierte en un parámetro se interpreta como una combinación de datos e instrucciones de control. La concatenación SQL ocurre antes de que se interprete y preserva la vulnerabilidad. El IEEE Center for Secure Design dice que separe estrictamente los datos y las instrucciones de control, y nunca procese las instrucciones de control recibidas de fuentes no confiables .
Alain O'Dea

28

Codifícalo así:

PreparedStatement pstmt = con.prepareStatement(
    "SELECT * FROM analysis WHERE notes like ?");
pstmt.setString(1, notes + "%");`

Asegúrese de NO incluir las citas '' como se muestra a continuación, ya que causarán una excepción.

pstmt.setString(1,"'%"+ notes + "%'");

1
Aunque parece que alguien no se encontrará con esta suposición, en realidad es muy válida, especialmente cuando se trabaja con Oracle. Gracias por señalar!
pide el

5

podemos hacer esto de manera simple, usando la función CONCATE SQL.

PreparedStatement pstmt = con.prepareStatement(
      "SELECT * FROM analysis WHERE notes like CONCAT( '%',?,'%')";
pstmt.setString(1, notes);
ResultSet rs = pstmt.executeQuery();

Este es un trabajo perfecto para mi caso.


4
PreparedStatement ps = cn.prepareStatement("Select * from Users where User_FirstName LIKE ?");
ps.setString(1, name + '%');

Probar esto.


1
String fname = "Sam\u0025";

PreparedStatement ps= conn.prepareStatement("SELECT * FROM Users WHERE User_FirstName LIKE ? ");

ps.setString(1, fname);

2
¿Podría elaborar la respuesta en lugar de simplemente dar la respuesta? Ver: stackoverflow.com/help/how-to-answer
Edwin

-13
String query="select * from test1 where "+selected+" like '%"+SelectedStr+"%';";


PreparedStatement preparedStatement=con.prepareStatement(query);


// where seleced and SelectedStr are String Variables in my program

no es seguro, utilice amablemente la declaración preparada parametrizada.
Durgesh Kumar el
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.