37

私は 2 つのストアド プロシージャを作成しましたがsp_executesql、一方には sp_executesql があり、もう一方には sp_executesql がありません。両方とも適切に同じ結果を実行しています。ここでの違いは何ですか。

EXEC (@SQL) と 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'
4

3 に答える 3

25

sp_executesql SQL はおそらく次のようになります。

DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' + 
            @TableName + ' where Status=@eStatus'

これにより、@eStatus を SQL に埋め込む代わりに、パラメーターとして 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'
于 2013-02-06T05:38:45.900 に答える
4

With Exec You can't have a place holder in your T-Sql statement string.

sp_executesql gives you the advantage of having a place holder and pass the actual value at runtime

于 2016-09-22T08:04:07.143 に答える
4

ではsp_executesql、そのようなクエリを作成する必要はありません。次のように宣言できます。

DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' + 
@TableName + ' where Status=@eStatus'

このように、@Status値がユーザーからのものである場合は、使用でき@eStatus、エスケープについて心配する必要はありません'。sp_executesql を使用すると、連結を使用する代わりに、変数を文字列形式でクエリに入れることができます。そのため、心配することが少なくなります。

列変数とテーブル変数は同じままですが、ユーザーから直接送信される可能性は低くなります。

于 2013-02-06T05:37:40.370 に答える