您的当前位置:首页正文

动态sql语句基本语法--Exec与Exec sp_executesql 的区别

2023-11-09 来源:要发发知识网

 2: SET @schemaname=‘dbo‘
 3: SET @tablename=‘Order Details‘
 4:  
 5: EXEC (N‘SELECT COUNT(*) FROM ‘+QUOTENAME(@schemaname)+N‘.‘+QUOTENAME(@tablename)+N‘;‘)

上述代码将会产生如下错误:

消息 102,级别 15,状态 1,第 5 行    ‘QUOTENAME‘ 附近有语法错误。    SQL Server 分析和编译时间:       CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。

SQL Server 执行时间:       CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。   

所以做好的方法是把代码构造到一个变量中,这样就不会受限制了,然后再把该变量作为EXEC命令的输入参数,就像这样:

 1: DECLARE @schemaname NVARCHAR(255) ,
 2: @tablename NVARCHAR(128) ,
 3: @sql NVARCHAR(MAX)
 4: SET @schemaname = ‘dbo‘
 5: SET @tablename = ‘Order Details‘
 6: SET @sql = N‘SELECT COUNT(*) FROM ‘ + QUOTENAME(@schemaname) + N‘.‘
 7: + QUOTENAME(@tablename) + N‘;‘
 8: EXEC (@sql)

 

2、EXEC不提供接口。EXEC(<string>)不提供接口。它唯一的输入就是包含你要调用代码的字符串。动态批处理不能访问在调用批处理中定义的局部变量。如下面代码尝试访问定义在调用批处理中的变量将失败。

 1: DECLARE @i INT 
 2: SET @i = 10248
 3:  
 4: DECLARE @sql NVARCHAR(MAX)
 5:  
 6: SET @sql = ‘SELECT * FROM dbo.Orders WHERE OrderID=@i;‘
 7: EXEC(@sql)

将产生如下错误:

消息 137,级别 15,状态 2,第 1 行    必须声明标量变量 "@i"。

 

使用EXEC时,如果想访问变量,必须把变量内容串联到动态构建的 代码字符串中。

DECLARE @i INT SET @i = 10248DECLARE @sql NVARCHAR(MAX)SET @sql = ‘SELECT * FROM dbo.Orders WHERE OrderID=‘ + CAST(@i AS NVARCHAR(10)) + ‘;‘EXEC(@sql)

这样就没有问题了。

 

如果一个变量包含字符串,把该变量的内容串联到代码将会导致安全风险(SQL注入),为了避免SQL注入,可以吧字符串大小限制为所需的最小长度。当然,实际中这种情况根本不需要动态SQL直接执行SQL语句就可以,这个示例只是为了演示。

 

串联变量的内容存在性能方面的弊端,SQL Server将为每个唯一的查询字符串创建新的即席执行计划,即使查询模式相同也是这样的。为演示这一点,先清空缓存中的执行计划。

DBCC FREEPROCCACHE
将上端代码执行三次,分别为@i赋值10248,10249和10250,然后使用下面的代码查询   
 1: SELECT cacheobjtype ,
 2: objtype ,
 3: usecounts ,
 4: sql
 5: FROM sys.syscacheobjects
 6: WHERE sql NOT LIKE ‘%cache%‘
 7: AND sql NOT LIKE ‘%sys.%‘

得到查询结果:

 

cacheobjtype    objtype    usecounts    sql    Compiled Plan    Adhoc    1    SELECT * FROM dbo.Orders WHERE OrderID=10250;    Compiled Plan    Adhoc    1    SELECT * FROM dbo.Orders WHERE OrderID=10248;    Compiled Plan    Prepared    3    (@1 smallint)SELECT * FROM [dbo].[Orders] WHERE [OrderID]=@1    Compiled Plan    Adhoc    4    SET STATISTICS IO ON SET STATISTICS TIME ON    Compiled Plan    Adhoc    1    SELECT * FROM dbo.Orders WHERE OrderID=10249;    Compiled Plan    Adhoc    4    SET STATISTICS IO OFF SET STATISTICS TIME OFF

 

EXEC除了不支持动态批处理中的输入参数外,也不支持输出参数。默认情况下,EXEC把查询输出返回给调用者。如果你想把输出结果返回给调用批处理中的变量,事情就没那么简单了,为此,你需要使用INSERT EXEC把输出插入到一个目的表,然后再从该表中取值,赋给该变量,就像这样:

 

 1: DECLARE @schemaname NVARCHAR(128) ,
 2: @tablename NVARCHAR(128) ,
 3: @colname NVARCHAR(128) ,
 4: @sql NVARCHAR(MAX) ,
 5: @cnt INT
 6: 
 7: SET @schemaname = ‘dbo‘
 8: SET @tablename = ‘Orders‘
 9: SET @colname = ‘CustomerID‘
 10: 
 11: SET @sql = N‘SELECT COUNT(DISTINCT ‘ + QUOTENAME(@colname) + ‘) FROM ‘
 12: + QUOTENAME(@schemaname) + N‘.‘ + QUOTENAME(@tablename) + N‘;‘
 13: 
 14: CREATE TABLE #T1 ( cnt INT )
 15: INSERT INTO #T1
 16: EXEC ( @sql
 17: )
 18: SELECT @cnt = cnt
 19: FROM #T1
 20: SELECT @cnt
 21: DROP TABLE #T1

