Die Verwendung von SqlParameter in der SQL LIKE-Klausel funktioniert nicht

74

Ich habe folgenden Code:

const string Sql = 
    @"select distinct [name] 
      from tblCustomers 
      left outer join tblCustomerInfo on tblCustomers.Id = tblCustomerInfo.CustomerId  
      where (tblCustomer.Name LIKE '%@SEARCH%' OR tblCustomerInfo.Info LIKE '%@SEARCH%');";

using (var command = new SqlCommand(Sql, Connection))
{       
    command.Parameters.AddWithValue("@SEARCH", searchString);
    ...
}

Das funktioniert nicht, ich habe es auch versucht:

const string Sql = 
    @"select distinct [name] 
     from tblCustomers 
     left outer join tblCustomerInfo on tblCustomers.Id = tblCustomerInfo.CustomerId  
     where (tblCustomer.Name LIKE @SEARCH OR tblCustomerInfo.Info LIKE @SEARCH );";

using (var command = new SqlCommand(Sql, Connection))
{       
    command.Parameters.AddWithValue("@SEARCH", "'%" + searchString + "%'");
    ...
}

aber das funktioniert nicht so gut. Was läuft falsch? Irgendwelche Vorschläge?

nmdr
quelle

Antworten:

150

Was Sie wollen ist:

tblCustomerInfo.Info LIKE '%' + @SEARCH + '%'

(oder bearbeiten Sie den Parameterwert, um das% an erster Stelle einzuschließen).

Andernfalls suchen Sie entweder (erstes Beispiel) nach dem Literal "@SEARCH" (nicht nach dem Argumentwert) oder Sie binden einige zusätzliche Anführungszeichen in die Abfrage ein (zweites Beispiel).

In mancher Hinsicht ist es möglicherweise einfacher, die TSQL nur zu verwenden LIKE @SEARCHund beim Aufrufer zu handhaben:

command.Parameters.AddWithValue("@SEARCH","%" + searchString + "%");

Jeder Ansatz sollte funktionieren.

