Reg*_*ser 27 sql sql-server stored-procedures sql-server-2008 sql-server-2012
我写了两个存储过程一个sp_executesql和其他没有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'
Run Code Online (Sandbox Code Playgroud)
下面是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'
Run Code Online (Sandbox Code Playgroud)
Joa*_*son 19
您的sp_executesql SQL可能应该是;
DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' +
@TableName + ' where Status=@eStatus'
Run Code Online (Sandbox Code Playgroud)
这将允许您使用@eStatus作为参数调用sp_executesql,而不是将其嵌入到SQL中.这样做的好处是@eStatus可以包含任何字符,如果需要安全,它将被数据库自动转义.
与EXEC所需的SQL相比;
DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' +
@TableName + ' where Status=' + char(39) + @Status + char(39)
Run Code Online (Sandbox Code Playgroud)
...嵌入在@Status中的char(39)会使您的SQL无效并可能创建SQL注入的可能性.例如,如果将@Status设置为O'Reilly,则生成的SQL将为;
select acol,bcol,ccol FROM myTable WHERE Status='O'Reilly'
Run Code Online (Sandbox Code Playgroud)
FLI*_*KER 19
除了用法之外,还有一些重要的区别:
sp_executesql允许语句参数化因此它比EXECSQL注入更安全
sp_executesql可以利用缓存的查询计划.TSQL字符串只构建一次,之后每次调用相同的查询时sp_executesql,SQL Server从缓存中检索查询计划并重新使用它
创建的EXEC临时表不能使用临时表缓存机制