2009-03-30 18 views
30

私は、ユーザーがさまざまなパラメータを指定してデータ(ステータス、日付など)を調べることができるフォームを用意しています。オプションの「WHERE」パラメータを使用したスト​​アドプロシージャ

Iであるクエリを生成することができる:

SELECT * FROM table WHERE: 
status_id = 3 
date = <some date> 
other_parameter = <value> 

等各WHEREは、(I等status = 3 AND date = 10/10/1980date = 10/10/1980、またはすべての行とstatus = 3、またはすべての行とすべての行を選択できるオプションであります)。

すべてのオプションを指定すると、動的ストアドプロシージャを構成する最適な方法は何ですか?

私は、 MySQL、Oracle、SQLServerなど、さまざまなDBに取り組んでいます。これを実現する最も簡単な方法の

答えて

44

ワン:

SELECT * FROM table 
WHERE ((@status_id is null) or (status_id = @status_id)) 
and ((@date is null) or ([date] = @date)) 
and ((@other_parameter is null) or (other_parameter = @other_parameter)) 

など これは完全に動的SQLを排除し、あなたが1つまたは複数のフィールドに検索することができます。動的SQLを削除することで、SQLインジェクションに関するもう1つのセキュリティ上の懸念が取り除かれます。

+2

これでは、すべてのパラメータをオプションにすることはできません。この例では、@status_idを渡す必要があります。ヌルであっても、これを実行するにはnullを渡す必要があります。 – Eppz

+0

MS SQL Serverのパラメータのデフォルト値を指定できます。私はMySQLについてはわかりません –

+4

あなたのRDBMSとそれがどのようにクエリプランをキャッシュするかによって、この方法で最高のパフォーマンスを得ることができないかもしれないことに留意してください。 –

3

あなたは、このようなあなたのプロシージャを作成します

WHERE 
(
ParameterA == 4 OR ParameterA IS NULL 
) 

AND 
(
ParameterB == 12 OR ParameterB IS NULL 
) 
11

ような何かを行うことができます。

CREATE PROCEDURE [dbo].[spXXX] 
    @fromDate datetime = null, 
    @toDate datetime = null, 
    @subCode int = null 
as 
begin 
set NOCOUNT ON 
/* NOCOUNT limits the server feedback on select results record count */ 
SELECT 
    fields... 
FROM 
    source 
WHERE 
    1=1 
--Dynamic where clause for various parameters which may or may not be passed in. 
and (@fromDate is null or [dateField] >= @fromDate) 
and (@toDate is null or [dateField] <= @toDate) 
and (@subCode is null or subCode= @leaveTypeSubCode) 
order by fields... 

これは、あなたが0のparams、すべてのparams、またはのparamsのいずれかの#でプロシージャを実行できるようになります。

1

動的にSQL文字列を作成しないようにしたい場合(よく避けることが多いが)、where節の各criteraをデフォルト値(「無視」に等しい)と比較することで、ストアドプロシージャでこれを行うことができます。例:

select * from Table where 
    (@Col1 IS NULL OR Col1 = @Col1) /*If you don't want to filter in @col, pass in NULL*/ 
    AND 
    (@Col2 IS NULL OR Col2 = @Col2) 
4

これは私が使用するスタイルです:

T-SQL

SELECT *   
FROM table   
WHERE  
status_id = isnull(@status_id ,status_id)  
and date = isnull(@date ,date)  
and other_parameter = isnull(@other_parameter,other_parameter) 

オラクル

SELECT *   
FROM table   
WHERE  
status_id = nval(p_status_id ,status_id)  
and date = nval(p_date ,date)  
and other_parameter = nval(p_other_parameter,other_parameter) 
2

それを行うには読みやすく、メンテナンス性の方法(JOIN/APPLYでも使用可能):

where 
     (@parameter1 IS NULL OR your_condition1) 
    and (@parameter2 IS NULL OR your_condition2) 
-- etc 

あなたの実行計画は、NULL値を無視し、大規模なパフォーマンスの抜け穴(例:発生しないので、それは、最も大きなテーブル(さらに多くの適用/ JOINを使用)に悪い考えですが:NULL値を探し、すべてのテーブルをscaningを)。

SQL Serverのラウンドアバウト方法は、クエリ(SQL 2008 SP1 CU5(10.0.2746)以降で使用可能)にWITH(RECOMPILE)オプションを使用することです。

これを実装する最も良い方法は、可能な組み合わせごとにIF ... ELSEブロックを使用することです。多分それは疲れているかもしれませんが、あなたは最高のパフォーマンスを持っていて、データベースの設定には関係ありません。

詳細が必要な場合は、KMを探すことができます。答え​​。

関連する問題