2

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

我想编写一个在表上执行选择的存储过程,并且需要一个类型的输入变量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

4 回答 4

10

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

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
于 2013-01-10T12:02:09.283 回答
5

您可以使用表值参数

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

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<string>被调用的names. 您需要将其转换为表值参数以发送到过程,使用类似:

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

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

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

    List<string> names = new List<string> { "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"]);
          }
        }
      }
    }
    
于 2013-01-10T13:07:15.043 回答
2

我想您需要 Sql Server 中的拆分函数将逗号分隔的字符串分解为表。请参考这些链接。

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

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

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

Select * from 
Personnel where 
  Name in (select items from dbo.Split ('Jack,Joe,Jane',','))
于 2013-01-10T11:57:35.890 回答
2

您可以简单地检查名称是否包含在字符串中。请注意末尾开头的逗号,以确保您匹配全名

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

SQL变成

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

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

于 2013-01-10T12:04:16.503 回答