3、在SQL Server2000中串联变量值时,EXEC比sp_executesql多一个优势,它支持更长的代码,尽管技术上sp_executesql的输入代码字符串是NTEXT类型的,但你一般是在局部变量中构造代码字符串。而你又不能用大型对象类型声明局部变量,所以,实际上在sp_executesql中执行的查询字符串被限制为Unicode字符串(NVARCHAR)支持的最大长度4000,而EXEC支持常规字符串(VARCHAR)允许最大8000个字符。另外EXEC还支持一个特殊的功能,它允许你在括号中串联多个变量,每个变量都支持8000个字符的长度。

在SQL Server2005中,就不用这么纠结了,因为可以为EXEC命令提供一个VARCHAR(MAX)或NVARCHAR(MAX)的变量作为输入,输入字符串可以达到2GB大小

动态sql语句基本语法--Exec与Exec sp_executesql 的区别

标签:

小编还为您整理了以下内容,可能对您也有帮助:

动态SQL的使用

在介绍动态SQL前我们先看看什么是静态SQL

静态SQL

静态 SQL 语句一般用于嵌入式 SQL 应用中,在程序运行前,SQL 语句必须是确定的,例如 SQL 语句中涉及的列名和表名必须是存在的。静态 SQL 语句的编译是在应用程序运行前进行的,编译的结果会存储在数据库内部。而后程序运行时,数据库将直接执行编译好的 SQL 语句,降低运行时的开销。

动态SQL

动态 SQL 语句是在应用程序运行时被编译和执行的,例如,使用 DB2 的交互式工具 CLP 访问数据库时,用户输入的 SQL 语句是不确定的,因此 SQL 语句只能被动态地编译。动态 SQL 的应用较多,常见的 CLI 和 JDBC 应用程序都使用动态 SQL。

动态SQL作用

动态SQL执行方法

使用EXEC(EXECUTE的缩写)命令和使用SP_EXECUTERSQL。

EXEC命令执行

语法

注:EXECUTE 命令有两个用途,一个是用来执行存储过程,另一个是执行动态SQL

不带参数示例

在变量@SQL中保存了一个字符串,该字符串中包含一条查询语句,再用EXEC调用保存在变量中的批处理代码,我们可以这样写SQL:

EXEC ('SELECT * FROM Customers')

结果如下:

与我们直接执行SELECT * FROM Customers一样。

带参数示例

还是上面的示例,我们换一种写法

DECLARE @SQL AS VARCHAR(100);

DECLARE @Column AS VARCHAR(20);

SET @Column = '姓名'

SET @SQL = 'SELECT ' + @Column + ' FROM Customers';

EXEC (@SQL)

结果如下:

SP_EXECUTERSQL执行

语法

注意:SP_EXECUTERSQL是继EXEC后另一种执行动态SQL的方法。使用这个存储过程更加安全和灵活,因为它支持输入和输出参数。注意的是,与EXEC不同的是,SP_EXECUTERSQL只支持使用Unicode字符串作为其输入的批处理代码。

示例

构造了一个对Customers表进行查询的批处理代码,在其查询过滤条件中使用一个输入参数@CusID

DECLARE @SQL AS NVARCHAR(100);

SET @SQL=N'SELECT * FROM Customers

WHERE 客户ID=@CusID;';

EXEC SP_EXECUTESQL

@STMT=@SQL,

@PARMS=N'@CusID AS INT',

@CusID=1;

结果如下:

代码中将输入参数取值指定为1,但即使采用不同的值在运行这段代码,代码字符串仍然保存相同。这样就可以增加重用以前缓存过的执行计划的机会

怎样SQL存储过程中执行动态SQL语句

存储过程中执行动态Sql语句

MSSQL为我们提供了两种动态执行SQL语句的命令,分别是EXEC和sp_executesql;通常,sp_executesql则更具有优势,它提供了输入输出接口,而EXEC没有。还有一个最大的好处就是利用sp_executesql,能够重用执行计划,这就大大提供了执行性能,还可以编写更安全的代码。EXEC在某些情况下会更灵活。除非您有令人信服的理由使用EXEC,否侧尽量使用sp_executesql.

1.EXEC的使用

EXEC命令有两种用法,一种是执行一个存储过程,另一种是执行一个动态的批处理。以下所讲的都是第二种用法。

下面先使用EXEC演示一个例子,代码1

代码

DECLARE @TableName VARCHAR(50),@Sql NVARCHAR (MAX),@OrderID INT;

SET @TableName = 'Orders';

SET @OrderID = 10251;

SET @sql =

    'SELECT * FROM '+QUOTENAME(@TableName) +'WHERE OrderID = '+

    CAST(@OrderID AS VARCHAR(10))+' ORDER BY ORDERID DESC'

EXEC(@sql);

注:这里的EXEC括号中只允许包含一个字符串变量,但是可以串联多个变量,如果我们这样写EXEC:

EXEC('SELECT TOP('+ CAST(@TopCount AS VARCHAR(10)) +')* FROM '+

          QUOTENAME(@TableName) +' ORDER BY ORDERID DESC');

SQL编译器就会报错,编译不通过,而如果我们这样:

EXEC(@sql+@sql2+@sql3);

编译器就会通过;

所以最佳的做法是把代码构造到一个变量中,然后再把该变量作为EXEC命令的输入参数,这样就不会受了。

EXEC的缺点是不提供接口,这里的接口是指,它不能执行一个包含一个带变量符的批处理,如下

代码

DECLARE @TableName VARCHAR(50),@Sql NVARCHAR(MAX),@OrderID INT;

SET @TableName = 'Orders';

SET @OrderID = 10251;

