为了说明sp_executesql对执行计划的管理优于EXEC,我将使用前面讨论EXEC时用到的代码。
1: DECLARE @TableName VARCHAR(50),@sqlNVARCHAR(MAX),@OrderID INT;
2: SET @TableName = 'Orders ';
3: SET @OrderID = 10251;
4: SET @sql = 'SELECT * FROM '+QUOTENAME(@TableName)+ ' WHERE OrderID = @OID ORDER BY ORDERID DESC'
5: EXEC sp_executesql
6: @stmt = @sql,
7: @params = N'@OID AS INT ',
8: @OID = @OrderID
在调用该代码和检查它生成的执行计划前,先清空缓存中的执行计划;
DBCC FREEPROCCACHE
将上面的动态代码执行3次,每次执行都赋予@OrderID 不同的值,然后查询sys.syscacheobjects表,并注意它的输出,优化器只创建了一个备用计划,而且该计划被重用的3次
SELECT cacheobjtype,objtype,usecounts,sqlFROM sys.syscacheobjects WHERE sql NOT LIKE '%cache%' AND sql NOT LIKE '%sys.%' AND sql NOT LIKE '%sp_executesql%'
点击F5运行,就会出现如下表所示的结果;
sq_executesql的另一个与其接口有关的强大功能是,你可以使用输出参数为调用批处理中的变量返回值。利用该功能可以避免用临时表返回数据,从而得到更高效的代码和更少的重新编译。定义和使用输出参数的语法与存储过程类似。也就是说,你需要在声明参数时指定OUTPUT子句。例如,下面的静态代码简单的演示了如何从动态批处理中利用输出参数@p把值返回到外部批处理中的变量@i.
DECLARE @sql AS NVARCHAR(12),@i AS INT;
SET @sql = N' SET @p = 10';
EXEC sp_executesql
@stmt = @sql,
@params = N'@p AS INT OUTPUT',
@p= @i OUTPUT
SELECT @i
该代码返回输出10