3

我正在尝试查询现有的访问数据库并允许用户为 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 标签。

4

6 回答 6

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 子句。

于 2013-07-19T09:26:45.497 回答
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]);
    }
}
于 2013-07-19T09:27:41.307 回答
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为空,则返回所有标签。

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 中以不同的方式执行此操作

于 2013-07-19T09:28:00.350 回答
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
于 2013-07-19T09:28:48.003 回答
0

将 where 子句放在变量中并使 CommandText 像cmd.CommandText = SELECT + WHERE when: SELECT = "SELECT * FROM Tags" WHERE = "WHERE " + "Name IN (@tag0 ....)" if no parameters variable WHERE will be = ""

于 2013-07-19T09:24:21.310 回答
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;
        }
于 2013-07-19T09:30:22.710 回答