来自MSDN的一行正在讨论using EXEC()
,例如:
SET @sql = 'SELECT foo FROM dbo.bar WHERE x = ''' + @x + ''';';
EXEC(@sql);
在我的测试中,现代版本的SQL Server仍然可以重用这样的计划,但是可能还有其他变量(例如版本,或者例如,如果您WHERE
基于某些参数的存在添加条件子句-在这种情况下,会生成不同的计划)。
如果使用,sp_executesql
则参数值仍然会导致参数嗅探问题(就像使用普通SQL一样),但这与SQL Server是否可以重用该计划无关。该计划将一遍又一遍地使用,就像您根本没有使用sp_executesql
过一样,除非会导致直接查询重新编译的变量,在这种情况下,该计划也将被重新编译(本质上,SQL Server不会存储任何带有计划的计划,其中包括“这是从sp_executesql执行的,但不是):
SET @sql = N'SELECT foo FROM dbo.bar WHERE x = @x;';
EXEC sp_executesql @sql, N'@x VARCHAR(32)', @x;
另外,它具有针对动态SQL的内置保护,避免了由于字符串定界符而使您不必担心将单引号加倍。我在这里写了一些这样的博客。
如果您有计划再利用和/或参数嗅探问题,有些事情你应该考虑是OPTION (RECOMPILE)
,OPTIMIZE FOR
,optimize for ad hoc workloads
和simple/forced parameterization
。为了回应这里最近的网络广播,我回答了一些类似的问题,可能值得一看:
http://sqlperformance.com/performance-palooza
要点是:不要害怕sp_executesql
使用它,而仅在需要时使用它,而在遇到实际性能问题时才花费精力过度优化它。上面的例子很糟糕,因为这里没有理由使用动态SQL-我已经写了这个答案,假设您有合法的用例。