网站导航网学 原创论文 原创专题 网站设计 最新系统 原创论文 论文降重 发表论文 论文发表 UI设计定制 论文答辩PPT格式排版 期刊发表 论文专题
返回网学首页
网学原创论文
最新论文 推荐专题 热门论文 论文专题
当前位置: 网学 > 交易代码 > SQL语法 > 正文

动态语句语法exec和sp_executesql语法的区别

论文降重修改服务、格式排版等 获取论文 论文降重及排版 论文发表 相关服务

【网学网提醒】:网学会员,鉴于大家对动态语句语法exec和sp_executesql语法的区别十分关注,会员在此为大家搜集整理了“动态语句语法exec和sp_executesql语法的区别”一文,供大家参考学习!


    动态语句语法:
    --方法1查询表改为动态
    select*fromsysobjects
    exec('selectID,Namefromsysobjects')
    execsp_executesqlN'selectID,Namefromsysobjects'--多了一个N为unicode
    --方法2:字段名,表名,数据库名之类作为变量时,用动态SQL
    declare@FNamevarchar(20)
    set@FName='ID'
    exec('select'+@FName+'fromsysobjectswhere'+@FName+'=5')
    declare@svarchar(1000)
    set@s=N'select'+@FName+'fromsysobjectswhere'+@FName+'=5'
    execsp_executesql@s--会报错
    declare@snvarchar(1000)--改为nvarchar
    set@s=N'select'+@FName+'fromsysobjectswhere'+@FName+'=5'
    execsp_executesql@s--成功
    --方法3:输入参数
    declare@iint,@snvarchar(1000)
    set@i=5
    exec('selectID,NamefromsysobjectswhereID='+@i)
    set@s='selectID,NamefromsysobjectswhereID=@i'
    execsp_executesql@s,N'@iint',@i--此处输入参数要加上N
    --方法4:输出参数
    declare@iint,@snvarchar(1000)
    set@s='select@i=count(1)fromsysobjects'
    --用exec
    exec('declare@iint'+@s+'select@i')--把整个语句用字符串加起来执行
    --用sp_executesql
    execsp_executesql@s,N'@iintoutput',@ioutput--此处输出参数要加上N
    select@i
    --方法5:输入输出
    --用sp_executesql
    declare@iint,@conint,@snvarchar(1000)
    set@i=5
    select@s='select@con=count(1)fromsysobjectswhereID>@i'
    execsp_executesql@s,N'@conintoutput,@iint',@conoutput,@i
    select@con
    --用exec
    declare@iint,@snvarchar(1000)
    set@i=5
    select@s='declare@conintselect@con=count(1)fromsysobjectswhereID>'+rtrim(@i)+'select@con'
    exec(@s)
    1、EXEC命令的括号中只允许包含一个字符串变量,或者一个字符串文本,或者字符串变量与字符串文本的串联。不能再括号中使用函数或CASE表达式,如下面尝试在括号中调用QUOTENAME函数以引用对象名称,运行将失败:
    
    1:DECLARE@schemanameNVARCHAR(255),@tablenameNVARCHAR(128)
    2:SET@schemaname='dbo'
    3:SET@tablename='OrderDetails'
    4:
    5:EXEC(N'SELECTCOUNT(*)FROM'+QUOTENAME(@schemaname)+N'.'+QUOTENAME(@tablename)+N';')
    上述代码将会产生如下错误:
    消息102,级别15,状态1,第5行
    'QUOTENAME'附近有语法错误。
    SQLServer分析和编译时间:
    CPU时间=0毫秒,占用时间=0毫秒。
    SQLServer执行时间:
    CPU时间=0毫秒,占用时间=0毫秒。
    所以做好的方法是把代码构造到一个变量中,这样就不会受限制了,然后再把该变量作为EXEC命令的输入参数,就像这样:
    1:DECLARE@schemanameNVARCHAR(255),
    2:@tablenameNVARCHAR(128),
    3:@sqlNVARCHAR(MAX)
    4:SET@schemaname='dbo'
    5:SET@tablename='OrderDetails'
    6:SET@sql=N'SELECTCOUNT(*)FROM'+QUOTENAME(@schemaname)+N'.'
    7:+QUOTENAME(@tablename)+N';'
    8:EXEC(@sql)
    
    2、EXEC不提供接口。EXEC(    ring>)不提供接口。它唯一的输入就是包含你要调用代码的字符串。动态批处理不能访问在调用批处理中定义的局部变量。如下面代码尝试访问定义在调用批处理中的变量将失败。
    1:DECLARE@iINT
    2:SET@i=10248
    3:
    4:DECLARE@sqlNVARCHAR(MAX)
    5:
    6:SET@sql='SELECT*FROMdbo.OrdersWHEREOrderID=@i;'
    7:EXEC(@sql)
    将产生如下错误:
    消息137,级别15,状态2,第1行
    必须声明标量变量"@i"。
    
    使用EXEC时,如果想访问变量,必须把变量内容串联到动态构建的代码字符串中。
    DECLARE@iINT
    SET@i=10248
    DECLARE@sqlNVARCHAR(MAX)
    SET@sql='SELECT*FROMdbo.OrdersWHEREOrderID='
    +CAST(@iASNVARCHAR(10))+';'
    EXEC(@sql)
    这样就没有问题了。
    
    如果一个变量包含字符串,把该变量的内容串联到代码将会导致安全风险(SQL注入),为了避免SQL注入,可以吧字符串大小限制为所需的最小长度。当然,实际中这种情况根本不需要动态SQL直接执行SQL语句就可以,这个示例只是为了演示。
    
    串联变量的内容存在性能方面的弊端,SQLServer将为每个唯一的查询字符串创建新的即席执行计划,即使查询模式相同也是这样的。为演示这一点,先清空缓存中的执行计划。
    DBCCFREEPROCCACHE
    将上端代码执行三次,分别为@i赋值10248,10249和10250,然后使用下面的代码查询
    1:SELECTcacheobjtype,
    2:objtype,
    3:usecounts,
    4:sql
    5:FROMsys.syscacheobjects
    6:WHEREsqlNOTLIKE'%cache%'
    7:ANDsqlNOTLIKE'%sys.%'
    得到查询结果:
    
    cacheobjtypeobjtypeusecountssql
    CompiledPlanAdhoc1SELECT*FROMdbo.OrdersWHEREOrderID=10250;
    CompiledPlanAdhoc1SELECT*FROMdbo.OrdersWHEREOrderID=10248;
    CompiledPlanPrepared3(@1smallint)SELECT*FROM[dbo].[Orders]WHERE[OrderID]=@1
    CompiledPlanAdhoc4SETSTATISTICSIOONSETSTATISTICSTIMEON
    CompiledPlanAdhoc1SELECT*FROMdbo.OrdersWHEREOrderID=10249;
    CompiledPlanAdhoc4SETSTATISTICSIOOFFSETSTATISTICSTIMEOFF
    
    EXEC除了不支持动态批处理中的输入参数外,也不支持输出参数。默认情况下,EXEC把查询输出返回给调用者。如果你想把输出结果返回给调用批处理中的变量,事情就没那么简单了,为此,你需要使用INSERTEXEC把输出插入到一个目的表,然后再从该表中取值,赋给该变量,就像这样:
    
    1:DECLARE@schemanameNVARCHAR(128),
    2:@tablenameNVARCHAR(128),
    3:@colnameNVARCHAR(128),
    4:@sqlNVARCHAR(MAX),
    5:@cntINT
    6:
    7:SET@schemaname='dbo'
    8:SET@tablename='Orders'
    9:SET@colname='CustomerID'
    10:
    11:SET@sql
    =N'SELECTCOUNT(DISTINCT'+QUOTENAME(@colname)+')FROM'
    12:+QUOTENAME(@schemaname)+N'.'+QUOTENAME(@tablename)+N';'
    13:
    14:CREATETABLE#T1(cntINT)
    15:INSERTINTO#T1
    16:EXEC(@sql
    17:)
    18:SELECT@cnt=cnt
    19:FROM#T1
    20:SELECT@cnt
    21:DROPTABLE#T1
    3、在SQLServer2000中串联变量值时,EXEC比sp_executesql多一个优势,它支持更长的代码,尽管技术上sp_executesql的输入代码字符串是NTEXT类型的,但你一般是在局部变量中构造代码字符串。而你又不能用大型对象类型声明局部变量,所以,实际上在sp_executesql中执行的查询字符串被限制为Unicode字符串(NVARCHAR)支持的最大长度4000,而EXEC支持常规字符串(VARCHAR)允许最大8000个字符。另外EXEC还支持一个特殊的功能,它允许你在括号中串联多个变量,每个变量都支持8000个字符的长度。
    在SQLServer2005中,就不用这么纠结了,因为可以为EXEC命令提供一个VARCHAR(MAX)或NVARCHAR(MAX)的变量作为输入,输入字符串可以达到2GB大小
    
设为首页 | 加入收藏 | 网学首页 | 原创论文 | 计算机原创
版权所有 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
Copyright 2008-2020 myeducs.Cn www.myeducs.Cn All Rights Reserved 湘ICP备09003080号 常年法律顾问:王律师