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

1

タグのいずれかがnullの場合

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 に答える
1

項目ごとに 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 のリストも同様で、関数を使用して解析するだけです。null の場合@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 に答える
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 に答える