Marc Gravell
quelle
2
command.Parameters.AddWithValue ("@ SEARCH", "%" + searchString + "%"); Arbeitete, die zusätzlichen einfachen Anführungszeichen waren das Problem, auf das Sie hingewiesen haben
nmdr
1
Den zweiten Weg zu gehen, sieht für mich besser aus, weil die endgültige Aussage in der Tat ordentlich aussehen wird.
Javid
12
Dies funktioniert nicht richtig, wenn der searchString die Zeichen enthält % _oder [wenn Sie tatsächlich nach einem dieser Zeichenliterale suchen möchten. Für eine 100% ige Lösung müssen Sie diese Zeichen in Klammern in den searchString einschließen []. Der C # -Code Regex.Replace(searchString, @"([%_\[])", @"[$1]")macht den Trick.
Matt Miller
@MattMiller wird searchString nur in eckige Klammern setzen, command.Parameters.AddWithValue("@SEARCH","%[" + searchString + "]%"); anstatt dass der reguläre Ausdruck nicht funktioniert?
Thabiso Mofokeng
1
@ThabisoMofokeng Nein, die Klammern sind nicht wie Anführungszeichen (es sei denn, sie enthalten ein einzelnes Zeichen). Was die Klammern in einem SQL LIKE tun, ist, ihm mitzuteilen, dass er mit einem beliebigen Zeichen darin übereinstimmen soll. So stimmt beispielsweise 'a [123] z' mit 'a1z', 'a2z' und 'a3z' überein, nicht jedoch mit 'a12z', da der Ausdruck in Klammern steht Entspricht nur einem Zeichen. Mein Vorschlag, einen regulären Ausdruck zu verwenden, um jedes der Sonderzeichen in Klammern zu setzen, zwingt das LIKE, diese Zeichen buchstäblich zuzuordnen.
Matt Miller
7

Anstatt zu verwenden:

const string Sql = 
@"select distinct [name] 
  from tblCustomers 
  left outer join tblCustomerInfo on tblCustomers.Id = tblCustomerInfo.CustomerId  
  where (tblCustomer.Name LIKE '%@SEARCH%' OR tblCustomerInfo.Info LIKE '%@SEARCH%');";

Verwenden Sie diesen Code:

const string Sql = 
@"select distinct [name] 
  from tblCustomers 
  left outer join tblCustomerInfo on tblCustomers.Id = tblCustomerInfo.CustomerId  
  where (tblCustomer.Name LIKE '%' + @SEARCH + '%' OR tblCustomerInfo.Info LIKE '%' + @SEARCH + '%');";
Ali Almasian
quelle
4
Das macht für mich keinen Sinn, aber es funktioniert. Können Sie erklären, warum?
Timothy
(@ muss in Kommentaren maskiert werden) Der Parameter @SEARCH wird in einen SQL-Varchar umgewandelt und dann mit% chars verkettet und schließlich mit der LIKE-Anweisung verglichen. Zum Beispiel wird aus \ @SEARCH der Wert "Joan": tblCustomer.Name LIKE '%' + 'Joan' + '%', beachten Sie, dass 'Joan' hier vollständig maskiert ist, -> tblCustomer.Name LIKE '% Joan% '. Wenn der Suchparameter unerwartete Zeichen enthalten würde (% oder ', würden sie mit \ @SEARCH = "% Ji'm" maskiert. TblCustomer.Name LIKE'% '+' [%] Ji''m '+' % '. =>'% [%] Ji''m% '(% wird durch eckige Klammern und ein einfaches Anführungszeichen durch Verdoppeln entkommen).
Noman_1
4

Nur ein wenig vorsichtig mit einem kleinen Unterschied zwischen den Methoden Add und AddWithValue . Ich hatte das folgende Problem, als ich die Add- Methode verwendete und den falschen SqlType- Parameter einfügte .

  • ncharund nvarcharkann Unicode- Zeichen speichern .
  • charund kann keine Unicode- Zeichen speichern .varchar

Zum Beispiel:

string query = " ... WHERE stLogin LIKE @LOGIN ";

SqlParameter p = new SqlParameter("@LOGIN", SqlDbType.Char, 255) 
{ 
    Value = "%" + login + "%" 
};

command.Parameters.AddWithValue(p.ParameterName, p.Value); //works fine!!!

command.Parameters.Add(p); // won't work

Als ich den SqlType in NVarChar geändert habe , haben die beiden Methoden für mich gut funktioniert.

SqlParameter p = new SqlParameter("@LOGIN", SqlDbType.NVarChar, 255) 
{ 
    Value = "%" + login + "%" 
};

command.Parameters.AddWithValue(p.ParameterName, p.Value); //worked fine!!!

command.Parameters.Add(p); //worked fine!!!
LeoFraietta
quelle
Ich denke, der Grund, warum das erste Beispiel nicht wie erwartet funktioniert hat, ist, dass Sie den Spaltentyp angegeben haben. Wenn Sie den Konstruktor verwenden, der den Parameternamen und den Wert verwendet, sollte er wie erwartet funktionieren. Mit Blick auf den Quellcode von AddWithValue rufen sie lediglich den Konstruktor auf, der den Parameternamen und den Wert annimmt. also: p = neuer SqlParameter ("@ LOGIN", "%" + login + "%"); command.Parameters.Add (p);
Heriberto Lugo
-7

Sie könnten es tun LIKE @SEARCHund in Ihrem C # -Code tun

searchString = "%" + searchString + "%"
Charles Graham
quelle
6
Wäre dies nicht eine Gelegenheit für eine SQL-Injektion?
Ben Pretorius
2
Ja es würde. Oder wahrscheinlich wird jemand nach einer Zeichenfolge suchen, die ein Zeichen enthält, und sie wird explodieren. Mach das nicht.
Taran