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

时间:2013-01-10 11:53:18

标签: c# .net sql tsql sql-server-2008-r2

  

可能重复:
  Help with a sql search query using a comma delimitted parameter

我想编写一个对表执行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运行此命令?

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

4 个答案:

答案 0 :(得分:8)

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

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

稍后使用以下SELECT获取@temp中所有人的列表,如果@temp不包含任何行(未过滤的结果),则会列出所有人的列表:

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

答案 1 :(得分:5)

您可以使用Table Valued Parameters

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

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
    

    您可以在this SQL Fiddle

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

    names

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

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

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

答案 2 :(得分:2)

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

Split Function in Sql Server to break Comma-Separated Strings into Table

SQL User Defined Function to Parse a Delimited String

您可以使用

从表中选择数据
Select * from 
Personnel where 
  Name in (select items from dbo.Split ('Jack,Joe,Jane',','))

答案 3 :(得分:2)

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

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

SQL成为

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

请参阅http://www.sqlfiddle.com/#!3/8ee5a/1