C#SQL Server – 将列表传递给存储过程

我从我的C#代码调用SQL Server存储过程:

using (SqlConnection conn = new SqlConnection(connstring)) { conn.Open(); using (SqlCommand cmd = new SqlCommand("InsertQuerySPROC", conn)) { cmd.CommandType = CommandType.StoredProcedure; var STableParameter = cmd.Parameters.AddWithValue("@QueryTable", QueryTable); var NDistanceParameter = cmd.Parameters.AddWithValue("@NDistanceThreshold", NDistanceThreshold); var RDistanceParameter = cmd.Parameters.AddWithValue(@"RDistanceThreshold", RDistanceThreshold); STableParameter .SqlDbType = SqlDbType.Structured; NDistanceParameter.SqlDbType = SqlDbType.Int; RDistanceParameter.SqlDbType = SqlDbType.Int; // Execute the query SqlDataReader QueryReader = cmd.ExecuteReader(); 

我存储的proc是相当标准的,但与QueryTable进行连接(因此需要使用存储过程)。

现在:我想添加一个stringList<string>到参数集。 例如,我存储的proc查询是这样的:

 SELECT feature FROM table1 t1 INNER JOIN @QueryTable t2 ON t1.fid = t2.fid WHERE title IN <LIST_OF_STRINGS_GOES_HERE> 

但是,string的列表是dynamic的,有几百个字符。

有没有办法将一个stringList<string>传递给存储过程? 还是有更好的方法来做到这一点?

非常感谢,Brett

如果您使用的是SQL Server 2008,则会有一个称为“用户定义表格types”的新function。 这是一个如何使用它的例子:

创build您的用户定义表types:

 CREATE TYPE [dbo].[StringList] AS TABLE( [Item] [NVARCHAR](MAX) NULL ); 

接下来,您需要在存储过程中正确使用它:

 CREATE PROCEDURE [dbo].[sp_UseStringList] @list StringList READONLY AS BEGIN -- Just return the items we passed in SELECT l.Item FROM @list l; END 

最后这里有一些SQL在C#中使用它:

 using (var con = new SqlConnection(connstring)) { con.Open(); using (SqlCommand cmd = new SqlCommand("exec sp_UseStringList @list", con)) { using (var table = new DataTable()) { table.Columns.Add("Item", typeof(string)); for (int i = 0; i < 10; i++) table.Rows.Add("Item " + i.ToString()); var pList = new SqlParameter("@list", SqlDbType.Structured); pList.TypeName = "dbo.StringList"; pList.Value = table; cmd.Parameters.Add(pList); using (var dr = cmd.ExecuteReader()) { while (dr.Read()) Console.WriteLine(dr["Item"].ToString()); } } } } 

在这种情况下的典型模式是将元素传递给逗号分隔的列表,然后在SQL中将其分解到可以使用的表中。 大多数人通常会创build一个指定的function来做到这一点:

  INSERT INTO <SomeTempTable> SELECT item FROM dbo.SplitCommaString(@myParameter) 

然后你可以在其他查​​询中使用它。

不,数组/列表不能直接传递给SQL Server。

以下选项可用:

  1. 传递逗号分隔的列表,然后在SQL中有一个函数将列表分割。 逗号分隔的列表很可能会作为Nvarchar()传递
  2. 通过xml并在SQL Server中有一个函数为列表中的每个值parsingXML
  3. 使用新定义的用户定义表types(SQL 2008)
  4. dynamic构buildSQL,并以“1,2,3,4”的forms传入原始列表并构buildSQL语句。 这很容易发生SQL注入攻击,但是会起作用。

是的,使存储过程参数为VARCHAR(...)然后通过逗号分隔值存储过程。

如果您正在使用Sql Server 2008,则可以利用TVP( 表值参数 ): SQL 2008 TVP和LINQ,如果QueryTable的结构比string数组复杂的话,否则这将是一个过度杀伤,因为需要在SQl Server中创build表types

如果您更喜欢在SQL中拆分CSV列表,还有一种使用公用表expression式 (CTE)的方法。 查看使用CTE进行string分割的高效方法 。

我知道的唯一方法是构buildCSV列表,然后将其作为string传递。 然后在SP一边,把它分开,做任何你需要的。

使用一列代替List来制作一个数据表,并向表中添加string。 您可以将此数据表以结构化types的forms传递,并使用表的标题字段执行另一个联接。