SET @sql = 'SELECT * FROM '+QUOTENAME(@TableName) +

    'WHERE OrderID = @OrderID ORDER BY ORDERID DESC'

EXEC(@sql);

关键就在SET @sql这一句话中,如果我们运行这个批处理,编译器就会产生一下错误

Msg 137, Level 15, State 2, Line 1

必须声明标量变量 "@OrderID"。

使用EXEC时,如果您想访问变量,必须把变量内容串联到动态构建的代码字符串中,如:

SET @sql = 'SELECT * FROM '+QUOTENAME(@TableName) +   'WHERE OrderID = '+CAST(@OrderID AS VARCHAR(10))+' ORDER BY ORDERID DESC'

串联变量的内容也存在性能方面的弊端。SQL Server为每一个的查询字符串创建新的执行计划,即使查询模式相同也是这样。为演示这一点,先清空缓存中的执行计划

DBCC FREEPROCCACHE (这个不是本文所涉及的内容,您可以查看MS的MSDN)

将代码1运行3次,分别对@OrderID 赋予下面3个值,10251,10252,10253。然后使用下面的代码查询

SELECT cacheobjtype,objtype,usecounts,sql FROM sys.syscacheobjects WHERE sql NOT LIKE '%cach%' AND sql NOT LIKE '%sys.%'

点击F5运行,我们可以看到,每执行一次都要产生一次的编译,执行计划没有得到充分重用。

EXEC除了不支持动态批处理中的输入参数外,他也不支持输出参数。默认情况下,EXEC把查询的输出返回给调用者。例如下面代码返回Orders表中所有的记录数

DECLARE @sql NVARCHAR(MAX)

SET @sql = 'SELECT COUNT(ORDERID) FROM Orders';

EXEC(@sql);

然而,如果你要把输出返回给调用批处理中的变量,事情就没有那么简单了。为此,你必须使用INSERT EXEC语法把输出插入到一个目标表中,然后从这表中获取值后赋给该变量,就像这样:

代码

DECLARE @sql NVARCHAR(MAX),@RecordCount INT

SET @sql = 'SELECT COUNT(ORDERID) FROM Orders';

CREATE TABLE #T(TID INT);

INSERT INTO #T EXEC(@sql);

