ユーザーがいくつかのデータ(ステータス、日付など)を介してDigにさまざまなパラメーターを指定できるフォームがあります。
次のようなクエリを作成できます。
SELECT * FROM table WHERE:
status_id = 3
date = <some date>
other_parameter = <value>
etc.各WHERE
はオプションです(status = 3
ですべての行を選択したり、date = 10/10/1980
ですべての行を選択したり、status = 3 AND date = 10/10/1980
ですべての行を選択したりできます。
多数のパラメーターがあり、すべてオプションである場合、動的ストアード・プロシージャーを構成する最良の方法は何ですか?
MySQL、Oracle、SQLServerなど、さまざまなDBに取り組んでいます。
これを達成する最も簡単な方法の1つ:
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インジェクションに関するさらに別のセキュリティ上の懸念を取り除きます。
次のような手順を作成します。
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個のパラメーター、すべてのパラメーター、または#個のパラメーターを使用してプロシージャを実行できます。
これは私が使うスタイルです:
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)
Oracle
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)
それを行うための読みやすく保守可能な方法(JOIN/APPLYでも使用可能):
where
(@parameter1 IS NULL OR your_condition1)
and (@parameter2 IS NULL OR your_condition2)
-- etc
ただし、実行プランはNULL値を無視せず、大規模なパフォーマンスループホールを生成するため(例:すべてのテーブルをスキャンしてNULL値を検索する)、ほとんどの大きなテーブル(さらにJOIN/APPLYを使用)ではお勧めできません。
SQL Serverの迂回方法は、クエリでWITH(RECOMPILE)オプションを使用することです(SQL 2008 SP1 CU5(10.0.2746)以降で使用可能)。
これを(パフォーマンスに関して)実装する最良の方法は、可能な組み合わせごとに1つ、IF ... ELSEブロックを使用することです。たぶん疲れ果てているかもしれませんが、最高のパフォーマンスが得られ、データベース設定は関係ありません。
詳細が必要な場合は、KMを検索できます。答え ここ 。
あなたは次のようなことができます
WHERE
(
ParameterA == 4 OR ParameterA IS NULL
)
AND
(
ParameterB == 12 OR ParameterB IS NULL
)
SQL文字列の動的な構築を回避したい場合(多くの場合は回避するのが最善です)、where句の各基準をデフォルト値と比較することで、ストアドプロシージャでこれを行うことができます。これは、「無視」に相当します。例えば。:
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)