查询具有未知数量参数的数据库

时间:2013-07-19 09:19:37

标签: c# sql

我正在尝试查询现有的访问数据库,并允许用户为WHERE子句选择多个值。我一直在使用此网站上的代码由用户Mark Brackett提供:

string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" };
string cmdText = "SELECT * FROM Tags WHERE Name IN ({0})";

string[] paramNames = tags.Select(
    (s, i) => "@tag" + i.ToString()
).ToArray();

string inClause = string.Join(",", paramNames);
using (SqlCommand cmd = new SqlCommand(string.Format(cmdText, inClause))) {
    for(int i = 0; i < paramNames.Length; i++) {
       cmd.Parameters.AddWithValue(paramNames[i], tags[i]);
    }
}

给出了这个:

cmd.CommandText = "SELECT * FROM Tags WHERE Name IN (@tag0,@tag1,@tag2,@tag3)"
cmd.Parameters["@tag0"] = "ruby"
cmd.Parameters["@tag1"] = "rails"
cmd.Parameters["@tag2"] = "scruffy"
cmd.Parameters["@tag3"] = "rubyonrails"

这非常有效,但我也想要以下功能。如果用户决定不输入任何值(在此示例中,如果tags数组为空),则我希望返回所有结果。实际上只是一个SELECT * FROM Tags。

6 个答案:

答案 0 :(得分:3)

这样的东西
string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" };
string cmdText = "SELECT * FROM Tags {0}";

string[] paramNames = tags.Select(
            (s, i) => "@tag" + i.ToString()
        ).ToArray();

string cmdWhere = paramNames.Length > 0 ? String.Format("WHERE Name IN ({0})", string.Join(",", paramNames)) : "";
using (SqlCommand cmd = new SqlCommand(string.Format(cmdText, cmdWhere)))
{
    for (int i = 0; i < paramNames.Length; i++)
    {
        cmd.Parameters.AddWithValue(paramNames[i], tags[i]);
    }
}

因此,如果您没有参数,则最后不添加where子句。

答案 1 :(得分:2)

尝试

string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" };
string cmdText = "SELECT * FROM Tags" ;

string cond=" WHERE Name IN ({0})";

string[] paramNames = tags.Select(
    (s, i) => "@tag" + i.ToString()
).ToArray();

if(paramNames.Length>0){
   string inClause = string.Join(",", paramNames);
   cmdText=string.Concat(cmdText,string.Format(cond, inClause));
}
using (SqlCommand cmd = new SqlCommand(cmdText) {
    for(int i = 0; i < paramNames.Length; i++) {
       cmd.Parameters.AddWithValue(paramNames[i], tags[i]);
    }
}

答案 2 :(得分:1)

为什么不将它们连接起来而不是为每个项目设置一个参数?

我不确定这是否适用于MS Access,但这是我用于MS SQL的内容:

DECLARE @tagIds nvarchar(max)

SELECT * FROM Tags where @tagIds is null or tagId IN (select number from dbo.iter_intlist_to_tbl(@tagIds))

所以@tagIds是一个以逗号分隔的ID列表,我只是用函数解析它。如果@tagIds为null,则返回所有标记。

iter_intlist_to_tbl()函数如下所示:

CREATE FUNCTION [dbo].[iter_intlist_to_tbl] (@list nvarchar(MAX))
   RETURNS @tbl TABLE (listpos int IDENTITY(1, 1) NOT NULL,
                       number  int NOT NULL) AS
BEGIN
   DECLARE @startpos int,
           @endpos   int,
           @textpos  int,
           @chunklen smallint,
           @str      nvarchar(4000),
           @tmpstr   nvarchar(4000),
           @leftover nvarchar(4000)

   SET @textpos = 1
   SET @leftover = ''
   WHILE @textpos <= datalength(@list) / 2
   BEGIN
      SET @chunklen = 4000 - datalength(@leftover) / 2
      SET @tmpstr = ltrim(@leftover +
                    substring(@list, @textpos, @chunklen))
      SET @textpos = @textpos + @chunklen

      SET @startpos = 0
      SET @endpos = charindex(',' COLLATE database_default, @tmpstr)

      WHILE @endpos > 0
      BEGIN
         SET @str = substring(@tmpstr, @startpos + 1,
                              @endpos - @startpos - 1)
         IF @str <> ''
            INSERT @tbl (number) VALUES(convert(int, @str))
         SET @startpos = @endpos
         SET @endpos = charindex(',' COLLATE database_default,
                                 @tmpstr, @startpos + 1)
      END

      SET @leftover = right(@tmpstr, datalength(@tmpstr) / 2 - @startpos)
   END

   IF ltrim(rtrim(@leftover)) <> ''
      INSERT @tbl (number) VALUES(convert(int, @leftover))

   RETURN
END
GO

有关解析逗号分隔列表的更多信息,请参阅http://www.sommarskog.se/arrays-in-sql-2005.html。虽然我想你会在MS Access中以不同的方式做到这一点

答案 3 :(得分:1)

我假设如果任何标签为空

if (@tag0 is null or @tag1 is null or @tag2 is null or @tag3 is null)  
 begin  
    select * from tags  
 end  
else  
  begin  
    SELECT * FROM Tags WHERE Name IN (@tag0,@tag1,@tag2,@tag3)  
end

答案 4 :(得分:0)

将where子句放在变量中并使CommandText像cmd.CommandText = SELECT + WHERE一样 何时:SELECT = "SELECT * FROM Tags" WHERE = "WHERE " + "Name IN (@tag0 ....)" 如果没有参数变量WHERE将是=“”

答案 5 :(得分:0)

我修改了现有的。这将有效。

string cmdText = "SELECT * FROM Tags ";
        string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" };
        string where = null;
        if (tags != null)
        {
            where = "WHERE Name IN (";
            foreach (string tag in tags)
            {
                where += "'" + tag + "',";
            }
            where = where.TrimEnd(',') + ")";
        }
        if (!string.IsNullOrEmpty(where))
        {
            cmdText += where;
        }