1

ASP.NET ページで実行している SQL クエリがあります。最終的に解析された SQL には、WHERE [columnname] IN [values]形式の文字列値のリストが含まれている必要があります。たとえば、最終的なクエリは次のようになります。

SELECT PRODUCTNAME FROM PRODUCT WHERE PRODUCTCODE IN ('ABC','DEF','GHI','JKL', /* etc */);

ただし、WHERE 句の文字列値は動的である必要があります。通常、コードを便利で安全にするためにパラメータ化されたクエリを使用するので、概念的には次のようにしたいと思います。

String[] productCodes = { "ABC", "DEF", "GHI", "JKL" };
SqlCommand cmd = "SELECT PRODUCTNAME FROM PRODUCT WHERE PRODUCTCODE IN (@ProductCodes)";
cmd.Parameters.Add("@ProductCodes", productCodes);

ただし、この種の機能は .NET には存在しないようです。これを実装するにはどうすればよいですか?配列で foreach ループを使用し、各値のパラメーターとして 1 つの値を使用してクエリを実行することもできますが、配列には 100 ほどの異なる値が存在する可能性があり、それらを個別にクエリするのは非常に非効率的です。

誰かが強く型付けされた int パラメータの解決策を提案した別の質問を読みましたが、特にクライアントが入力値に影響を与える可能性が非常に高いため、文字列値で使用すると、その方法は SQL インジェクションについて不安になります。

このクエリ機能をどのように実装しますか?

DBの詳細で編集

データベースは SQL Server 2005 です。言い忘れてすみません。

4

4 に答える 4

2

基本SQLステートメントをフォーマットとして作成し、パラメーターを動的に追加してから、ループで値を設定します。

String[] productCodes = { "ABC", "DEF", "GHI", "JKL" };
string sqlFormat = "SELECT PRODUCTNAME FROM PRODUCT WHERE PRODUCTCODE IN ({0})";
var @params = productCodes.Select((id, index) => String.Format("@id{0}", index)).ToArray();
var sql = String.Format(sqlFormat, string.Join(",", @params));

using(var cmd = new DbCommand(sql))
{
    for (int i = 0; i < productCodes.Length; i++)
        cmd.Parameters.Add(new Parameter(@params[i], DbType.String, productCodes[i]));
    // execute query
}
于 2011-03-11T21:07:57.107 に答える
1

ただのアイデア:

String[] productCodes = { "ABC", "DEF", "GHI", "JKL" };
SqlCommand cmd = "SELECT PRODUCTNAME FROM PRODUCT WHERE PRODUCTCODE IN ("; 

for (int i=0;i<productCodes.Length;i++) {
  cmd.CommandText += "@" + productCodes[i] + ",";
  cmd.Parameters.Add("@" + productCodes[i], productCodes[i]);
}
cmd.CommandText = cmd.CommandText.SubString(0, cmd.CommandText.Length-1);
cmd.CommandText += ");"

おそらく最善の方法ではありませんが、これが私が試してみた方法だと思います。

于 2011-03-11T21:02:56.237 に答える
0

テーブル値パラメーターを探しています。 ただし、これらは、asp.net が広く採用されるまで SQL Server で利用できなかったため、asp.net でのそれらのサポートは制限されています。

私がお勧めするのは、ショッピング カートを作るようなものだと考えることです。ユーザーがカートにアイテムを追加し、ある時点でカート内のすべてのアイテムを表示したいとします。この場合、当然の解決策は、ショッピング カート自体をデータベース テーブルに置くことです。カードが "IN (?)" ディレクティブの一部として含める項目をプルダウンするのではなく、これをディレクティブのサブクエリとして作成します: " WHERE X IN (SELECT X FROM ShoppingCart WHERE UserID= @UserID AND SessionKey= @SessionKey)"。何百ものアイテムを追加したとしても、ユーザーは非常に高速になり、挿入ごとの負荷はかなり均等に分散されます。

もちろん、ショッピング カート以外のものを作成している可能性もありますが、クエリはほとんどの場合、次の 3 つのカテゴリのいずれかに分類されます。

  1. リストのアイテムはユーザーが手動で選択します。この場合、各選択結果を新しいデータベース レコードにして、サブクエリで使用することができます。
  2. これはデータベースで既に利用可能なデータであり、その場合でもサブクエリを使用できるはずです (使用できない場合は、できるように「カテゴリ」列をどこかに追加する必要があるかもしれません)。
  3. これはアプリにハード コードされたデータであり、その場合はクエリにコード化することもできます

まれな例外は、クエリが別のマシン ソースによってトリガーされた場合です。または、これを可能にするためにやり直すことをためらうコードが多数ある場合もあります。
したがって、何らかの理由でこのアプローチがうまくいかない場合は、SQL Server に関する標準記事 (いくつかの代替案を含む) をここで見つけることができます:
http://www.sommarskog.se/arrays-in -sql.html

この記事は、この主題に関する標準的な作業であり、時間をかける価値があります。

于 2011-03-11T21:01:05.627 に答える
0

レコードについては、配列内の 100 程度の値を「個別に」クエリしないことも非効率的です (ただし、SQL Server への 100 程度の往復ほど非効率的ではありません)。ただし、クエリをパラメーター化すると、同じクエリを準備して複数回実行できるため、少し役立ちます。ストアド プロシージャはさらに優れている可能性があります。

Linq を使用できる可能性はありますか、それとも .NET-3.5 より前ですか?

Linq を使用できず、絶対にこのルートを使用する必要がある場合は、次のことを試してください。

SqlCommand cmd = "SELECT PRODUCTNAME FROM PRODUCT WHERE PRODUCTCODE = @ProductCode";
cmd.Prepare();
List<string> results;
foreach (string code in productCodes)
{
    cmd.Parameters.Clear();
    cmd.Parameters.Add("@ProductCodes", DbType.VarChar).Value = code;
    cmd.ExecuteQuery();
    // Add code here to add the returned values to the results list.  It's been
    // a while since I've used ADO.NET, and I don't have time to look it up
    // at the moment...
}

そして、結果のリストがあります。

于 2011-03-11T21:08:08.243 に答える