15

我已经写了两个存储过程,一个与sp_executesql和其他没有sp_executesql的 都被正确地执行相同的结果,我没有得到的是有什么区别这里存储过程EXEC与sp_executesql的区别?

EXEC(@SQL)VS之间EXEC sp_executesql的@SQL,N '@ eStatus VARCHAR(12)', @eStatus = @Status

和EXEC(@SQL)如何容易产生SQL注入和sp_executesql的@SQL ...... ISN “T?

下面的存储过程,而不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

WHOA通过实际的价值!已经停止编码SQL注入!每次调用sp_executesql时,都可能让Internet上的每个joe黑客进入你的服务器。 – SecurityMatt

回答

12

您的sp_executesql SQL可能应该是;

DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' + 
      @TableName + ' where [email protected]' 

这将允许你作为一个参数与@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' 
+0

为什么where子句中不包含'''? –

+0

@ user1095881如果用引号将@eStatus括起来,它将使用_string_'@eStatus'在数据库中搜索,如果使用未引用的@eStatus,则将使用_value_。例如,如果@eStatus是'test','INSERT INTO myTable VALUES(@eStatus)'会插入字符串'test',而'INSERT INTO myTable VALUES('@eStatus')'会插入字符串'@eStatus ”。 –

+0

我认为这在第一个代码示例中缺少结尾'''。 – Sam

4

随着sp_executesql,你不必构建查询这样的。你可以像这样把它声明:

DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' + 
@TableName + ' where [email protected]' 

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

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

11

除了使用情况,有一些重要的区别:

  1. sp_executesql允许语句进行参数 因此它比EXEC更安全的SQL注入方面

  2. sp_executesql能利用缓存的查询计划。 的TSQL字符串是建立只有一次,每一次相同的查询调用与sp_executesql后,SQL Server在高速缓存中检索查询计划,并重新使用它EXEC创建不能使用临时表缓存机制

  3. 临时表

+0

第二个区别是最重要的一个imo(而高回复的答案甚至没有提及它)。 +1 – sotn

+0

谢谢你提及 – FLICKER

1

随着Exec的你不能在你的T-SQL语句字符串占位

sp_executesql的 给你的好处有占位符,并在运行