参数化动态sql查询

我有一个关键字列表,我存储在列表中。

要从表中获取记录,请使用以下查询:

sqlBuilder.Append("SELECT name, memberid FROM members WHERE"); StringBuilder sqlBuilder = new StringBuilder(); foreach (string item in keywords) { sqlBuilder.AppendFormat(" LOWER(Name) LIKE '%{0}%' AND", item); } string sql = sqlBuilder.ToString(); 

您可能已经注意到,我的查询容易受到sql注入,因此我想使用SqlCommand()来使用参数。 我尝试了以下但仍然无法正常工作:

 foreach (string item in keywords) { sqlBuilder.AppendFormat(" LOWER(Name) LIKE '%' + @searchitem + '%' AND", item); SqlCommand cmd = new SqlCommand(sqlBuilder.ToString()); cmd.Parameters.AddWithValue("@searchitem",item); } 

我在哪里可以犯这个错误,或者更确切地说,我应该怎么做?

你在这里犯了一些错误:

  • 您为所有参数指定了相同的名称@searchitem 。 那不行。 参数需要唯一的名称。
  • 您为每个项目创建一个新的SqlCommand。 那不行。 在循环开始时创建一次 SqlCommand,然后在创建SQL后设置CommandText
  • 您的SQL以AND结尾,这是无效的语法。

改进建议(本身没有错,但也不是最佳做法):

  • 正如Frederik建议的那样,通常的方法是将%标记放在参数中,而不是在SQL中进行字符串连接。
  • 除非您为数据库明确使用区分大小写的排序规则,否则比较应不区分大小写。 因此,您可能不需要LOWER

代码示例:

 SqlCommand cmd = new SqlCommand(); StringBuilder sqlBuilder = new StringBuilder(); sqlBuilder.Append("SELECT name, memberid FROM members "); var i = 1; foreach (string item in keywords) { sqlBuilder.Append(i == 1 ? " WHERE " : " AND "); var paramName = "@searchitem" + i.ToString(); sqlBuilder.AppendFormat(" Name LIKE {0} ", paramName); cmd.Parameters.AddWithValue(paramName, "%" + item + "%"); i++; } cmd.CommandText = sqlBuilder.ToString(); 

不要将通配符放在查询字符串中,而是将它们添加到参数值中:

 sql = "SELECT name FROM members WHERE Name LIKE @p_name"; ... cmd.Parameters.AddWithValue("@p_name", "%" + item + "%"); 

在查询字符串中添加通配符时,参数将被转义,但通配符字符不会; 这将导致发送到DB的查询,如下所示:

 SELECT name FROM members WHERE Name LIKE %'somename'% 

这显然是不正确的。

接下来,您将在循环中创建一个SqlCommand,这是不必要的。 此外,您正在使用非唯一名称创建参数,因为您在循环中添加它们,并且参数始终具有相同的名称。 退出循环时,还需要删除最后一个AND关键字。