¿Cómo? Parámetros y sentencia LIKE SQL

80

Estoy escribiendo una función de búsqueda y he pensado en esta consulta utilizando parámetros para prevenir, o al menos limitar, ataques de inyección SQL. Sin embargo, cuando lo ejecuto a través de mi programa, no devuelve nada:

SELECT * FROM compliance_corner WHERE (body LIKE '%@query%') OR (title LIKE '%@query%')

¿Se pueden usar los parámetros de esta manera? o solo son válidos en una instancia como:

SELECT * FROM compliance_corner WHERE body LIKE '%<string>%'(donde <string>está el objeto de búsqueda).

EDITAR: Estoy construyendo esta función con VB.NET, ¿eso tiene un impacto en la sintaxis que ustedes han contribuido?

Además, ejecuté esta declaración en SQL Server: SELECT * FROM compliance_corner WHERE (body LIKE '%max%') OR (title LIKE % max% ') `y eso devuelve resultados.

Anders
fuente

Respuestas:

78

Su código visual básico se vería así:

Dim cmd as New SqlCommand("SELECT * FROM compliance_corner WHERE (body LIKE '%' + @query + '%') OR (title LIKE '%' + @query + '%')")

cmd.Parameters.Add("@query", searchString)
John
fuente
3
Como Adam ha señalado en su respuesta, esto no protege contra la inyección de SQL. La consulta debe estar parametrizada.
DOK
6
¿Podría proporcionar un ejemplo en el que esto no evite la inyección de SQL? Según mis pruebas, funciona bien
John
27
No está abierto a SQLinyecciones, solo LIKEinyecciones. Esto significa que el usuario puede ingresar caracteres especiales como % ^y _que LIKEinterpretará especialmente. Esto significa que es posible que el usuario no obtenga lo que espera de determinadas búsquedas. Por ejemplo, una búsqueda de 'less than 1% fat'puede devolver el resultado 'less than 1% of doctors recommend this - it's full of fat!'.
Alex Humphrey
1
Estoy de acuerdo, los me gusta están sujetos a la "inyección de me gusta" y que el daño es solo que el usuario no obtiene lo que espera. El saneamiento de consultas debe realizarse en todo momento incluso cuando esté parametrizado. Confiar solo en esa protección no es exactamente seguro.
Anthony Mason
1
También recomendaría hacerlo searchString.Replace("[","[[]").Replace("%","[%]").Replace("_","[_]"), lo que permitirá la inyección LIKE (siempre que no esté usando la cláusula de escape).
8DX
114

Bueno, iría con:

 Dim cmd as New SqlCommand(
 "SELECT * FROM compliance_corner"_
  + " WHERE (body LIKE @query )"_ 
  + " OR (title LIKE @query)")

 cmd.Parameters.Add("@query", "%" +searchString +"%")
James Curran
fuente
Esto es correcto, ¡la respuesta aceptada proporcionada por John tiene la sintaxis incorrecta!
Adam
3
No estoy seguro de cómo su sintaxis es incorrecta, su solución funcionó bien. Tengo una función que construye y devuelve una declaración SQL para usar en una tabla de datos o cualquier otra cosa.
Anders
1
Nota adicional: Sintaxis para C # usando MySQLDataAdapter = da = new MySQLDataAdapter ("SELECT * FROM tableA WHERE fieldA = @fieldA"); da.SelectCommand.Parameters.AddWithValue ("@ fieldA", "%" + someValue + "%");
John M
3
La otra respuesta (de John) también funciona, pero de hecho es vulnerable a una inyección similar, que PODRÍA dar resultados extraños, dependiendo del propósito de su campo.
Steven Lemmens
1
¿No debería ser el se cmd.Parameters.Addconvierte cmdLoad.Parameters.AddWithValueo hay algún problema? Entiendo que la respuesta de James es de 2008 :)
WTFZane
26

tu tienes que hacer:

LIKE '%' + @param + '%'

Andrew Bullock
fuente
excelente solución - ¡le daría más de +1 si fuera posible! Gracias
BM
2

Puede que tenga que concatenar los signos% con su parámetro, por ejemplo:

COMO '%' || @query || '%'

Editar: En realidad, eso puede no tener ningún sentido en absoluto. Creo que he entendido mal tu problema.

Will Wagner
fuente
1

A veces, el símbolo utilizado como marcador de posición %no es el mismo si ejecuta una consulta desde VB que cuando la ejecuta desde MS SQL / Access. Intente cambiar su símbolo de marcador de posición de %a *. Aquello podría funcionar.
Sin embargo, si depura y desea copiar su cadena SQL directamente en MS SQL o Access para probarla, es posible que deba volver a cambiar el símbolo a% MS SQL o Access para devolver valores.

Espero que esto ayude

Lalie
fuente
No lo sé con certeza en 2012, pero este% vs * es específico de los motores ADO vs DAO. Si está utilizando DAO o Current () en Access, el comodín es *; si usa ADO desde cualquier código, incluido VBA dentro de Access, el comodín es%.
Marcelo Scofano Diniz
1

prueba también de esta manera

Dim cmd as New SqlCommand("SELECT * FROM compliance_corner WHERE (body LIKE CONCAT('%',@query,'%')  OR  title LIKE CONCAT('%',@query,'%') )")
cmd.Parameters.Add("@query", searchString)
cmd.ExecuteNonQuery()

Usó Concat en lugar de +

Ramgy Borja
fuente