T-SQL EXEC与sp_exec

时间:2014-11-08 20:49:30

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

我尝试了以下内容:

declare @var2 nvarchar(30)
declare @qsql nvarchar(100)

set @var2 = N'iddelegat'

exec ('select max('+ @var2 + ') as IDexec from delegat');

set @qsql = 'select max(@varsp) as IDspexec from delegat';

exec sp_executesql @qsql, N'@varsp nvarchar(30)', @var2;

结果:

IDexec        IDspexec
-----------------------    
500038       iddelegat

我无法理解为什么sp_executesql不会返回与EXECUTE相同的结果。正确的返回值仅在EXECUTE语句中。似乎sp_executesql没有评估字符串'iddelegat'来返回列。

2 个答案:

答案 0 :(得分:2)

使用sp_executesql时,无法参数化列名或表名。因此,当您在iddelegat中插入值exec()时,您将获得该列。当您将其作为sp_executesql的参数时,您将获得'iddelegat' - 一个包含该列名称的字符串。

SQL文档中没有很好地解释您可以参数化的问题。如果你dig far enough,你会得到这个:

  

您可以使用参数的位置

     

您可以使用参数作为文字值的占位符 - 两者之一   文字或数字值。最常见的是,参数用作   占位符在单个行或组的搜索条件中   (即,在SQL语句的WHERE或HAVING子句中)。

这是文档中一个不起眼的部分,但它有正确的一般概念。

为了帮助进一步理解这一点,SQL引擎可以使用参数编译查询以获取执行计划。为此,它需要知道查询中的实际列和表。在编译步骤之后,可以在中插入额外值 - 参数。

答案 1 :(得分:1)

您无法对列名称进行参数化。

您的尝试与MAX(N'iddelegat')而非MAX(iddelegat)

基本相同

在动态SQL中使用它们的唯一方法是将它们直接连接到字符串中。

如果这样做,您应该使用quotename函数来减轻SQL注入的可能性。

请参阅The curses and blessings of dynamic SQL