DECLARE @id int
DECLARE @name nvarchar(20)
SET @id = 5
SET @name = 'Paul'
这两个选项之间的区别是什么:
Set @SQLQueryInnen = 'SELECT * FROM someTable WHERE ID = ' + @id + ' AND NAME = ''' + @name + ''''
Execute sp_Executesql @SQLQueryInnen
以及
Set @SQLQueryInnen = 'SELECT * FROM someTable WHERE ID = @id AND NAME = @name'
Set @ParmDefinition = '@id int, @name nvarchar(20)'
Execute sp_Executesql @SQLQueryInnen, @ParmDefinition, @id
到目前为止,我只看到了在使用@ParmDefinition时声明两次@id和@name数据类型的麻烦,另一方面,使用@ ParmDefinition时“字符串构建”似乎更容易一些。
3条答案
按热度按时间oxf4rvwz1#
第一种情况是容易发生SQL注入并且存在安全风险。讨论到此为止。
7eumitmz2#
这样就避免了 * 字符串 * 类型的代码--在这种代码中,必须将所有内容转换为字符串,以便将其推到
@SQLQueryInnen
参数中,然后引入问题,因为必须解决如何安全、明确地执行字符串到正确的原始数据类型的转换。对于
int
s,转换问题不是很明显。但是如果你看看人们报告的在datetime
s和字符串之间转换问题的数量(在这里和其他论坛上),你会意识到它确实会引起真正的问题。最好始终保持数据的自然类型。jc3wubiy3#
我看到没有人提到最重要的事情之一:当你使用参数化查询时,你的执行计划被缓存。
您的查询是:
它的执行计划将被存储在内存中,并在每次查询时重用(这是一个很大的好处)。同时,如果你使用字符串连接生成代码,如下所示:
代码将为每个参数组合生成一个执行计划(除非是重复的),缓存的计划不会被重用。假设您正在传递
@Id = 1
和@Name = 'Paul'
,生成的查询如下所示:如果将名称更改为
'Rob'
,则生成的查询将类似于,SQL Server必须为其创建新计划:意思是计划不会被重复使用。希望能有所帮助。
这是一篇更详细地解释这一点的文章:EXEC vs. sp_executeSQL(不要依赖文章标题,它解释了您在问题中提出的确切差异)。
TSQL字符串只生成一次,之后每次使用sp_executesql调用同一查询时,SQLServer都会该高速缓存中检索查询计划并重用它