使用sp_executesql执行包含参数的存储过程

时间:2016-07-26 15:41:39

标签: sql-server stored-procedures

我有一个带参数

的简单存储过程
CREATE Procedure GetSupplierForTesting
    (@SupplierId INT)
AS
    SELECT SuppLabel 
    FROM Supplier 
    WHERE Supplier.SupplierId = @SupplierId

我可以使用exec命令在另一个存储过程中调用它,如

exec GetSupplierForTesting @SupplierId = 10

我发现了一篇文章,解释了sp_executesql如何比exec更快。我的问题是我不知道如何调用参数为sp_executesql的存储过程。我试过这段代码

DECLARE @SupplierId INT = 10;
EXEC sp_executesql N'GetSupplierForTesting', N'@SupplierId INT', @SupplierId

但是我收到了一个错误:

  

程序或功能' GetSupplierForTesting'期望参数' @ SupplierId',未提供

2 个答案:

答案 0 :(得分:6)

您需要的语法是

DECLARE @SupplierId INT = 10;

EXEC sys.sp_executesql N'GetSupplierForTesting @SupplierId=@SupplierId', 
                       N'@SupplierId INT', 
                         @SupplierId=@SupplierId

不要这样做。这完全没有意义。使用sp_executesql基本上包装相同的exec语句并在不同的范围内执行它,不会产生任何神奇的性能提升。

只需使用

exec dbo.GetSupplierForTesting @SupplierId = 10

答案 1 :(得分:2)

1

性能问题基于以下假设:当您使用非参数化即席查询时,它(表示此查询的字符串)每次都会不同 - 因为特定参数值是查询文本的一部分。

虽然参数化查询保持身体不变,因为代替where ... and title="asdf"你有where ... and title = @title。只有变量@title的内容发生变化。但是查询文本仍然存在,并且sql server意识到不需要重新编译它。

每次更改其中使用的值时,都会重新编译非参数化查询。

2

您将获得异常,因为您的脚本未将任何参数传递给存储过程。

您的脚本是:'GetSupplierForTesting' - 就是这样。

通过将参数传递给sp_executesql,您将它们传递给scipt。不是脚本中使用的sp,而是脚本本身。 E.g:

exec sp_executesql N'print @val', N'@val int', @val = 1

此脚本确实使用变量@val。你的 - 没有。它只包含proc的名称。因此,您的脚本更正应该是

exec sp_executesql
    N'exec GetSupplierForTesting @Supplier = @Supplier_id_value', 
    N'@Supplier_id_value int',
    @Supplier_id_value = 10
  1. 脚本包含调用sp的代码,此代码将参数传递给sp,其值取自@Supplier_id_value变量
  2. @Supplier_id_value被声明为此脚本内部的int
  3. 10的值传递给脚本的参数
  4. 3

    您正在谈论的性能问题是关于ad-hocs,而不是SP。

    此问题的另一面是参数嗅探问题。有时使用特定的参数值,您的脚本或SP应使用另一个执行计划,与之前传递的参数值的计划不同。

    每次重新编译("慢慢执行")ad-hoc将被(重新)编译以确保并且可能会获得更好的执行计划,而SP或参数化查询可能不会被重新编译并将使用更糟糕,更不理想的执行计划,并且由于重新编译而最终执行速度会慢得多,并且#34;临时查询。

    没有"写这个 - 它会慢慢地工作","写下 - 它会像火箭一样发作#34; sql中的规则。这一切都取决于很多因素。有时人们可能需要专门的ad-hocs,有时候 - 应该完全避免它们。