在sp_executesql中使用@ParmDefinition有什么好处

时间:2015-07-28 08:07:08

标签: sql-server tsql dynamic-sql sp-executesql

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的数据类型的overhad。另一方面,"字符串构建"使用@ParamDefinition看起来有点容易。

3 个答案:

答案 0 :(得分:3)

你避免使用字符串类型的代码 - 你必须将所有内容转换为字符串,以便将其推入@SQLQueryInnen参数,然后引入问题,因为你必须找出如何安全,明确地执行与字符串之间的转换,并将其转换回正确的原始数据类型。

对于int,转化问题并不十分明显。但是,如果你看一下人们在datetime和字符串之间转换问题时报告的问题(这里和其他论坛),你会发现它确实会导致真正的问题。最好将数据保持为自然类型。

答案 1 :(得分:2)

首先是SQL注入和安全风险。讨论在此停止。

答案 2 :(得分:1)

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

您的查询,即:

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调用查询,SQL Server检索查询   从缓存计划并重用它