建議使用 sp_executesql 而不要使用 EXECUTE 語句執行字符串。支持參數替換不僅使 sp_executesql 比 EXECUTE 更通用,而且還使 sp_executesql 更有效,因為它生成的執行計劃更有可能被 SQL Server 重新使用。
自包含批處理
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. */
sp_executesql N'PRINT @CharVariable'
GO
/* Show database context resetting after sp_executesql completes. */
USE pubs
GO
sp_executesql N'USE Northwind'
GO
/* This statement fails because the database context
has now returned to pubs. */
SELECT * FROM Shippers
GO
替換參數值
sp_executesql 支持對 Transact-SQL 字符串中指定的任何參數的參數值進行替換,但是 EXECUTE 語句不支持。因此,由 sp_executesql 生成的 Transact-SQL 字符串比由 EXECUTE 語句所生成的更相似。SQL Server 查詢優化器可能將來自 sp_executesql 的 Transact-SQL 語句與以前所執行的語句的執行計劃相匹配,以節約編譯新的執行計劃的開銷。
使用 EXECUTE 語句時,必須將所有參數值轉換為字符或 Unicode 并使其成為 Transact-SQL 字符串的一部分:
DECLARE @IntVariable INT
DECLARE @SQLString NVARCHAR(500)
/* Build and execute a string with one parameter value. */
SET @IntVariable = 35
SET @SQLString = N'SELECT * FROM pubs.dbo.employee WHERE job_lvl = ' +
CAST(@IntVariable AS NVARCHAR(10))
EXEC(@SQLString)
/* Build and execute a string with a second parameter value. */
SET @IntVariable = 201
SET @SQLString = N'SELECT * FROM pubs.dbo.employee WHERE job_lvl = ' +
CAST(@IntVariable AS NVARCHAR(10))
EXEC(@SQLString)
如果語句重復執行,則即使僅有的區別是為參數所提供的值不同,每次執行時也必須生成全新的 Transact-SQL 字符串。從而在下面幾個方面產生額外的開銷:
SQL Server 查詢優化器具有將新的 Transact-SQL 字符串與現有的執行計劃匹配的能力,此能力被字符串文本中不斷更改的參數值妨礙,特別是在復雜的 Transact-SQL 語句中。
每次執行時均必須重新生成整個字符串。
每次執行時必須將參數值(不是字符或 Unicode 值)投影到字符或 Unicode 格式。
sp_executesql 支持與 Transact-SQL 字符串相獨立的參數值的設置:
DECLARE @IntVariable INT
DECLARE @SQLString NVARCHAR(500)
DECLARE @ParmDefinition NVARCHAR(500)
/* Build the SQL string once. */
SET @SQLString =
N'SELECT * FROM pubs.dbo.employee WHERE job_lvl = @level'
/* Specify the parameter format once. */
SET @ParmDefinition = N'@level tinyint'
/* Execute the string with the first parameter value. */
SET @IntVariable = 35
EXECUTE sp_executesql @SQLString, @ParmDefinition,
@level = @IntVariable
/* Execute the same string with the second parameter value. */
SET @IntVariable = 32
EXECUTE sp_executesql @SQLString, @ParmDefinition,
@level = @IntVariable
此 sp_executesql 示例完成的任務與前面的 EXECUTE 示例所完成的相同,但有下列額外優點:
因為 Transact-SQL 語句的實際文本在兩次執行之間未改變,所以查詢優化器應該能將第二次執行中的 Transact-SQL 語句與第一次執行時生成的執行計劃匹配。這樣,SQL Server 不必編譯第二條語句。
Transact-SQL 字符串只生成一次。
整型參數按其本身格式指定。不需要轉換為 Unicode。