存储过程EXEC与sp_executesql的区别?

时间:2013-02-06 05:27:37

标签: sql sql-server sql-server-2008 stored-procedures 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'

使用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 个答案:

答案 0 :(得分:18)

除了用法之外,还有一些重要的区别:

  1. UPDATE允许参数化语句 因此,就SQL注入而言,它比MERGE INTO MYTABLE A USING ( SELECT Y, Z, X FROM MYTABLE_TEMP T JOIN (SELECT X FROM TABLE_X WHERE COLUMN_N = '81205' GROUP BY 1) S ON S.X = T.X ) B ON (A.Y = B.Y) AND (A.X = B.X) WHEN MATCHED THEN UPDATE SET /*remove the A.*/ LOAD_DS = B.LOAD_DS WHEN NOT MATCHED THEN INSERT VALUES (B.Y, B.Z, B.X, B.LOAD_DS ); 更安全

  2. sp_executesql可以利用缓存的查询计划。 TSQL字符串只构建一次,之后每次使用EXEC调用相同的查询时,SQL Server从缓存中检索查询计划并重新使用

  3. sp_executesql中创建的临时表不能使用临时表缓存机制

答案 1 :(得分:17)

您的 sp_executesql SQL可能应该是;

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

这将允许您使用@eStatus作为参数调用sp_executesql,而不是将其嵌入到SQL中。这样做的好处是@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'

答案 2 :(得分:4)

使用sp_executesql,您无需像这样构建查询。您可以这样声明:

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

这样,如果您的@Status值来自用户,则可以使用@eStatus,而不必担心转义'。 sp_executesql使您能够以字符串形式将变量放入查询中,而不是使用串联。所以你不必担心。

列和表变量仍然相同,但不太可能直接来自用户。

答案 3 :(得分:2)

使用 Exec 您的T-Sql语句字符串中不能有占位符

sp_executesql的 为您提供占位符的优势,并在运行时

中传递实际值