zoukankan      html  css  js  c++  java
  • 使用 sp_executesql

    建议您在执行字符串时,使用 sp_executesql 存储过程而不要使用 EXECUTE 语句。由于此存储过程支持参数替换,因此 sp_executesql 比 EXECUTE 的功能更多;由于 SQL Server 更可能重用sp_executesql 生成的执行计划,因此 sp_executesql 比 EXECUTE 更有效。

    当 sp_executesql 或 EXECUTE 语句执行字符串时,字符串将作为它的自包含批处理执行。SQL Server 会将字符串中的一个或多个 Transact-SQL 语句编译为独立于批处理(包含 sp_executesql 或 EXECUTE 语句)执行计划的执行计划。下列规则适用于自包含批处理:

    • 在执行 sp_executesql 或 EXECUTE 语句之前,不会将 sp_executesql 或 EXECUTE 字符串中的 Transact-SQL 语句编译到执行计划中。执行字符串之前,不会分析或检查其错误。执行时才对字符串中引用的名称进行解析。

    • 已执行的字符串中的 Transact-SQL 语句不能访问包含 sp_executesql 或 EXECUTE 语句的批处理中声明的任何变量。包含 sp_executesql 或 EXECUTE 语句的批处理不能访问已执行字符串中定义的变量或局部游标。

    • 如果已执行字符串包含一个更改数据库上下文的 USE 语句,则对数据库上下文所做的更改将仅持续到 sp_executesql 或 EXECUTE 语句运行结束。

    运行下列两个批处理说明了这些方面:

     
     
    /*Show not having access to variables from the calling batch. */
    DECLARE @CharVariable CHAR(3);
    SET @CharVariable = 'abc';
    /* sp_executesql fails because @CharVariable has gone out of scope. */
    EXECUTE sp_executesql N'PRINT @CharVariable';
    GO
    
    /* Show database context resetting after sp_executesql finishes. */
    USE master;
    GO
    EXECUTE sp_executesql N'USE AdventureWorks2008R2;'
    GO
    /* This statement fails because the database context
       has now returned to master. */
    SELECT * FROM Sales.Store;
    GO
    

    sp_executesql 支持替换 Transact-SQL 字符串中指定的任何参数值,但 EXECUTE 语句不支持。因此,由 sp_executesql 生成的 Transact-SQL 字符串比那些由 EXECUTE 语句生成的字符串更加相似。SQL Server 查询优化器可能将 sp_executesql 的 Transact-SQL 语句与以前所执行的语句的执行计划相匹配,从而节省编译新的执行计划的开销。

    使用 EXECUTE 语句,所有参数值都必须转换为字符或 Unicode,并成为 Transact-SQL 字符串的一部分。

    如果重复执行语句,则即使只有提供的参数值不同,每次执行时也必须生成全新的 Transact-SQL 字符串。这样就会以下列方式生成额外的开销:

    • 不断更改字符串文本(特别是复杂 Transact-SQL 语句)中的参数值,会影响 SQL Server 查询优化器将新的 Transact-SQL 字符串与现有执行计划相匹配的功能。

    • 每次执行时均必须重新生成整个字符串。

    • 每次执行时必须将参数值(非字符或 Unicode 值)转换为字符或 Unicode 格式。

    sp_executesql 可以单独使用 Transact-SQL 字符串来设置参数值:

     
     
    DECLARE @IntVariable INT;
    DECLARE @SQLString NVARCHAR(500);
    DECLARE @ParmDefinition NVARCHAR(500);
    
    /* Build the SQL string one time. */
    SET @SQLString =
         N'SELECT * FROM AdventureWorks2008R2.Sales.Store WHERE SalesPersonID = @SalesID';
    /* Specify the parameter format one time. */
    SET @ParmDefinition = N'@SalesID int';
    
    /* Execute the string with the first parameter value. */
    SET @IntVariable = 275;
    EXECUTE sp_executesql @SQLString, @ParmDefinition,
                          @SalesID = @IntVariable;
    /* Execute the same string with the second parameter value. */
    SET @IntVariable = 276;
    EXECUTE sp_executesql @SQLString, @ParmDefinition,
                          @SalesID = @IntVariable;
    

    sp_executesql 还另有以下优点:

    • 因为 Transact-SQL 语句的实际文本在两次执行之间未更改,所以查询优化器能够将第二次执行中的 Transact-SQL 语句与第一次执行时生成的执行计划相匹配。因此,SQL Server 不必编译第二条语句。

    • Transact-SQL 字符串只生成一次。

    • 整型参数按其本身格式指定。不需要转换为 Unicode。

      注意注意

      语句字符串中的对象名称必须完全符合 SQL Server 重用执行计划的要求。

    在 SQL Server 早期版本中,唯一可以重用执行计划的方式是将 Transact-SQL 语句定义为存储过程并让应用程序执行该存储过程。这会产生管理应用程序的额外开销。使用 sp_executesql 可有助于减少此开销,并允许 SQL Server 仍重用执行计划。当提供给 Transact-SQL 语句的参数值只有一个变量时,如果要多次执行 Transact-SQL 语句,则可以使用 sp_executesql 而不要使用其他存储过程。因为 Transact-SQL 语句本身保持不变,仅参数值发生更改,所以 SQL Server 查询优化器可能会重用第一次执行时生成的执行计划。

    下面的示例为服务器上的每个数据库(四个系统数据库除外)生成并执行 DBCC CHECKDB 语句。

     
     
    USE master;
    GO
    SET NOCOUNT ON;
    GO
    DECLARE AllDatabases CURSOR FOR
    SELECT name FROM sys.databases WHERE database_id > 4
    OPEN AllDatabases;
    
    DECLARE @DBNameVar NVARCHAR(128);
    DECLARE @Statement NVARCHAR(300);
    
    FETCH NEXT FROM AllDatabases INTO @DBNameVar;
    WHILE (@@FETCH_STATUS = 0)
    BEGIN
       PRINT N'CHECKING DATABASE ' + @DBNameVar;
       SET @Statement = N'USE ' + @DBNameVar + CHAR(13)
          + N'DBCC CHECKDB (' + @DBNameVar + N')' + N'WITH PHYSICAL_ONLY';
       EXEC sp_executesql @Statement;
       PRINT CHAR(13) + CHAR(13);
       FETCH NEXT FROM AllDatabases INTO @DBNameVar;
    END;
    
    CLOSE AllDatabases;
    DEALLOCATE AllDatabases;
    GO
    SET NOCOUNT OFF;
    GO
    

    要执行的 Transact-SQL 语句包含绑定的参数标记时,SQL Server ODBC 驱动程序使用 sp_executesql 来实施 SQLExecDirect。这样,可以将 sp_executesql 提供的优势扩展到使用 ODBC 或通过 ODBC 定义的 API(例如 RDO)的所有应用程序。连接到 SQL Server 的现有 ODBC 应用程序无需重写就可以自动获得性能上的改进。但有一个例外,如果是执行时数据参数,则不能使用sp_executesql。有关详细信息,请参阅使用语句参数

    SQL Server Native Client ODBC 访问接口也使用 sp_executesql 来直接执行带有绑定参数的语句。使用 OLE DB 或 ADO 的应用程序无需重写就可以利用 sp_executesql 具有的优点。

    http://technet.microsoft.com/zh-cn/library/ms175170(v=sql.105).aspx

  • 相关阅读:
    CodeForces 510C Fox And Names (拓扑排序)
    Codeforces 1153D Serval and Rooted Tree (简单树形DP)
    HDU 6437 Problem L.Videos (最大费用)【费用流】
    Luogu P3381 (模板题) 最小费用最大流
    Codeforces 741B Arpa's weak amphitheater and Mehrdad's valuable Hoses (并查集+分组背包)
    Codeforces 1144F Graph Without Long Directed Paths (DFS染色+构造)
    HDU 2204 Eddy's 爱好 (容斥原理)
    Codeforces 939E Maximize! (三分 || 尺取)
    Codeforces 938D. Buy a Ticket (最短路+建图)
    CodeForces 959E Mahmoud and Ehab and the xor-MST (MST+找规律)
  • 原文地址:https://www.cnblogs.com/joe-yang/p/3271085.html
Copyright © 2011-2022 走看看