5

値のリストに関連付けられているすべての行を返したいクエリがあります。これは次のように非常に簡単に記述できます。

select * from TableA where ColumnB in (1, 2, 3, 5)

このクエリを C# で生成して実行できます。ただし、これはパラメーターを使用しないため、明らかに理想的とは言えません。クエリ プランをキャッシュしようとすると問題が発生し、SQL インジェクション攻撃に対して明らかに脆弱です。

別の方法は、これを次のように書くことです。

select * from TableA where ColumnB = @value

これは C# で何度も実行できますが、これにより N DB ヒットが発生します。

私が見ることができる他の唯一の選択肢は、一時テーブルを作成してそのように結合することですが、これはより複雑になり、最初のオプションと同じ制限を受けるため、この点はわかりません。

SQL サーバーと OLDB を使用していますが、クエリの作成は問題ではありません。私は最も効率的なプロセスを作成しようとしています。

これらの 3 つの方法のうち、より効率的なのはどれですか? 代替手段を逃しましたか?

4

3 に答える 3

4

SQL Server 2008 以降を想定して、SQL Server でテーブル タイプを 1 回作成します。

CREATE TYPE dbo.ColumnBValues AS TABLE
(
  ColumnB INT
);

次に、そのような型を入力として受け取るストアド プロシージャ:

CREATE PROCEDURE dbo.whatever
  @ColumnBValues dbo.ColumnBValues READONLY
AS
BEGIN
  SET NOCOUNT ON;

  SELECT A.* FROM dbo.TableA AS A
    INNER JOIN @ColumnBValues AS c
    ON A.ColumnB = c.ColumnB;
END
GO

C# で DataTable を作成し、それをパラメータとしてストアド プロシージャに渡します。

DataTable cbv = new DataTable();
cbv.Columns.Add(new DataColumn("ColumnB"));

// in a loop from a collection, presumably:
cbv.Rows.Add(someThing.someValue);

using (connectionObject)
{
    SqlCommand cmd        = new SqlCommand("dbo.whatever", connectionObject);
    cmd.CommandType       = CommandType.StoredProcedure;
    SqlParameter cbvParam = cmd.Parameters.AddWithValue("@ColumnBValues", cbv);
    cbvParam.SqlDbType    = SqlDbType.Structured;
    //cmd.Execute...;
}

(型をもっと汎用的にしたいかもしれません。私はそれが何をしているかを明確にするために特別に名前を付けました。)

于 2012-07-19T13:38:53.277 に答える
2

複数の結果セットを使用して、次のような一連のクエリを送信することもできます。

select * from TableA where ColumnB = @value0
select * from TableA where ColumnB = @value1
select * from TableA where ColumnB = @value2
...
select * from TableA where ColumnB = @valuen

1回の呼び出しで。明らかに直感に反するとしても、実行プランを活用し、パラメーター化の観点から安全です。

于 2012-07-19T13:24:38.453 に答える
0

これは簡単に書くことができます:

String csvString = "1, 2, 3, 5"; // Built the list somehow, don't forget escaping
String query = "select * from TableA where ColumnB in (" + csvString + ")";

これにより、パフォーマンスが低下することはなく、SQL インジェクションが作成中に入力値を単純にエスケープすることを防ぐことができますcsvString

ところで、標準 SQL の代わりにMS SQLを使用する場合は、別の方法を見つける ことができます。

于 2012-07-19T13:19:58.453 に答える