Wie man? Parameter und LIKE-Anweisung SQL

80

Ich schreibe eine Suchfunktion und habe mir diese Abfrage mit Parametern ausgedacht, um SQL-Injection-Angriffe zu verhindern oder zumindest einzuschränken. Wenn ich es jedoch über mein Programm ausführe, wird nichts zurückgegeben:

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

Können Parameter so verwendet werden? oder sind sie nur in einer Instanz gültig wie:

SELECT * FROM compliance_corner WHERE body LIKE '%<string>%'(Wo <string>ist das Suchobjekt).

EDIT: Ich konstruiere diese Funktion mit VB.NET. Hat das Auswirkungen auf die Syntax, die ihr beigetragen habt?

Außerdem habe ich diese Anweisung in SQL Server ausgeführt: SELECT * FROM compliance_corner WHERE (body LIKE '%max%') OR (title LIKE% max% ') `und das gibt Ergebnisse zurück.

Anders
quelle

Antworten:

78

Ihr visueller Basiscode würde ungefähr so ​​aussehen:

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

cmd.Parameters.Add("@query", searchString)
John
quelle
3
Wie Adam in seiner Antwort ausgeführt hat, schützt dies nicht vor SQL-Injection. Die Abfrage sollte parametrisiert werden.
DOK
6
Können Sie ein Beispiel nennen, in dem dies nicht gegen SQL-Injection verhindert? Von meinen Tests funktioniert es gut
John
27
Es ist nicht offen für SQLInjektionen, nur LIKEInjektionen. Dies bedeutet , dass die Benutzer Sonderzeichen eingeben können, wie % ^und _welche LIKEspeziell interpretiert. Dies bedeutet, dass der Benutzer möglicherweise nicht das erhält, was er für bestimmte Suchvorgänge erwartet. Beispielsweise kann eine Suche nach 'less than 1% fat'das Ergebnis zurückgeben 'less than 1% of doctors recommend this - it's full of fat!'.
Alex Humphrey
1
Ich bin damit einverstanden, dass dergleichen "Like Injection" unterliegt und dass der Schaden nur darin besteht, dass der Benutzer nicht das bekommt, was er erwartet. Die Abfragebereinigung sollte jederzeit durchgeführt werden, auch wenn sie parametrisiert ist. Sich auf diesen Schutz allein zu verlassen, ist nicht gerade sicher.
Anthony Mason
1
Ich würde auch empfehlen, dies zu tun searchString.Replace("[","[[]").Replace("%","[%]").Replace("_","[_]"), wodurch eine ähnliche Injektion vermieden wird (solange Sie die Escape-Klausel nicht verwenden).
8DX
114

Nun, ich würde gehen mit:

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

 cmd.Parameters.Add("@query", "%" +searchString +"%")
James Curran
quelle
Dies ist richtig, die akzeptierte Antwort von John hat die falsche Syntax!
Adam
3
Ich bin mir nicht sicher, wie seine Syntax falsch ist, seine Lösung hat gut funktioniert. Ich habe eine Funktion, die eine SQL-Anweisung zur Verwendung in einer Datentabelle oder was auch immer erstellt und zurückgibt.
Anders
1
Zusätzlicher Hinweis: Syntax für C # unter Verwendung von MySQLDataAdapter = da = new MySQLDataAdapter ("SELECT * FROM tableA WHERE fieldA = @fieldA"); da.SelectCommand.Parameters.AddWithValue ("@ fieldA", "%" + someValue + "%");
John M
3
Die andere Antwort (von John) funktioniert ebenfalls, ist aber in der Tat anfällig für Injektionen, die je nach Zweck Ihres Fachgebiets seltsame Ergebnisse liefern können.
Steven Lemmens
1
Sollte nicht das cmd.Parameters.Addwird cmdLoad.Parameters.AddWithValueoder ist es eine Frage? Ich verstehe, dass James Antwort von 2008 ist :)
WTFZane
26

du musst:

LIKE '%' + @param + '%'

Andrew Bullock
quelle
ausgezeichnete Lösung - würde es mehr als +1 geben, wenn möglich! Vielen Dank
BM
2

Möglicherweise müssen Sie die% -Zeichen mit Ihrem Parameter verketten, z.

WIE '%' || @query || '%'

Edit: Eigentlich macht das vielleicht überhaupt keinen Sinn. Ich glaube, ich habe Ihr Problem möglicherweise falsch verstanden.

Will Wagner
quelle
1

Manchmal ist das als Platzhalter verwendete Symbol %nicht dasselbe, wenn Sie eine Abfrage von VB ausführen, wie wenn Sie sie von MS SQL / Access ausführen. Versuchen Sie, Ihr Platzhaltersymbol von auf %zu ändern *. Das könnte funktionieren.
Wenn Sie jedoch debuggen und Ihre SQL-Zeichenfolge direkt in MS SQL oder Access kopieren möchten, um sie zu testen, müssen Sie das Symbol möglicherweise wieder %in MS SQL oder Access ändern , um tatsächlich Werte zurückzugeben.

Hoffe das hilft

Lalie
quelle
Ich weiß es 2012 nicht genau, aber dieses% vs * ist spezifisch für ADO vs DAO-Engines. Wenn Sie DAO oder Current () in Access verwenden, lautet der Platzhalter *; Wenn Sie ADO aus einem beliebigen Code verwenden, einschließlich VBA in Access, lautet der Platzhalter%.
Marcelo Scofano
0

versuche es auch so

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()

Verwendet Concat anstelle von +

Ramgy Borja
quelle