2009-07-22 12 views
3

私はいくつかのフィールドを持つテーブルを持っています。私は、ユーザーが1つまたはフィールドの組み合わせで検索できるように、asp.netで検索フィルターを作成しようとしています。だから、基本的に私は4つのparamsにかかる単一のストアドプロシージャを作成したいとそのnullではない...SQLフィルタクエリ

TableExampleは4列、のCol1 Col2にCOL3 COL4

Iを持っている場合には、WHERE句にPARAMを追加します可能な組み合わせごとに1つ作成するのではなく、1つのストアドプロシージャでこれを行う方法があることを望んでいます。

私はこのようなものを試していましたが、それは正しくありませんでしたが、これまでに何が得られましたか。

感謝!

CREATE PROCEDURE [dbo].[Search] 
    @Col1 int, 
    @Col2 int, 
    @Col3 int, 
    @Col4 int 
AS 

SET TRANSACTION ISOLATION LEVEL READ COMMITTED 

SELECT * 

FROM 
    [dbo].[TestTable] 
WHERE 
    1=1 
    CASE   
     WHEN @Col1 IN NOT NULL 
     THEN AND [Col1] = @Col1 

     WHEN @Col2 IN NOT NULL 
     THEN AND [Col2] = @Col2 

     WHEN @Col3 IN NOT NULL 
     THEN AND [Col3] = @Col3 

     WHEN @Col4 IN NOT NULL 
     THEN AND [Col4] = @Col4 
    END 
+0

のでいただきましたが、ちょうどC#でコード側のクエリ文字列を構築するために良いことは、代わりにストアドプロシージャのビルドを持ってしようとしているのクエリは、動的に合意されないされています?格納されたprocメソッドでいくつかの落とし穴があるようです... – Gabe

答えて

0

あなたの回答はすべてありがとうございます。しかし、少し違ってやった。誰かを助けることを願っています!ここで私はそれについていった方法は次のとおりです。

CREATE PROCEDURE [dbo].[TestTable_Search] 
    @Col1 int, 
    @Col2 uniqueidentifier, 
    @Col3 datetime, 
    @Col4 datetime 
AS 

SET TRANSACTION ISOLATION LEVEL READ COMMITTED 

SELECT * 

FROM 
    [dbo].[TestTable] 
WHERE 
    [Col1] = COALESCE(@Col1, Col1) AND 
    [Col2] = COALESCE(@Col2, Col2) AND 
    [Col3] >= COALESCE(@Col3 + "00:00:00", Col3) AND 
    [Col4] <= COALESCE(@Col4 + "23:59:59", Col4) 
0

あなたはそれを行うには、動的SQLを使用する必要があると思います:

CREATE PROCEDURE [dbo].[Search] 
    @Col1 int, 
    @Col2 int, 
    @Col3 int, 
    @Col4 int 
AS 

DECLARE @SQL nvarchar(MAX) 

SET TRANSACTION ISOLATION LEVEL READ COMMITTED 

SET @SQL = 'SELECT * 
       FROM [dbo].[TestTable] 
      WHERE 1=1 ' 

IF @Col1 IS NOT NULL 
SET @SQL = @SQL + ' AND Col1 = ''' + @Col1 + ''' ' 

IF @Col2 IS NOT NULL 
SET @SQL = @SQL + ' AND Col2 = ''' + @Col2 + ''' ' 

IF @Col3 IS NOT NULL 
SET @SQL = @SQL + ' AND Col3 = ''' + @Col3 + ''' ' 

IF @Col4 IS NOT NULL 
SET @SQL = @SQL + ' AND Col4 = ''' + @Col4 + ''' ' 

exec sp_executesql @SQL 

END 

SQLインジェクションだけでなく、そのほかのアクセス許可の問題のホストを含​​めこれに危険があることを覚えておいてください動的SQLであるために発生する可能性がありますが、これをデータベースレイヤーで実行する唯一の方法です。アプリケーション層(C#で)でクエリを作成したい場合は、SQLインジェクション攻撃からより完全に守ることができます。

あなたは欠点を理解するのに役立つかもしれないいくつかの動的SQLへのリンク:

http://www.sommarskog.se/dynamic_sql.html http://slashstar.com/blogs/tim/archive/2006/10/12/The-Prevalence-and-Dangers-of-SQL-Injection.aspx

2

は、そのOR短絡事実を使用してください。私は-1が有効な値ではないと仮定しました。

CREATE PROCEDURE [dbo].[Search] 
    @Col1 int = -1, 
    @Col2 int = -1, 
    @Col3 int = -1, 
    @Col4 int = -1 
AS 
Begin 
SET TRANSACTION ISOLATION LEVEL READ COMMITTED 

SELECT * 

FROM 
    [dbo].[TestTable] 
WHERE 
(@Col1 = -1 OR [Col1] = @Col1) 
and 
(@Col2 = -1 OR [Col2] = @Col2) 
and 
(@Col3 = -1 OR [Col3] = @Col3) 
and 
(@Col4 = -1 OR [Col4] = @Col4) 



END 
+1

これはしばらくの間、私のお気に入りの検索方法でした。しかし、私はそれがいくつかの検索の引数のために実際にすぐに悪い実行計画とパフォーマンスの低下を引き起こす可能性があることに気づいた。 –

+1

事前に列名を知っているので、動的SQLを使用せずにこれを行うことができます。 WHERE行を "(@ Col1 IS NULL OR [Col1] = @ Col1)"に変更するだけで、元のNULL値でこれを行うこともできます。この場合、-1が有効な値として残ります。 – SqlRyan

+0

intにnullを使用していないのは私の習慣です;) – cmsjr

1

あなたが持っているものと同様の方法でそれを行うことができます。

WHERE 
    CASE 
    WHEN @Col1 IS NULL THEN true 
    ELSE [Col1] = @Col1 
    END 
AND 
    CASE 
    WHEN @Col2 IS NULL THEN true 
    ELSE [Col2] = @Col2 
    END 
... 

それとも、おそらく読みにくくものの、それは多くの簡単にすることができます。

WHERE (@Col1 IS NULL OR [Col1] = @Col1]) 
    AND (@Col2 IS NULL OR [Col2] = @Col2]) 
    AND ... 
2

検索がありますまれなオプションの1つ私はどちらかの動的SQLを使用して宣言したり、コードでSQL文字列を構築します。すべてのsproc環境を使用している場合は、sprocで動的SQLを使用してください。 SQLインジェクションを避けるためにsp_executeSQLを実行してください。

関連する問題