使用 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
使用 sp_executesql的更多相关文章
- EXEC sp_executesql
declare @sql nvarchar(max)declare @nu int set @sql='SELECT * FROM [FMTest].[dbo].[FM_Radio_Station]' ...
- SQL Server 中 EXEC 与 SP_EXECUTESQL 的区别
SQL Server 中 EXEC 与 SP_EXECUTESQL 的区别 MSSQL为我们提供了两种动态执行SQL语句的命令,分别是 EXEC 和 SP_EXECUTESQL ,我们先来看一下两种方 ...
- sp_executesql得到执行sql语句的返回值
执行 sql语句,得到 变量的值 ' declare @Partition int; ); ); SET @SQLString = N'SELECT @RangeKeyOUT = $PARTITION ...
- sp_executeSql 用法
今天遇到了一个难题 就是把 一个拼接sql语句 的返回值 赋值给一个变量 经研究 要用sp_executeSql这个存储过程 据说是从sql 2005才开始有的 代码如下: declare @str ...
- 动态SQL语句之sp_executesql的使用
sp_executesql,sql2005中引入的新的系统存储过程,也是用来处理动态sql的, 如: exec sp_executesql @sql, N'@item_name nvarchar(10 ...
- 动态sql语句基本语法--Exec与Exec sp_executesql 的区别
http://www.cnblogs.com/goody9807/archive/2010/10/19/1855697.html 动态sql语句基本语法 1 :普通SQL语句可以用Exec执行 ...
- SQLServer : EXEC和sp_executesql的区别
MSSQL为我们提供了两种动态执行SQL语句的命令,分别是EXEC和sp_executesql.通常,sp_executesql则更具有优势,它提供了输入输出接口,而EXEC没有.还有一个最大的好处就 ...
- sp_executesql 使用
sp_executesql 比 之前的exec @sql 区别在可以实现参数的传入传出 如 declare @sql nvarchar(2000) declare @pid varchar(20) s ...
- sp_executesql的用法
之前做项目的时候负责一个成绩分析的模块儿,写存储过程的时候因为考试的科目是不固定的,所以导致查找成绩的sql语句也是动态的,就用到了sp_executesql,下面就来说一说它的用法 需求:表名是动态 ...
- SQL sp_executesql【转】
execute相信大家都用的用熟了,简写为exec,除了用来执行存储过程,一般都用来执行动态Sql sp_executesql,sql2005中引入的新的系统存储过程,也是用来处理动态sql的, 如: ...
随机推荐
- Configure the Struts Tag Libraries
In Struts framework, you always need to configure the Struts tag libraries in order to access it in ...
- CISCO ASA 防火墙 IOS恢复与升级
在IOS被误清除时的处理办法: 1.从tftp上的ios启动防火墙 防火墙启动后 ,按“ESC”键进入监控模式 rommon #2> ADDRESS=192.168.1.116 rommon # ...
- circle area
circle area Github 链接:传送门 本次作业要求 Create a program that asks for the radius of a circle and prints th ...
- ADT下开发环境的配置--个人配置啦 Eclipse Color Themes
一. Eclipse Color Themes的安装 首先 这个ADT没有Marketplace Client 需要装一个, 节选自: http://blog.csdn.net/liu37226700 ...
- ASP.NET MVC 修改视图的默认路径(MVC2,MVC3)
ASP.NET MVC2 修改视图的默认路径 步骤:1.编写继承自WebFormViewEngine的类,重写视图路径 2.在Application_Start()中添加语句: ViewEngines ...
- Winform XiaoCai.WinformUI 框架界面设计
开源用户界面和布局的套件XiaoCai.WinformUI(美化用户界面利器) http://www.cnblogs.com/aganqin/p/3400453.html 源码下载:https://g ...
- 负margin使用权威指南
自CSS2早在1998年,推荐表的使用已经慢慢褪色成背景和历史书中.正因为如此,CSS布局从那时起一直编码优雅的代名词. 的所有CSS概念设计师所使用,奖项可能需要给负margin的使用是最至少谈论的 ...
- 博客中最快捷的公式显示方式:Mathjax + Lyx
经常为在博客园中显示公式而烦恼的同志们看过来!! 什么是mathjax? 答:就是在web中显示公式用的,基于JavaScript写的,关键是开源,网址http://www.mathjax.org/, ...
- C++之vector中元素删除
今天在删除vector中的元素中遇到一个问题,这里记录下来以便以后查阅. 预备知识:用到了erase()函数,对于一个容器c来说,假设迭代器为p,那么执行: c.erase(p)之后就删除了容器c中p ...
- C++学习笔记之输入、输出和文件
一.流的概念 数据从内存的一个地址移动到另一个地址称为数据流动——流操作 流操作是通过缓冲区(buffer)机制实现的. 缓冲区:内存的一块区域——用作文件与内存交换数据. 数据从文件中读出:文件 → ...