SQL Server 在sp_executesql中使用@ParmDefinition的优点是什么

yxyvkwin  于 2023-01-16  发布在  其他
关注(0)|答案(3)|浏览(135)
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时“字符串构建”似乎更容易一些。

oxf4rvwz

oxf4rvwz1#

第一种情况是容易发生SQL注入并且存在安全风险。讨论到此为止。

7eumitmz

7eumitmz2#

这样就避免了 * 字符串 * 类型的代码--在这种代码中,必须将所有内容转换为字符串,以便将其推到@SQLQueryInnen参数中,然后引入问题,因为必须解决如何安全、明确地执行字符串到正确的原始数据类型的转换。
对于int s,转换问题不是很明显。但是如果你看看人们报告的在datetime s和字符串之间转换问题的数量(在这里和其他论坛上),你会意识到它确实会引起真正的问题。最好始终保持数据的自然类型。

jc3wubiy

jc3wubiy3#

我看到没有人提到最重要的事情之一:当你使用参数化查询时,你的执行计划被缓存。
您的查询是:

SELECT *
FROM someTable
WHERE ID = @id
    AND NAME = @name;

它的执行计划将被存储在内存中,并在每次查询时重用(这是一个很大的好处)。同时,如果你使用字符串连接生成代码,如下所示:

Set @SQLQueryInnen = 'SELECT * FROM someTable WHERE ID = ' + @id + ' AND NAME = ''' + @name + ''''
Execute sp_Executesql @SQLQueryInnen

代码将为每个参数组合生成一个执行计划(除非是重复的),缓存的计划不会被重用。假设您正在传递@Id = 1@Name = 'Paul',生成的查询如下所示:

SELECT *
FROM someTable
WHERE ID = 5
    AND NAME = 'Paul';

如果将名称更改为'Rob',则生成的查询将类似于,SQL Server必须为其创建新计划:

SELECT *
FROM someTable
WHERE ID = 5
    AND NAME = 'Rob';

意思是计划不会被重复使用。希望能有所帮助。
这是一篇更详细地解释这一点的文章:EXEC vs. sp_executeSQL(不要依赖文章标题,它解释了您在问题中提出的确切差异)。
TSQL字符串只生成一次,之后每次使用sp_executesql调用同一查询时,SQLServer都会该高速缓存中检索查询计划并重用它

相关问题