如何将SQL参数中的字符串数组传递给SQL中的IN子句

我正在以复杂的方式做的逻辑。

我只需要在存储过程中执行此查询:

select Sizes, SUM(Quantity) from tbl_SizeBreakup where (Brand=@brand) and (Combo in ('1','2')) ... 

组合我必须在C#中使用SQL参数传递

 DataSet dt = new DataSet(); cmd = new SqlCommand(); cmd.CommandType = System.Data.CommandType.StoredProcedure; cmd.CommandText = "sp_Accessories"; cmd.Connection = con; cmd.Parameters.AddRange( new SqlParameter[] { new SqlParameter("@Mode",mode), new SqlParameter("@Combo",combo), }} 

所以如果我传递1个参数,按预期工作。 我应该传递的组合是一个string[] (字符串数组)。 数组长度可以取决于用户在UI中选择的任何内容。

我的问题是,如何将string[]传递给new SqlParameter("@Combo",combo)

我的存储过程..

 ALTER proc [dbo].[sp_Accessories] ( @Mode varchar(50)=null, @id int=null, @brand varchar(50)=null, @department varchar(MAX)=null, @season varchar(50)=null, @groupname varchar(MAX)=null, @styles varchar(50)=null, @combo varchar(50)=null, @combo_color nvarchar(max)=null, ) as if @Mode='getsizewise' begin select Sizes,SUM(Quantity) from tbl_SizeBreakup where (Brand=@brand) and (Department=@department) and (Season=@season) and (Group_Name=@groupname) and (Style=@styles) and (Combo_Color=@color) and (Total_Add_Qty='Total Quantity') Group By Sizes end 

简介 :尽管OP已经接受了答案,但我认为分享我的经验会更好,因为我相信我要展示的方法比接受的方法更好。

我发现将数组传递给sql server数据库的最佳方法是使用user defined table type和c# DataTable 。 在你的情况下,因为你想传递一个维度的字符串数组,所以很容易:

首先,您需要在数据库中创建用户定义的表类型:

  CREATE TYPE dbo.StringArray As Table ( StringItem varchar(50) -- you can use any length suited for your needs ) 

然后,您需要在c#代码中创建一个数据表:

 DataTable dt = new DataTable(); dt.Columns.Add("StringItem", typeof(System.String)); 

然后更改存储过程以接受此数据类型作为参数:

 ALTER proc [dbo].[sp_Accessories] ( @Mode varchar(50)=null, @id int=null, @brand varchar(50)=null, @department varchar(MAX)=null, @season varchar(50)=null, @groupname varchar(MAX)=null, @styles varchar(50)=null, @combo dbo.StringArray Readonly=null, -- NOTE THIS CHANGE @combo_color nvarchar(max)=null, ) as if @Mode='getsizewise' begin select Sizes,SUM(Quantity) from tbl_SizeBreakup where (Brand=@brand) and (Department=@department) and (Season=@season) and (Group_Name=@groupname) and (Style=@styles) and (Combo_Color=@color) and (Total_Add_Qty='Total Quantity') and comboColumn in(select StringItem from @Combo) -- NOTE THIS CHANGE Group By Sizes end 

然后,您需要将字符串数组转换为c#代码中的dataTable。

 foreach (string s in YourStringArray) { string[] temp = {s}; dt.Rows.Add(temp); } 

将DataTable作为参数添加到存储过程:

 System.Data.SqlClient.SqlParameter sp = new Data.SqlClient.SqlParameter(); sp.SqlDbType = SqlDbType.Structured; sp.Value = dt; sp.ParameterName = "@Combo"; cmd.Parameters.Add(sp); 

建立并运行。

这种方法应该具有更好的性能,然后使用sql用户定义的函数,也可以用于不同的数据类型。 这是使用它的最佳理由之一:考虑一个需要传递日期数组的场景:csv方法需要sql将每个字符串转换为日期,而使用这种方法,您可以简单地按日期传递日期,不将它们转换为字符串然后再转换为日期。此外,您可以传递2维数组或字典,您只需在sql数据库中创建适当的用户定义数据类型。

注意:这里直接写的代码,可能会有一些拼写错误。

你可以在csv中传递一个列表(逗号分隔值):’1,2,3’,SP中的这个字符串是没用的,但是你可以转换成一个表,首先创建这个函数:

 CREATE FUNCTION fun_CSV_to_Table ( @pcsvList varchar(max) ) RETURNS @tableWithValues table(theColumn varchar(100)) AS BEGIN DECLARE @pos INT WHILE CHARINDEX(',', @pcsvList) > 0 BEGIN SELECT @pos = CHARINDEX(',', @pcsvList) INSERT INTO @tableWithValues SELECT LTRIM(RTRIM(SUBSTRING(@pcsvList, 1, @pos-1))) SELECT @pcsvList = SUBSTRING(@pcsvList, @pos+1, LEN(@pcsvList)-@pos) END --Insert the last value. INSERT INTO @tableWithValues SELECT @pcsvList RETURN END GO 

然后你可以使用它:

  SELECT SIZES, SUM(QUANTITY) FROM TBL_SIZEBREAKUP WHERE BRAND=@BRAND AND COMBO IN (select theColumn FROM dbo.fun_CSV_to_Table(@aList)) /* @aList must be a csv: '1,2,3,...,n' */ 

你应该关心白色空间。

您可以使用Parameters.AddWithValues (已更新):

 DataSet dt = new DataSet(); cmd = new SqlCommand(); cmd.CommandType = System.Data.CommandType.StoredProcedure; cmd.CommandText = "sp_Accessories"; cmd.Connection = con; var parameterList = new StringBuilder(); for (int i = 0; i < items.Length; i++) { parameterList.Append(items[i] + ","); } var parameters= parameters.ToString().TrimEnd(','); cmd.Parameters.AddWithValue("@Combo", parameters); cmd.Parameters.AddRange( new SqlParameter[] { new SqlParameter("@Mode",mode), }}