2012-07-19 3 views
5

私は値のリストに関連付けられたすべての行を返すクエリを持っています。パラメータリストによるSQLクエリフィルタリング

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

私はこのクエリをC#で生成して実行することができました。ただし、これはパラメータを使用しないため明らかに理想的ではなく、クエリプランをキャッシュしようとすると苦労し、SQLインジェクション攻撃に対して脆弱です。これは、しかし、これはN DBヒットになり、C#と何度も実行することができ

select * from TableA where ColumnB = @value 

選択肢はこれを書くことです。

私が見ることのできる唯一の代替方法は、テンポラリテーブルを作成してそれに参加させることですが、この点はもっと複雑で、最初のオプションと同じ制限があります。

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

これら3つの方法のどれが効率的ですか?代替案が欠けていますか?あなたは簡単にこの書くことができます

+0

どのようにクエリを実行しますか? EF、LINQ、ADO、OLEDB? – paul

+0

そしてどのサーバー? MySql、MsSql、その他? – mmdemirbas

+0

OLDBとMsSQL、質問が更新されました – Liath

答えて

4

は、SQL Serverで、一度テーブル型を作成:

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

もっと一般的なタイプのため、具体的に何をしているのかを明確にするために名前を付けました)

0

:このところで

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

を、パフォーマンスが低下していない、とあなたはcsvStringを作成しながら、単に入力値をエスケープSQLインジェクションを防ぐことができます。

ところで、あなたはMS SQLの代わりに、標準SQLを使用する場合は、することができますfindalternativeways

+0

はい、これは私が現在やっている方法です。私の問題は、コマンドが異なるのでパフォーマンスがかなり低下するたびに、このクエリが実行されるたびに新しい実行計画が作成されることです。 – Liath

+1

@Liath [最適化された特別なワークロードの最適化]を使用すると、 http://msdn.microsoft.com/en-us/library/cc645587.aspx)設定。この方法では、特定のクエリが2回実行されるまで、プランはキャッシュされません。クエリではまだスキャンが行われますが、実際には再利用される場合を除き、プランキャッシュ内のスペースを占有することはありません。 –

2

またmultiple resultsetsを使用して、このようなクエリのbounchを送ることができます。シングル呼び出しで

​​

。 明らかに直観に反しても、実行計画を活用し、パラメータ化の面で安全です。 SQL Server 2008またはそれ以降を想定し

+0

私は受け取った-1について興味があります –

+0

OPは彼らがしたくないと言ったものではありませんか? –

+0

@AaronBertrand正確ではない:彼は実行計画を使いたいと思う。これらは往復ではないことに注意してください。ただし、すべてのクエリはDBへの単一のルートで実行されます。さらに、注入を避けるために、クエリが正しくパラメータ化されています。 –

関連する問題