webdevqa.jp.net

LIKEおよびIN条件のパラメーター化されたクエリ

.Netのパラメーター化されたクエリは、例では常に次のようになります。

SqlCommand comm = new SqlCommand(@"
   SELECT * 
   FROM   Products 
   WHERE  Category_ID = @categoryid
", 
   conn);
comm.Parameters.Add("@categoryid", SqlDbType.Int);
comm.Parameters["@categoryid"].Value = CategoryID;

しかし、私はレンガ壁にぶつかり、次のことを試みています。

SqlCommand comm = new SqlCommand(@"
   SELECT * 
   FROM   Products 
   WHERE  Category_ID IN (@categoryids) 
      OR  name LIKE '%@name%'
", 
   conn);
comm.Parameters.Add("@categoryids", SqlDbType.Int);
comm.Parameters["@categoryids"].Value = CategoryIDs;
comm.Parameters.Add("@name", SqlDbType.Int);
comm.Parameters["@name"].Value = Name;

どこ

  • CategoryIDsは、「123,456,789」(引用符なし)のコンマ区切りのリストです。
  • 名前は文字列で、単一引用符やその他の不正な文字が含まれている可能性があります

これの正しい構文は何ですか?

47
Tom Ritter

整数配列にカテゴリIDがあり、Nameが文字列であるとしましょう。トリックは、コマンドテキストを作成して、すべてのカテゴリIDを個別のパラメータとして入力し、名前のあいまい一致を作成できるようにすることです。前者を行うには、ループを使用してパラメーター名のシーケンス@ p0から@ pN-1を作成します。ここで、Nは配列内のカテゴリーIDの数です。次に、パラメーターを作成し、関連するカテゴリーIDを各名前付きパラメーターの値としてコマンドに追加します。次に、クエリ自体の名前に連結を使用して、名前のあいまい検索を可能にします。

string Name = "someone";
int[] categoryIDs = new int[] { 238, 1138, 1615, 1616, 1617,
                                1618, 1619, 1620, 1951, 1952,
                                1953, 1954, 1955, 1972, 2022 };

SqlCommand comm = conn.CreateCommand();

string[] parameters = new string[categoryIDs.Length];
for(int i=0;i<categoryIDs.Length;i++)
{
   parameters[i] = "@p"+i;
   comm.Parameters.AddWithValue(parameters[i], categoryIDs[i]);
}
comm.Parameters.AddWithValue("@name",$"%{Name}%");
comm.CommandText = "SELECT * FROM Products WHERE Category_ID IN (";
comm.CommandText += string.Join(",", parameters) + ")";
comm.CommandText += " OR name LIKE @name";

これは完全にパラメータ化されたクエリであり、DBAを満足させるはずです。これらは整数であるため、名前をパラメーター化しながら、値を使用してコマンドテキストを直接作成することはセキュリティリスクになりません。カテゴリIDが文字列配列にある場合は、配列をコンマで分割し、それぞれを整数に変換して、整数配列に格納します。

注:配列と言って例で使用していますが、どのコレクションでも機能するはずですが、反復はおそらく異なります。

http://www.tek-tips.com/viewthread.cfm?qid=1502614&page=9 の元のアイデア

58
tvanfosson

SQLパラメータの値に「%」が必要です。

SqlCommand comm = new SqlCommand("SELECT * FROM Products WHERE Category_ID IN (@categoryid1, @categoryid2) OR name LIKE @name", conn);
comm.Parameters.Add("@categoryid1", SqlDbType.Int);
comm.Parameters["@categoryid1"].Value = CategoryID[0];
comm.Parameters.Add("@categoryid2", SqlDbType.Int);
comm.Parameters["@categoryid2"].Value = CategoryID[1];
comm.Parameters.Add("@name", SqlDbType.Int);
comm.Parameters["@name"].Value = "%" + Name + "%";
12
TcKs

このアプローチは機能しません。限目。

IN句はパラメータ自体のリストを想定しているため、それにoneパラメータをバインドすると、one値を渡すことができます。

渡す予定の個々のIN句のプレースホルダーの正確な量を使用してステートメント文字列を動的に作成し、パラメーターを追加してループに値をバインドします。

6
Tomalak