動的SQL-EXEC(@SQL)対EXEC SP_EXECUTESQL(@SQL)


95

を使用してSQL Serverのストアドプロシージャで動的SQLコマンドを実行することの現実的な長所と短所は何ですか

EXEC (@SQL)

EXEC SP_EXECUTESQL @SQL

回答:


96

sp_executesqlクエリプランの再利用を促進する可能性が高くなります。を使用する場合sp_executesql、パラメーターは呼び出し署名で明示的に識別されます。この優れた記事はこのプロセスを説明しています

動的SQLの多くの側面についてよく引用されるリファレンスは、Erland Sommarskogの必読の記事です:「動的SQLの呪いと祝福」。


21

SP_EXECUTESQLの大きな点は、パラメーター化されたクエリを作成できることです。これは、SQLインジェクションに関心がある場合に非常に適しています。


1
あなたはそれなしで動的SQLをパラメータ化することができないと思いますか?
DJ。

EXEC( 'SELECT * FROM FOO WHERE ID =?'、123)は、パラメータープレースホルダー "?"を置き換えます 値123でクエリを実行し、SELECT * FROM FOO WHERE ID = 123の結果を返します
Peter Wone

1
おっと、その構文はリンクサーバーでのみ使用できます。
Peter Wone

1
SQLインジェクションを防ぐためにクエリを動的に構築する場合にsp_executesqlを使用する最大の理由の1つです。
Steven Rogers、

5

Microsoftの「sp_executesql使用」の記事sp_executesqlでは、executeステートメントの代わりに使用することを推奨しています。

このストアドプロシージャはパラメータ置換をサポートしているため、sp_executesqlはEXECUTEよりも用途が広いです。また、sp_executesqlはSQL Serverで再利用される可能性が高い実行プランを生成するため、EXECUTEよりもsp_executesqlの方が効率的です。

したがって、要点:ステートメントを使用しないでexecuteください。を使用しsp_executesqlます。


7
あなたの持ち帰りは常に立っているわけではありません。sp_executesqlを使用しても効率が向上しない場合がありますが、SQLインジェクション攻撃からコードを保護できます。ときどき、execを使用するのと同じ方法でsp_executesqlを使用できないため、...誰かが言った-特効薬はありません。同意する。
OzrenTkalcecKrznaric 2013年

はい、マイクロソフトはそれを「より効率的である可能性が高い」と表現するべきでした。また、業界に数年sp_executesqlいるため、交換に使用できないケースを見てきましたexecute。おそらく、私が強調しようとしている点を次のsp_executesqlようにexecute 表現する必要があります。
2013年

2

最近は常にsp_executesqlを使用しますが、それはすべて、パラメーターと変数を処理するEXECのラッパーです。

ただし、特に複数のデータベースにまたがるデータがあり、CONSTRAINTを使用してインデックススキャンを制限している非常に大規模なデータベースでクエリをチューニングする場合は、OPTION RECOMPILEを忘れないでください。

OPTION RECOMPILEを使用しない限り、SQLサーバーはクエリの「1つのサイズですべてに適合する」実行プランを作成しようとし、実行されるたびにフルインデックススキャンを実行します。

これはシークよりもはるかに効率が悪く、クエリを実行していない範囲に制限されているインデックス全体をスキャンする可能性があります。


-2
  1. 変数を宣言する
  2. コマンドで設定し、spのパラメーター値の使用などの動的な部分を追加します(ここで@IsMondayと@IsTuesdayはsp paramsです)。
  3. コマンドを実行する

    declare  @sql varchar (100)
    set @sql ='select * from #td1'
    
    if (@IsMonday+@IsTuesday !='')
    begin
    set @sql= @sql+' where PickupDay in ('''+@IsMonday+''','''+@IsTuesday+''' )'
    end
    exec( @sql)

15
たとえば、 "a '; DROP DATABASE DATABASE_NAME; GO;';"とすると、SQLインジェクションが可能になります。@IsMonday変数内
Erik A.

@IsMondayがintの場合、SQLインジェクションが発生しやすくなりますか?
Vikas Rana

@VikasRana @IsMonday intを動的SQLにすることはできません。@sqlは次のように宣言されていることに注意してくださいvarcharnvarchar
衛輝市郭
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.