SET @RecordCount = (SELECT TID FROM #T)

SELECT @RecordCount

DROP TABLE #T2

2.sp_executesql的使用

sp_executesql命令在SQL Server中引入的比EXEC命令晚一些,它主要为重用执行计划提供更好的支持。

为了和EXEC作一个鲜明的对比,我们看看如果用代码1的代码,把EXEC换成sp_executesql,看看是否得到我们所期望的结果

代码

DECLARE @TableName VARCHAR(50),@sql NVARCHAR(MAX),@OrderID INT ,@sql2 NVARCHAR(MAX);

SET @TableName = 'Orders ';

SET @OrderID = 10251;

SET @sql = 'SELECT * FROM '+QUOTENAME(@TableName) + ' WHERE OrderID = '+CAST(@OrderID AS VARCHAR(50)) + ' ORDER BY ORDERID DESC'

EXEC sp_executesql @sql

注意最后一行;事实证明可以运行;

sp_executesql提供接口

sp_executesql命令比EXEC命令更灵活,因为它提供一个接口,该接口及支持输入参数也支持输出参数。这功能使你可以创建带参数的查询字符串,这样就可以比EXEC更好的重用执行计划,sp_executesql的构成与存储过程非常相似,不同之处在于你是动态构建代码。它的构成包括:代码快,参数声明部分,参数赋值部分。说了这么多,还是看看它的语法:

EXEC sp_executesql

@stmt= <statement>,--类似存储过程主体

@params = <params>, --类似存储过程参数部分,声明参数类型

<params assignment> --类似存储过程调用,为参数赋值,参数值要和参数顺序要一一对应,也可以通过为参数指明参数值的方式为其赋值

@stmt参数是输入的动态批处理,它可以引入输入参数或输出参数,和存储过程的主体语句一样,只不过它是动态的,而存储过程是静态的,不过你也可以在存储过程中使用sp_executesql;

@params参数与定义输入/输出参数的存储过程头类似,实际上和存储过程头的语法完全一样;

@<params assignment> 与调用存储过程的EXEC部分类似。

其实@stmt,@params可以省略,那么exec sp_executesql的语法就可以简写成如下格式:

EXEC sp_executesql

<statement>,

<params>,

<params assignment>

为了说明sp_executesql对执行计划的管理优于EXEC,我将使用前面讨论EXEC时用到的代码。

代码

DECLARE @TableName VARCHAR(50),@sql NVARCHAR(MAX),@OrderID INT;

SET @TableName = 'Orders ';

SET @OrderID = 10251;

SET @sql = 'SELECT * FROM '+@TableName + ' WHERE OrderID = @OID ORDER BY ORDERID DESC'

--注意当要对动态sql语句的表名实行参数化时,不可以如下表示:

--set @sql='select * from @TableName where OrderID=@OID ORDER BY Orderid desc',

--如果这样会提示必须声明标量变量@TableName,只可以如上面所写的一样,将表名@TableName作为变量名进行拼接

EXEC sp_executesql

@sql,

N'@OID int ',

@OID = @OrderID

下面我们看看exec sp_executesql的执行效率,在调用该代码和检查它生成的执行计划前,先清空缓存中的执行计划;

DBCC FREEPROCCACHE

将上面的动态代码执行3次,每次执行都赋予@OrderID 不同的值,然后查询sys.syscacheobjects表,并注意它的输出,优化器只创建了一个备用计划,而且该计划被重用的3次

SELECT cacheobjtype,objtype,usecounts,sql FROM 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

@sql,

N'@p AS INT OUTPUT',

@p = @i OUTPUT

SELECT @i --该代码返回输出10

以字母 N 为前缀标识 Unicode 字符串常量

总结以下几点:

一.使用exce sp_executesql效率比exec要高,同一类型的语句,只需编译一次即可,而exec执行几次就需要编译几次。

二.构造动态sql的where子句,也就是条件子句时,exec无法使用变量来进行站位,需要将变量转换成字符串,然后和动态sql进行拼接,这就可能引起Sql注入问题,如下:

SET @sql = 'SELECT * FROM '+QUOTENAME(@TableName) +

  ' WHERE OrderID = '+CAST(@OrderID AS VARCHAR(50)) + ' ORDER BY ORDERID DESC'

而若使用exec sp_executesql则可以使用变量来进行站位,以后再给这个参数传值的放式构造动态sql,就避免的Sql注入的问题,如下:

SET @sql = 'SELECT * FROM '+@TableName + ' WHERE OrderID = @OID ORDER BY ORDERID DESC'

三.无论是Exec还是Exec sp_executesql,如果想要将表名和列名进行动态参数化,不可以使用表名参数和列名参数来进行站位,而且表名参数和列名参数需要使用存储过程的参数.对 于exec sp_executesql来说,不可以将表名参数和列名参数在指定为在exec sp_executesql参数声明部分声明的参数,如:

代码

create PROCEDURE GetData

@tbName nvarchar(10),

@colName nvarchar(10),

@Name nvarchar(10)

AS

BEGIN

declare @sql nvarchar(50);

set @sql='select '+ @colName+' from ' +@tbName+ ' where name=@whereName';

--注意此句不可以写成如下:

-- set @sql='select @colName from @tbName where name=@whereName';

exec sp_executesql

@sql,

N'@whereName nvarchar(10)',

@Name

END

数据库的“EXEC”是什么意思?应该怎么用?

sqlserver中x0dx0aEXEC命令有两种用法,一种是执行一个存储过程,另一种是执行一个动态的批处理x0dx0ax0dx0a1.使用系统存储过程sp_executesql运行Unicode命令字符串x0dx0a语法如下:x0dx0asp_executesql [@stmt=] stmtx0dx0a[x0dx0a {,[@params=] N'@parameter_name data_type [,...n]'}x0dx0a {,[@param1=] 'value' [,...n]}x0dx0a]x0dx0a说明:必须先将各个包含所要运行的命令语句的Unicode字符串相加在一起,再交给系统存储过程sp_executesql来运行,而不能在sp_executesql的语句中来相加各个命令字符串。x0dx0a举例如下:x0dx0adeclare @DBName nvarchar(20),x0dx0a @Tbname nvarchar(20),x0dx0a @SQLString nvarchar(500)x0dx0aset @DBName=N'Northwind'x0dx0aset @Tbname=N'Customers'x0dx0aset @SQLString=N'USE '+@DBName+char(13) --char(13)换行x0dx0aSET @SQLString=@SQLString+N'select * from '+@Tbnamex0dx0a--必须先将命令字符串组合完毕后再交给sp_executesql来运行x0dx0aexec sp_executesql @SQLStringx0dx0ax0dx0a2.使用EXECUTE命令运行命令字符串x0dx0a要使用EXECUTE命令来运行一个命令字符串的语法如下:x0dx0aEXEC[UTE] ({@string_variable|[N] 'stql_string'} [+...n])x0dx0a从语法看出,可以先将包含所要运行的命令的字符串赋给一个局部变量@string_variable,再使用EXECUTE命令来运行,或是直接使用EXECUTE命令去运行一个包含所要运行的命令语句的字符串。此外,您也可以将多个包含所要运行的命令语句的字符串相加在一起,再交给EXECUTE命令来一次运行。x0dx0ax0dx0a例:x0dx0adeclare @sql nvarchar(4000) x0dx0a set @sql='select * from [表] where email=''test@163.com''' x0dx0a exec (@sql)

sqlserver中exec和execute的区别

在项目中需要将内部DECLARE的参数通过EXEC赋值后再作为下面一个EXEC参数的时候,发现都使用EXEC时,问题就不是那么简单了。
趁着没有睡意研究下。
EXEC的使用与缺点
EXEC命令有两种用法,一种是执行一个存储过程,另一种是执行一个动态的批处理

一般的使用如下,做动态SQL语句拼接,然后执行

 技术分享

然而上面这样的拼接语句又称为“串联变量”,而串联变量是不支持执行计划的,在我的演示代码中我已加了测试的SQL语句。
使用DBCC FREEPROCCACHE清空缓存。(具体使用可以查看MS的MSDN:http://msdn.microsoft.com/zh-cn/library/ms174283.aspx)

在输出的数据中我们很清楚的看到系统执行了两次,没有很好地使用执行计划

 技术分享

而最重要的是当我有下面这样的需求

 技术分享

出错啦!

 技术分享

 然而我们发现这样的需求变相也是可以满足的,就是有点麻烦了,解决方案如下,使用临时表

 技术分享

 sp_executesql的使用

使用sp_executesql的话,一切将变的很简单
sp_executesql命令比EXEC命令更灵活,因为它提供一个接口,该接口及支持输入参数也支持输出参数。这功能使你可以创建带参数的查询字符串,这样就可以比EXEC更好的重用执行计划,sp_executesql的构成与存储过程非常相似,不同之处在于你是动态构建代码。它的构成包括:代码快,参数声明部分,参数赋值部分。
sp_executesql的语法
EXEC sp_executesql
@stmt = <statement>,--类似存储过程主体
@params = <params>, --类似存储过程参数部分
<params assignment> --类似存储过程调用
@stmt参数是输入的动态批处理,它可以引入输入参数或输出参数,和存储过程的主体语句一样,只不过它是动态的,而存储过程是静态的,不过你也可以在存储过程中使用sp_executesql;
@params参数与定义输入/输出参数的存储过程头类似,实际上和存储过程头的语法完全一样;
@<params assignment> 与调用存储过程的EXEC部分类似。
现在我们按照sp_executesql的语法改造下上面的查询

 技术分享

 查看执行计划的调用,很好的利用了已有的执行计划提升查询效率

技术分享

 我们再去看上面那个需要使用临时表的问题

代码如下,可以将@TitleOutPut取出后再作为查询的参数给@TitleInPut赋值。

难题得解!

技术分享 

EXEC与sp_executesql的区别及应用

标签:技术分享   http   调用   img   代码   sql命令   字符   ros   exec   

sqlserver中exec和execute的区别

在项目中需要将内部DECLARE的参数通过EXEC赋值后再作为下面一个EXEC参数的时候,发现都使用EXEC时,问题就不是那么简单了。
趁着没有睡意研究下。
EXEC的使用与缺点
EXEC命令有两种用法,一种是执行一个存储过程,另一种是执行一个动态的批处理

一般的使用如下,做动态SQL语句拼接,然后执行

 技术分享

然而上面这样的拼接语句又称为“串联变量”,而串联变量是不支持执行计划的,在我的演示代码中我已加了测试的SQL语句。
使用DBCC FREEPROCCACHE清空缓存。(具体使用可以查看MS的MSDN:http://msdn.microsoft.com/zh-cn/library/ms174283.aspx)

在输出的数据中我们很清楚的看到系统执行了两次,没有很好地使用执行计划

 技术分享

而最重要的是当我有下面这样的需求

 技术分享

出错啦!

 技术分享

 然而我们发现这样的需求变相也是可以满足的,就是有点麻烦了,解决方案如下,使用临时表

 技术分享

 sp_executesql的使用

使用sp_executesql的话,一切将变的很简单
sp_executesql命令比EXEC命令更灵活,因为它提供一个接口,该接口及支持输入参数也支持输出参数。这功能使你可以创建带参数的查询字符串,这样就可以比EXEC更好的重用执行计划,sp_executesql的构成与存储过程非常相似,不同之处在于你是动态构建代码。它的构成包括:代码快,参数声明部分,参数赋值部分。
sp_executesql的语法
EXEC sp_executesql
@stmt = <statement>,--类似存储过程主体
@params = <params>, --类似存储过程参数部分
<params assignment> --类似存储过程调用
@stmt参数是输入的动态批处理,它可以引入输入参数或输出参数,和存储过程的主体语句一样,只不过它是动态的,而存储过程是静态的,不过你也可以在存储过程中使用sp_executesql;
@params参数与定义输入/输出参数的存储过程头类似,实际上和存储过程头的语法完全一样;
@<params assignment> 与调用存储过程的EXEC部分类似。
现在我们按照sp_executesql的语法改造下上面的查询

 技术分享

 查看执行计划的调用,很好的利用了已有的执行计划提升查询效率

技术分享

 我们再去看上面那个需要使用临时表的问题

代码如下,可以将@TitleOutPut取出后再作为查询的参数给@TitleInPut赋值。

难题得解!

技术分享 

EXEC与sp_executesql的区别及应用

标签:技术分享   http   调用   img   代码   sql命令   字符   ros   exec   

怎样SQL存储过程中执行动态SQL语句

1.EXEC的使用

EXEC命令有两种用法,一种是执行一个存储过程,另一种是执行一个动态的批处理。以下所讲的都是第二种用法。

下面先使用EXEC演示一个例子,代码1

DECLARE @TableName VARCHAR(50),@Sql NVARCHAR (MAX),@OrderID INT;

SET @TableName = 'Orders';

SET @OrderID = 10251;

SET @sql =

    'SELECT * FROM '+QUOTENAME(@TableName) +'WHERE OrderID = '+

    CAST(@OrderID AS VARCHAR(10))+' ORDER BY ORDERID DESC'

EXEC(@sql);

sp_executesql命令在SQL Server中引入的比EXEC命令晚一些,它主要为重用执行计划提供更好的支持。

为了和EXEC作一个鲜明的对比,我们看看如果用代码1的代码,把EXEC换成sp_executesql,看看是否得到我们所期望的结果

DECLARE @TableName VARCHAR(50),@sql NVARCHAR(MAX),@OrderID INT ,@sql2 NVARCHAR(MAX);

SET @TableName = 'Orders ';

SET @OrderID = 10251;

SET @sql = 'SELECT * FROM '+QUOTENAME(@TableName) + ' WHERE OrderID = '+CAST(@OrderID AS VARCHAR(50)) + ' ORDER BY ORDERID DESC'

EXEC sp_executesql @sql

SQL Server执行动态SQL正确方式

SQL Server执行动态SQL的话 应该如何实现呢?下面就为您介绍SQL Server执行动态SQL两种正确方式 希望可以让您对SQL Server执行动态SQL有更深的了解

动态SQL:code that is executed dynamically 它一般是根据用户输入或外部条件动态组合的SQL语句块 动态SQL能灵活的发挥SQL强大的功能 方便的解决一些其它方法难以解决的问题 相信使用过动态SQL的人都能体会到它带来的便利 然而动态SQL有时候在执行性能(效率)上面不如静态SQL 而且使用不恰当 往往会在安全方面存在隐患(SQL 注入式攻击)

动态SQL可以通过EXECUTE 或SP_EXECUTESQL这两种方式来执行

EXECUTE

执行 Transact SQL 批中的命令字符串 字符串或执行下列模块之一:系统存储过程 用户定义存储过程 标量值用户定义函数或扩展存储过程 SQL Server 扩展了 EXECUTE 语句 以使其可用于向链接服务器发送传递命令 此外 还可以显式设置执行字符串或命令的上下文

SP_EXECUTESQL

执行可以多次重复使用或动态生成的 Transact SQL 语句或批处理 Transact SQL 语句或批处理可以包含嵌入参数 在批处理 名称作用域和数据库上下文方面 SP_EXECUTESQL 与 EXECUTE 的行为相同 SP_EXECUTESQL stmt 参数中的 Transact SQL 语句或批处理在执行 SP_EXECUTESQL 语句时才编译 随后 将编译 stmt 中的内容 并将其作为执行计划运行 该执行计划独立于名为 SP_EXECUTESQL 的批处理的执行计划 SP_EXECUTESQL 批处理不能引用调用 SP_EXECUTESQL 的批处理中声明的变量 SP_EXECUTESQL 批处理中的本地游标或变量对调用 SP_EXECUTESQL 的批处理是不可见的 对数据库上下文所作的更改只在 SP_EXECUTESQL 语句结束前有效

如果只更改了语句中的参数值 则 sp_executesql 可用来代替存储过程多次执行 Transact SQL 语句 因为 Transact SQL 语句本身保持不变 仅参数值发生变化 所以 SQL Server 查询优化器可能重复使用首次执行时所生成的执行计划

一般来说 我们推荐 优先使用SP_EXECUTESQL来执行动态SQL 一方面它更加灵活 可以有输入输出参数 另外一方面 查询优化器更有可能重复使用执行计划 提高执行效率 还有就是使用SP_EXECUTESQL能提高安全性;当然也不是说要完全摈弃EXECUTE 在特定场合下 EXECUTE比SP_EXECUTESQL更方便些 比如动态SQL字符串是VARCHAR类型 不是NVARCHAR类型 SP_EXECUTESQL 只能执行是Unicode的字符串或是可以隐式转换为ntext的常量或变量 而EXECUTE则两种类型的字符串都能执行

下面我们来对比看看EXECUTE 和SP_EXECUTESQL的一些细节地方

EXECUTE(N SELECT * FROM Groups ) 执行成功

EXECUTE( SELECT * FROM Groups ) 执行成功

SP_EXECUTESQL N SELECT * FROM Groups ; 执行成功

SP_EXECUTESQL SELECT * FROM Groups 执行出错

Summary:EXECUTE 可以执行非Unicode或Unicode类型的字符串常量 变量 而SP_EXECUTESQL只能执行Unicode或可以隐式转换为ntext的字符串常量 变量

DECLARE @GroupName VARCHAR( );SET@GroupName = SuperAdmin ;

EXECUTE( SELECT * FROM Groups WHERE GroupName= + SUBSTRING(@GroupName ) + ); SUBSTRING 附近有语法错误

DECLARE @Sql VARCHAR( );

DECLARE @GroupName VARCHAR( );SET@GroupName = SuperAdmin ;

SET@Sql= SELECT * FROM Groups WHERE GroupName= + SUBSTRING(@GroupName ) +

PRINT @Sql;EXECUTE(@Sql);

Summary:EXECUTE 括号里面只能是字符串变量 字符串常量 或它们的连接组合 不能调用其它一些函数 存储过程等 如果要使用 则使用变量组合 如上所示

DECLARE @Sql VARCHAR( );

DECLARE @GroupName VARCHAR( );SET@GroupName = SuperAdmin ;

SET@Sql= SELECT * FROM Groups WHEREGroupName=@GroupName

PRINT @Sql;EXECUTE(@Sql); 出错:必须声明标量变量 “@GroupName” SET@Sql= SELECT * FROM Groups WHERE GroupName= + QUOTENAME(@GroupName )

EXECUTE(@Sql); 正确:

DECLARE @Sql NVARCHAR( );

DECLARE @GroupName NVARCHAR( );SET@GroupName = SuperAdmin ;

SET@Sql= SELECT * FROM Groups WHEREGroupName=@GroupName

PRINT @Sql;

EXEC SP_EXECUTESQL @Sql N @GroupNameNVARCHAR @GroupName

查询出来没有结果 没有声明参数长度

DECLARE @Sql NVARCHAR( );

DECLARE @GroupName NVARCHAR( );SET@GroupName = SuperAdmin ;

SET@Sql = SELECT * FROM Groups WHERE GroupName=@GroupName

PRINT @Sql;

EXEC SP_EXECUTESQL @Sql N @GroupName NVARCHAR( ) @GroupName

Summary:动态批处理不能访问定义在批处理里的局部变量 SP_EXECUTESQL 可以有输入输出参数 比EXECUTE灵活

下面我们来看看EXECUTE SP_EXECUTESQL的执行效率 首先把缓存清除执行计划 然后改变用@GroupName值SuperAdmin CommonUser CommonAdmin分别执行三次 然后看看其使用缓存的信息

DBCC FREEPROCCACHE;

DECLARE @Sql VARCHAR( );

DECLARE @GroupName VARCHAR( );SET@GroupName = SuperAdmin ; CommonUser CommonAdmin

SET@Sql = SELECT * FROM Groups WHERE GroupName= + QUOTENAME(@GroupName )

EXECUTE(@Sql); SELECTcacheobjtype objtype usecounts sql

FROM sys syscacheobjects

WHERE sql NOTLIKE %cache%

ANDsql NOTLIKE %sys % ;

依葫芦画瓢 接着我们看看SP_EXECUTESQL的执行效率

DBCC FREEPROCCACHE;

DECLARE @Sql NVARCHAR( );

DECLARE @GroupName NVARCHAR( );SET@GroupName = SuperAdmin ; CommonUser CommonAdmin

SET@Sql = SELECT * FROM Groups WHERE GroupName=@GroupName

EXECUTESP_EXECUTESQL @Sql N @GroupName NVARCHAR( ) @GroupName;

SELECTcacheobjtype objtype usecounts sql

FROM sys syscacheobjects

WHERE sql NOTLIKE %cache%

ANDsql NOTLIKE %sys % ;

lishixin/Article/program/SQLServer/201311/22279

    SQL Server执行动态SQL正确方式

    SQL Server执行动态SQL的话 应该如何实现呢?下面就为您介绍SQL Server执行动态SQL两种正确方式 希望可以让您对SQL Server执行动态SQL有更深的了解

    动态SQL:code that is executed dynamically 它一般是根据用户输入或外部条件动态组合的SQL语句块 动态SQL能灵活的发挥SQL强大的功能 方便的解决一些其它方法难以解决的问题 相信使用过动态SQL的人都能体会到它带来的便利 然而动态SQL有时候在执行性能(效率)上面不如静态SQL 而且使用不恰当 往往会在安全方面存在隐患(SQL 注入式攻击)

    动态SQL可以通过EXECUTE 或SP_EXECUTESQL这两种方式来执行

    EXECUTE

    执行 Transact SQL 批中的命令字符串 字符串或执行下列模块之一:系统存储过程 用户定义存储过程 标量值用户定义函数或扩展存储过程 SQL Server 扩展了 EXECUTE 语句 以使其可用于向链接服务器发送传递命令 此外 还可以显式设置执行字符串或命令的上下文

    SP_EXECUTESQL

    执行可以多次重复使用或动态生成的 Transact SQL 语句或批处理 Transact SQL 语句或批处理可以包含嵌入参数 在批处理 名称作用域和数据库上下文方面 SP_EXECUTESQL 与 EXECUTE 的行为相同 SP_EXECUTESQL stmt 参数中的 Transact SQL 语句或批处理在执行 SP_EXECUTESQL 语句时才编译 随后 将编译 stmt 中的内容 并将其作为执行计划运行 该执行计划独立于名为 SP_EXECUTESQL 的批处理的执行计划 SP_EXECUTESQL 批处理不能引用调用 SP_EXECUTESQL 的批处理中声明的变量 SP_EXECUTESQL 批处理中的本地游标或变量对调用 SP_EXECUTESQL 的批处理是不可见的 对数据库上下文所作的更改只在 SP_EXECUTESQL 语句结束前有效

    如果只更改了语句中的参数值 则 sp_executesql 可用来代替存储过程多次执行 Transact SQL 语句 因为 Transact SQL 语句本身保持不变 仅参数值发生变化 所以 SQL Server 查询优化器可能重复使用首次执行时所生成的执行计划

    一般来说 我们推荐 优先使用SP_EXECUTESQL来执行动态SQL 一方面它更加灵活 可以有输入输出参数 另外一方面 查询优化器更有可能重复使用执行计划 提高执行效率 还有就是使用SP_EXECUTESQL能提高安全性;当然也不是说要完全摈弃EXECUTE 在特定场合下 EXECUTE比SP_EXECUTESQL更方便些 比如动态SQL字符串是VARCHAR类型 不是NVARCHAR类型 SP_EXECUTESQL 只能执行是Unicode的字符串或是可以隐式转换为ntext的常量或变量 而EXECUTE则两种类型的字符串都能执行

    下面我们来对比看看EXECUTE 和SP_EXECUTESQL的一些细节地方

    EXECUTE(N SELECT * FROM Groups ) 执行成功

    EXECUTE( SELECT * FROM Groups ) 执行成功

    SP_EXECUTESQL N SELECT * FROM Groups ; 执行成功

    SP_EXECUTESQL SELECT * FROM Groups 执行出错

    Summary:EXECUTE 可以执行非Unicode或Unicode类型的字符串常量 变量 而SP_EXECUTESQL只能执行Unicode或可以隐式转换为ntext的字符串常量 变量

    DECLARE @GroupName VARCHAR( );SET@GroupName = SuperAdmin ;

    EXECUTE( SELECT * FROM Groups WHERE GroupName= + SUBSTRING(@GroupName ) + ); SUBSTRING 附近有语法错误

    DECLARE @Sql VARCHAR( );

    DECLARE @GroupName VARCHAR( );SET@GroupName = SuperAdmin ;

    SET@Sql= SELECT * FROM Groups WHERE GroupName= + SUBSTRING(@GroupName ) +

    PRINT @Sql;EXECUTE(@Sql);

    Summary:EXECUTE 括号里面只能是字符串变量 字符串常量 或它们的连接组合 不能调用其它一些函数 存储过程等 如果要使用 则使用变量组合 如上所示

    DECLARE @Sql VARCHAR( );

    DECLARE @GroupName VARCHAR( );SET@GroupName = SuperAdmin ;

    SET@Sql= SELECT * FROM Groups WHEREGroupName=@GroupName

    PRINT @Sql;EXECUTE(@Sql); 出错:必须声明标量变量 “@GroupName” SET@Sql= SELECT * FROM Groups WHERE GroupName= + QUOTENAME(@GroupName )

    EXECUTE(@Sql); 正确:

    DECLARE @Sql NVARCHAR( );

    DECLARE @GroupName NVARCHAR( );SET@GroupName = SuperAdmin ;

    SET@Sql= SELECT * FROM Groups WHEREGroupName=@GroupName

    PRINT @Sql;

    EXEC SP_EXECUTESQL @Sql N @GroupNameNVARCHAR @GroupName

    查询出来没有结果 没有声明参数长度

    DECLARE @Sql NVARCHAR( );

    DECLARE @GroupName NVARCHAR( );SET@GroupName = SuperAdmin ;

    SET@Sql = SELECT * FROM Groups WHERE GroupName=@GroupName

    PRINT @Sql;

    EXEC SP_EXECUTESQL @Sql N @GroupName NVARCHAR( ) @GroupName

    Summary:动态批处理不能访问定义在批处理里的局部变量 SP_EXECUTESQL 可以有输入输出参数 比EXECUTE灵活

    下面我们来看看EXECUTE SP_EXECUTESQL的执行效率 首先把缓存清除执行计划 然后改变用@GroupName值SuperAdmin CommonUser CommonAdmin分别执行三次 然后看看其使用缓存的信息

    DBCC FREEPROCCACHE;

    DECLARE @Sql VARCHAR( );

    DECLARE @GroupName VARCHAR( );SET@GroupName = SuperAdmin ; CommonUser CommonAdmin

    SET@Sql = SELECT * FROM Groups WHERE GroupName= + QUOTENAME(@GroupName )

    EXECUTE(@Sql); SELECTcacheobjtype objtype usecounts sql

    FROM sys syscacheobjects

    WHERE sql NOTLIKE %cache%

    ANDsql NOTLIKE %sys % ;

    依葫芦画瓢 接着我们看看SP_EXECUTESQL的执行效率

    DBCC FREEPROCCACHE;

    DECLARE @Sql NVARCHAR( );

    DECLARE @GroupName NVARCHAR( );SET@GroupName = SuperAdmin ; CommonUser CommonAdmin

    SET@Sql = SELECT * FROM Groups WHERE GroupName=@GroupName

    EXECUTESP_EXECUTESQL @Sql N @GroupName NVARCHAR( ) @GroupName;

    SELECTcacheobjtype objtype usecounts sql

    FROM sys syscacheobjects

    WHERE sql NOTLIKE %cache%

    ANDsql NOTLIKE %sys % ;

    lishixin/Article/program/SQLServer/201311/22279

      sql server 中的EXEC有什么用?!

      exec函数族的作用为根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。

      exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,只留下进程ID等一些表面上的信息仍保持原样,看上去还是旧的躯壳,却已经注入了新的灵魂。只有调用失败了,它们才会返回一个-1,从原程序的调用点接着往下执行。

      扩展资料

      使用exec函数族主要有两种情况:

      1、当进程认为自己不能再为系统和用户做出任何贡献时,就可以调用exec函数族中的任意一个函数让自己重生。

      2、如果一个进程想执行另一个程序,那么它就可以调用fork函数新建一个进程,然后调用exec函数族中的任意一个函数,这样看起来就像通过执行应用程序而产生了一个新进程(这种情况非常普遍)。

      参考资料来源:百度百科-exec函数族

      参考资料来源:百度百科-exec...

      数据库的“EXEC”是什么意思?应该怎么用?

      sqlserver中

      EXEC命令有两种用法,一种是执行一个存储过程,另一种是执行一个动态的批处理

      1.使用系统存储过程sp_executesql运行Unicode命令字符串

      语法如下:

      sp_executesql [@stmt=] stmt

      [

      {,[@params=] N'@parameter_name data_type [,...n]'}

      {,[@param1=] 'value' [,...n]}

      ]

      说明:必须先将各个包含所要运行的命令语句的Unicode字符串相加在一起,再交给系统存储过程sp_executesql来运行,而不能在sp_executesql的语句中来相加各个命令字符串。

      举例如下:

      declare @DBName nvarchar(20),

      @Tbname nvarchar(20),

      @SQLString nvarchar(500)

      set @DBName=N'Northwind'

      set @Tbname=N'Customers'

      set @SQLString=N'USE '+@DBName+char(13) --char(13)换行

      SET @SQLString=@SQLString+N'select * from '+@Tbname

      --必须先将命令字符串组合完毕后再交给sp_executesql来运行

      exec sp_executesql @SQLString

      2.使用EXECUTE命令运行命令字符串

      要使用EXECUTE命令来运行一个命令字符串的语法如下:

      EXEC[UTE] ({@string_variable|[N] 'stql_string'} [+...n])

      从语法看出,可以先将包含所要运行的命令的字符串赋给一个局部变量@string_variable,再使用EXECUTE命令来运行,或是直接使用EXECUTE命令去运行一个包含所要运行的命令语句的字符串。此外,您也可以将多个包含所要运行的命令语句的字符串相加在一起,再交给EXECUTE命令来一次运行。

      例:

      declare @sql nvarchar(4000)

      set @sql='select * from [表] where email=''test@163.com'''

      exec (@sql)