C# 查询参数数目未知的数据库

C# 查询参数数目未知的数据库,c#,sql,C#,Sql,我试图查询现有的access数据库,并允许用户为WHERE子句选择多个值。我一直在使用这个网站上的代码,这是由用户Mark Brackett提供的: string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" }; string cmdText = "SELECT * FROM Tags WHERE Name IN ({0})"; string[] paramNames = tags.Select(

我试图查询现有的access数据库,并允许用户为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]);
    }
}

这很好地工作,但是我也想要以下功能。如果用户决定不输入任何值(在本例中,如果标记数组为空),那么我希望返回所有结果。实际上只是一个SELECT*FROM标记。

将where子句放入变量中,并使CommandText类似于
cmd.CommandText=SELECT+where
当:
SELECT=“SELECT*FROM Tags”
WHERE=“WHERE”+“Name IN(@tag0…)”

如果没有参数变量WHERE will=“”

那么

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]);
    }
}
string[]tags=newstring[]{“ruby”、“rails”、“scruffy”、“rubyonrails”};
string cmdText=“从标记{0}中选择*”;
string[]paramNames=标记。选择(
(s,i)=>“@tag”+i.ToString()
).ToArray();
字符串cmdWhere=paramNames.Length>0?String.Format(“WHERE Name IN({0})”,String.Join(“,”,paramNames)):“”;
使用(SqlCommand cmd=newsqlcommand(string.Format(cmdText,cmdWhere)))
{
for(int i=0;i
因此,如果没有参数,则在结尾处不添加where子句。

请尝试

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]);
    }
}
string[]tags=newstring[]{“ruby”、“rails”、“scruffy”、“rubyonrails”};
string cmdText=“从标记中选择*”;
字符串cond=“WHERE Name IN({0})”;
string[]paramNames=标记。选择(
(s,i)=>“@tag”+i.ToString()
).ToArray();
如果(paramNames.Length>0){
string incluse=string.Join(“,”参数名);
cmdText=string.Concat(cmdText,string.Format(cond,inClause));
}
使用(SqlCommand cmd=newsqlcommand(cmdText){
for(int i=0;i
与其为每个项目都有一个参数,为什么不将它们串联起来呢

我不确定这是否适用于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\u intlist\u to\u 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
创建函数[dbo]。[iter_intlist_to_tbl](@list nvarchar(MAX))
返回@tbl TABLE(listpos int IDENTITY(1,1)不为空,
数字int(非空)为
开始
声明@startpos int,
@endpos int,
@textpos int,
@chunklen smallint,
@str nvarchar(4000),
@tmpstr nvarchar(4000),
@剩余nvarchar(4000)
设置@textpos=1
设置@leftover=“”
而@textpos 0
开始
设置@str=substring(@tmpstr、@startpos+1、,
@endpos-@startpos-1)
如果@str“
插入@tbl(数字)值(转换(int,@str))
设置@startpos=@endpos
设置@endpos=charindex(','COLLATE database_默认值,
@tmpstr,@startpos+1)
结束
设置@leftover=right(@tmpstr,datalength(@tmpstr)/2-@startpos)
结束
如果ltrim(rtrim(@leftover))“”
插入@tbl(数字)值(转换(整数,@leftover))
返回
结束
去

有关解析逗号分隔列表的更多信息,请参阅。虽然我认为在MS Access中您会以不同的方式执行此操作,但我假设如果任何标记为空

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

我已修改了现有的。这将起作用

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;
        }

好吧,除了这样一个事实,即这抛弃了根据包含搜索词列表的数组中的值的数量来计算
in
子句中的值的数量的逻辑,并且最终会得到类似
SELECT*FROM tags where Name in…
…谢谢你。这看起来很有趣,我会的我稍后再看。这太好了,谢谢。我还可以看到,我可以在我的查询中包含几个这样的多参数子句,方法是将我的cmdText设置为“Select*FROM Tags WHERE 1=1”,然后将您的代码与“and Name in({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;
        }