用逗号分隔的类似数组的字符串执行存储过程

可能重复:
使用逗号分隔参数帮助sql搜索查询

我想编写一个存储过程,在表上执行select并需要一个varchar(max)类型的输入变量。

我想发送一堆由输入参数分隔的值,例如

 'Jack','Jane','Joe' 

然后获取包含其中一个名称的行。

在SQL中,代码将是

 Select * from Personnel where Name in ('Jack','Joe','Jane'); 

现在我想在我的C#应用​​程序中有一个变量,比如strNames并填充它

 string strNames = "'Jack','Joe','Jane'"; 

并将此变量发送到SP并执行它。 就像是

 Select * from Personnel where Name in (''Jack','Joe','Jane'') -- this is wrong 

但是, 如何告诉SQL Server运行此命令?

我需要做到这一点,我知道这是可能的,请给我一些线索。

首先,当您将单个名称传递给存储过程时,不需要引用单个名称。

 using (SqlCommand cmd = new SqlCommand("MyStoredProc", conn)) { cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@longFilter", "Jack,Jill,Joe"); using (SqlDataReader reader = cmd.ExecuteReader()) { ... } } 

然后,在存储过程中,您可以使用简单的文本函数和临时表,如下所示将逗号分隔字符串,并为字符串的每个部分分配临时表的条目:

 DECLARE @temp AS TABLE (Name NVARCHAR(255)) IF ISNULL(@longFilter, '') <> '' BEGIN DECLARE @s NVARCHAR(max) WHILE LEN(@longFilter) > 0 BEGIN IF CHARINDEX(',', @longFilter) > 0 BEGIN SET @s = LTRIM(RTRIM(SUBSTRING(@longFilter, 1, CHARINDEX(',', @longFilter) - 1))) SET @longFilter = SUBSTRING(@longFilter, CHARINDEX(',', @longFilter) + 1, LEN(@longFilter)) END ELSE BEGIN SET @s = LTRIM(RTRIM(@longFilter)) SET @longFilter= '' END -- This was missing until 20140522 INSERT INTO @temp (Name) VALUES (@s) END END 

如果@temp不包含任何行(未过滤的结果),请稍后使用以下SELECT获取其名称在@temp或所有人的所有人的@temp

 SELECT * FROM Personnel WHERE Name IN (SELECT Name FROM @temp) OR (SELECT COUNT(*) FROM @temp) = 0 

您可以使用表值参数 。

基本上,您可以在过程中插入值列表作为参数,并将它们用作表格,类似于

 Select * from Personnel where Name in (select name from @NamesTable). 

现在,具体细节

  • 要使用表值参数,必须在sql server中使用预定义参数的类型

     create type NamesTable as table (Name varchar(50)) 
  • 然后,您可以使用已定义的类型作为过程中的参数

     create procedure getPersonnelList @NamesTable NamesTable readonly as begin select * from personnel where Name in (select Name from @NamesTable) end 

    你可以在这个SQL Fiddle中看到它的实际效果

  • 在C#方面你需要创建参数。 如果你有一个集合中的名字,并构建字符串,你可以使用它来生成参数,如果它们是逗号分隔的字符串,快速string.Split可以处理它。 由于我不知道你的具体细节,我假设你有一个名为List names 。 您需要将其转换为要发送到过程的表值参数,使用类似于:

     DataTable tvparameter = new DataTable(); tvparameter.Columns.Add("Name", typeof(string)); foreach (string name in names) { tvparameter.Rows.Add(name); } 

    您可以在SO问题中找到有关如何使用C#代码生成TVP的更多信息。 。

  • 现在您只需要将该参数发送到该过程,就是这样。 这是一个完整的控制台程序,它执行过程并输出结果。

     List names = new List { "Joe", "Jane", "Jack" }; using (SqlConnection cnn = new SqlConnection("...")) { cnn.Open(); using (SqlCommand cmd = new SqlCommand("getPersonnelList", cnn)) { cmd.CommandType = CommandType.StoredProcedure; DataTable tvparameter = new DataTable(); tvparameter.Columns.Add("Name", typeof(string)); foreach (string name in names) { tvparameter.Rows.Add(name); } cmd.Parameters.AddWithValue("@NamesTable", tvparameter); using (SqlDataReader dr = cmd.ExecuteReader()) { while (dr.Read()) { Console.WriteLine("{0} - {1}", dr["ID"], dr["Name"]); } } } } 

我想你需要在Sql Server中使用Split函数来将逗号分隔的字符串分解为表格。 请参考这些链接。

在Sql Server中拆分函数以将逗号分隔的字符串分解为表

用于定义分隔字符串的SQL用户定义函数

您可以使用从表中选择数据

 Select * from Personnel where Name in (select items from dbo.Split ('Jack,Joe,Jane',',')) 

您只需检查字符串中是否包含Name。 请注意结尾处的逗号,以确保您匹配全名

 string strNames = ",Jack,Joe,Jane,"; 

SQL变成了

 select * from Personnel where PATINDEX('%,' + Name + ',%', @strNames) > 0 

见http://www.sqlfiddle.com/#!3/8ee5a/1