sp_executesql
を使用して2つのストアドプロシージャを記述しましたが、sp_executesqlを使用していないストアドプロシージャは両方とも同じ結果を適切に実行しています。
EXEC(@SQL)vs EXEC sp_executesql @ SQL、N '@ eStatus varchar(12)'、@ eStatus = @Status
また、EXEC(@SQL)はSQLインジェクションを起こしやすく、sp_executesql @SQL ......はそうではありませんか?
Sp_executesqlを使用しないストアドプロシージャの下
ALTER proc USP_GetEmpByStatus
(
@Status varchar(12)
)
AS
BEGIN
DECLARE @TableName AS sysname = 'Employee'
Declare @Columns as sysname = '*'
DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' + @TableName + ' where Status=' + char(39) + @Status + char(39)
print (@SQL)
EXEC (@SQL)
END
EXEC USP_GetEmpByStatus 'Active'
以下のストアドプロシージャとsp_executesql
create proc USP_GetEmpByStatusWithSpExcute
(
@Status varchar(12)
)
AS
BEGIN
DECLARE @TableName AS sysname = 'JProCo.dbo.Employee'
Declare @Columns as sysname = '*'
DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' + @TableName + ' where Status=' + char(39) + @Status + char(39)
print @SQL
exec sp_executesql @SQL, N'@eStatus varchar(12)', @eStatus = @Status
END
EXEC USP_GetEmpByStatusWithSpExcute 'Active'
あなたのsp_executesql SQLはおそらくそうです;
DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' +
@TableName + ' where Status=@eStatus'
これにより、SQLに埋め込む代わりに、パラメータとして@eStatusを指定してsp_executesqlを呼び出すことができます。これにより、@ eStatusには任意の文字を含めることができ、安全が必要な場合はデータベースによって自動的に適切にエスケープされるという利点があります。
[〜#〜] exec [〜#〜];に必要なSQLとは対照的です。
DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' +
@TableName + ' where Status=' + char(39) + @Status + char(39)
... @ Statusに埋め込まれたchar(39)は、SQLを無効にし、SQLインジェクションの可能性を作成します。たとえば、@ StatusがO'Reilly
に設定されている場合、結果のSQLは次のようになります。
select acol,bcol,ccol FROM myTable WHERE Status='O'Reilly'
使用法の他に、いくつかの重要な違いがあります。
sp_executesql
を使用すると、ステートメントをパラメーター化できます。したがって、SQLインジェクションに関してはEXEC
よりも安全です。
sp_executesql
は、キャッシュされたクエリプランを活用できます。 TSQL文字列は一度だけ構築され、その後、同じクエリがsp_executesql
で呼び出されるたびに、SQL Serverはキャッシュからクエリプランを取得して再利用します
EXEC
で作成された一時テーブルは、一時テーブルキャッシングメカニズムを使用できません
sp_executesql
、そのようなクエリを作成する必要はありません。次のように宣言できます。
DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' +
@TableName + ' where Status=@eStatus'
このようにすると、@Status
値は、使用できるユーザーからのものです@eStatus
エスケープについて心配する必要はありません'
。 sp_executesqlを使用すると、連結を使用する代わりに、変数を文字列形式でクエリに含めることができます。したがって、心配する必要はありません。
列変数とテーブル変数は同じままですが、ユーザーから直接送信される可能性は低くなります。
WithExecT-Sqlステートメント文字列にプレースホルダーを含めることはできません。
sp_executesqlは、プレースホルダーを持ち、runtimeで実際の値を渡すという利点を提供します