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看起来有点容易。
答案 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检索查询 从缓存计划并重用它