使用LIKE和IN条件的参数化查询

.Net中的参数化查询在示例中总是如下所示:

SqlCommand comm = new SqlCommand(@" SELECT * FROM Products WHERE Category_ID = @categoryid ", conn); comm.Parameters.Add("@categoryid", SqlDbType.Int); comm.Parameters["@categoryid"].Value = CategoryID; 

但是我遇到了一堵砖墙,试图做到以下几点:

 SqlCommand comm = new SqlCommand(@" SELECT * FROM Products WHERE Category_ID IN (@categoryids) OR name LIKE '%@name%' ", conn); comm.Parameters.Add("@categoryids", SqlDbType.Int); comm.Parameters["@categoryids"].Value = CategoryIDs; comm.Parameters.Add("@name", SqlDbType.Int); comm.Parameters["@name"].Value = Name; 

哪里

  • CategoryIDs是逗号分隔的数字列表“123,456,789”(不含引号)
  • 名称是一个string,可能带有单引号和其他不好的字符

什么是正确的语法?

假设您的类别ID是一个整型数组,Name是一个string。 诀窍是创build命令文本,允许您input所有的类别ID作为单独的参数,并构build名称的模糊匹配。 为了做前者,我们使用一个循环来构build一个参数名称@ p0到@ pN-1的序列,其中N是数组中的分类id的数量。 然后,我们构造一个参数并将其添加到具有关联的类别id的命令中作为每个命名参数的值。 然后我们在查询本身的名字上使用连接来允许名字上的模糊search。

 string Name = "someone"; int[] categoryIDs = new int[] { 238, 1138, 1615, 1616, 1617, 1618, 1619, 1620, 1951, 1952, 1953, 1954, 1955, 1972, 2022 }; SqlCommand comm = conn.CreateCommand(); string[] parameters = new string[categoryIDs.Length]; for(int i=0;i<categoryIDs.Length;i++) { parameters[i] = "@p"+i; comm.Parameters.AddWithValue(parameters[i], categoryIDs[i]); } comm.Parameters.AddWithValue("@name",$"%{Name}%"); comm.CommandText = "SELECT * FROM Products WHERE Category_ID IN ("; comm.CommandText += string.Join(",", parameters) + ")"; comm.CommandText += " OR name LIKE @name"; 

这是一个完全参数化的查询,应该让你的DBA高兴。 我怀疑,因为这些是整数,尽pipe直接用这些值构造命令文本并没有太大的安全风险,但仍然参数化名称。 如果您的类别ID位于string数组中,则只需以逗号分隔数组,将其转换为整数,然后将其存储在整数数组中。

注意:我说数组并在示例中使用它,但它应该适用于任何集合,尽pipe您的迭代可能会有所不同。

来自http://www.tek-tips.com/viewthread.cfm?qid=1502614&page=9的原创构思;

你需要在sql参数的值的“%”。

 SqlCommand comm = new SqlCommand("SELECT * FROM Products WHERE Category_ID IN (@categoryid1, @categoryid2) OR name LIKE @name", conn); comm.Parameters.Add("@categoryid1", SqlDbType.Int); comm.Parameters["@categoryid1"].Value = CategoryID[0]; comm.Parameters.Add("@categoryid2", SqlDbType.Int); comm.Parameters["@categoryid2"].Value = CategoryID[1]; comm.Parameters.Add("@name", SqlDbType.Int); comm.Parameters["@name"].Value = "%" + Name + "%"; 

这种做法是行不通的。 期。

IN子句本身需要一个参数列表,所以当你绑定一个参数的时候,你有机会传入一个值。

dynamic构build您的语句string,您准备传入的单个IN子句占位符的确切数量,然后在循环中添加参数并将值绑定到它们。

不知道这是否是正确的方式,但这是我在之前做过的一种方式

列表templist =新列表

comm.Parameters.Add(“@ categoryids”,SqlDbType.varchar); comm.Parameters [“@ categoryids”]。value = string.join(“,”,templist.toarray())