【问题标题】:How to pass string array in SQL parameter to IN clause in SQL如何将 SQL 参数中的字符串数组传递给 SQL 中的 IN 子句
【发布时间】:2014-07-22 04:37:21
【问题描述】:

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

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

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

【问题讨论】:

标签: c# sql sql-server


【解决方案1】:

简介:尽管 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 将每个字符串转换为日期,而使用这种方法,您可以简单地按原样传递日期,而无需将它们转换为字符串然后再返回日期。此外,您可以传递二维数组或字典,您所要做的就是在您的 sql 数据库中创建适当的用户定义数据类型。

注意:这里直接写代码,可能有错别字。

【讨论】:

    【解决方案2】:

    可以在csv中传入一个list(逗号分隔值): '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' */
    

    您应该注意空格。

    【讨论】:

      【解决方案3】:

      您可以使用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),
          }}
      

      【讨论】:

      • 它抛出一个错误,@Combo0 不是过程 sp_Accessories 的参数。 ???那我应该如何在存储过程中使用参数...
      • 你能分享你的SP吗?
      • 没有错误和没有输出......它的空白...... @Combo 是字符串,我改变了代码...... parameterList.Append("'" + combo_color[i] + "' " + ",");仍然没有输出...
      • 但我没有看到您在更新问题中发布的查询中使用了@Combo 参数
      猜你喜欢
      • 1970-01-01
      • 2013-12-15
      • 2011-06-11
      • 2011-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多