SQL SERVER 中构建执行动态SQL语句的方法
1:普通SQL语句可以用exec执行
Select*fromtableName exec('select*fromtableName') execsp_executesqlN'select*fromtableName'--请注意字符串前一定要加N
2:字段名,表名,数据库名之类作为变量时,必须用动态SQL
declare@fnamevarchar(20) set@fname='FiledName' --Select@fnamefromtableName--错误,不会提示错误,但结果为固定值FiledName,并非所要。 exec('select'+@fname+'fromtableName')--请注意加号前后的单引号的边上加空格 --当然将字符串改成变量的形式也可 declare@fnamevarchar(20) set@fname='FiledName'--设置字段名 declare@svarchar(1000) set@s='select'+@fname+'fromtableName' exec(@s)--成功 --execsp_executesql@s--此句会报错 declare@sNvarchar(1000)--注意此处改为nvarchar(1000)(必须为ntext或nchar哐nvarchar类型,不能是varchar类型) set@s='select'+@fname+'fromtableName' exec(@s)--成功 execsp_executesql@s--此句正确
3.输入或输出参数
--(1)输入参数: declare@QueryStringnvarchar(1000)--动态查询语句变量(注:必须为ntext或nchar哐nvarchar类型,不能是varchar类型) declare@paramstringnvarchar(200)--设置动态语句中的参数的字符串(注:必须为ntext或nchar哐nvarchar类型,不能是varchar类型) declare@input_idint--定义需传入动态语句的参数的值 set@QueryString='select*fromtablenamewhereid=@id'--id为字段名,@id为要传入的参数 set@paramstring='@idint'--设置动态语句中参数的定义的字符串 set@input_id=1--设置需传入动态语句的参数的值为1 execsp_executesql@querystring,@paramstring,@id=@input_id --若有多个参数: declare@QueryStringnvarchar(1000)--动态查询语句变量(注:必须为ntext或nchar哐nvarchar类型,不能是varchar类型) declare@paramstringnvarchar(200)--设置动态语句中的参数的字符串(注:必须为ntext或nchar哐nvarchar类型,不能是varchar类型) declare@input_idint--定义需传入动态语句的参数的值,参数1 declare@input_namevarchar(20)--定义需传入动态语句的参数的值,参数2 set@QueryString='select*fromtablenamewhereid=@idandname=@name'--id与name为字段名,@id与@name为要传入的参数 set@paramstring='@idint,@namevarchar(20)'--设置动态语句中参数的定义的字符串,多个参数用","隔开 set@input_id=1--设置需传入动态语句的参数的值为1 set@input_name='张三'--设置需传入动态语句的参数的值为"张三" execsp_executesql@querystring,@paramstring,@id=@input_id,@name=@input_name--请注意参数的顺序 --(2)输出参数 declare@numint,@sqlsnvarchar(4000) set@sqls='selectcount(*)fromtableName' exec(@sqls) --如何将exec执行结果放入变量中? declare@QueryStringnvarchar(1000)--动态查询语名变量(注:必须为ntext或nchar哐nvarchar类型,不能是varchar类型) declare@paramstringnvarchar(200)--设置动态语句中的参数的字符串(注:必须为ntext或nchar哐nvarchar类型,不能是varchar类型) declare@output_resultint--查询结果赋给@output_result set@QueryString='select@totalcount=count(*)fromtablename'--@totalcount为输出结果参数 set@paramstring='@totalcountintoutput'--设置动态语句中参数的定义的字符串,多个参数用","隔开 execsp_executesql@querystring,@paramstring,@totalcount=@output_resultoutput select@output_result --当然,输入与输出参数可以一起使用,大家可以自己去试一试。 --另外,动态语句查询的结果集要输出的话,我只想到以下用临时表的方法,不知各位有没有更好的方法. IFobject_id('[tempdb].[dbo].#tmp')ISNOTNULL--判断临时表#tmp是否存在,存在则删除 droptable#tmp select*into#tmpfromtablenamewhere1=2--创建临时表#tmp,其结构与tablename相同 declare@QueryStringnvarchar(1000)--动态查询语名变量(注:必须为ntext或nchar哐nvarchar类型,不能是varchar类型) set@QueryString='select*fromtablename' insertinto#tmp(field1,field2,)exec(@querystirng)
有些特殊原因,我们需要在SQL语句或者存储过程中动态创建SQL语句,然后在SQL语句或存储过程中动态来执行。
这里,微软提供了两个方法,一个是使用
Execute函数
执行方式为
Execute(@sql)来动态执行一个SQL语句,但是这里的SQL语句无法得到里面的返回结果,下面来介绍另一种方法
使用存储过程sp_ExecuteSql
使用该存储过程,则可将动态语句中的参数返回来。
比如
declare@sqlnvarchar(800),@ddvarchar(20) set@sql='set@mm=''测试字符串''' execsp_executesql@sql,N'@mmvarchar(20)output',@ddoutput select@dd
执行他就会将内部创建的SQL语句的某个变量的值返回到外部调用者。
主要来源于工作中的一个偶然需要:
createprocproc_InToServer@收费站点编号varchar(4),@车道号tinyint,@进入时间varchar(23),@UIDchar(16), @车牌varchar(12),@车型char(1),@识别车牌号varchar(12),@识别车型char(1),@收费金额money,@交易状态char(1), @有图像bit,@离开时间varchar(23),@速度float,@HasInsertintoutput as begin declare@inTimedatetime,@TableNamevarchar(255),@leaveTimedatetime,@HasTablebit,@Sqlnvarchar(4000) select@intime=Convert(datetime,@进入时间),@leaveTime=Convert(datetime,@离开时间) set@TableName='ETC03_01_OBE原始过车记录表_'+dbo.formatDatetime(@intime,'YYYYMMDD') select@HasTable=(CasewhenCount(*)>0then1else0end)fromsysobjectswhereid=Object_id(@TableName)andObjectProperty(id,'IsUserTable')=1 if@HasTable=0 begin set@Sql='CREATETABLE[dbo].['+@TableName+']( [收费站点编号][char](4)COLLATEChinese_PRC_CI_ASNOTNULL, [车道号][tinyint]NOTNULL, [进入时间][datetime]NOTNULL, [UID][char](16)COLLATEChinese_PRC_CI_ASNOTNULL, [车牌][varchar](12)COLLATEChinese_PRC_CI_ASNULL, [车型][char](1)COLLATEChinese_PRC_CI_ASNULL, [识别车牌号][varchar](12)COLLATEChinese_PRC_CI_ASNULL, [识别车型][char](1)COLLATEChinese_PRC_CI_ASNULL, [收费金额][money]NULL, [交易状态][char](1)COLLATEChinese_PRC_CI_ASNULL, [有图像][bit]NOTNULL, [离开时间][datetime]NULL, [速度][float]NULL, Constraint'+'PK_'+@TableName+'primarykey(收费站点编号,车道号,进入时间,UID) )ON[PRIMARY]' Execute(@Sql) end set@sql='select@Cnt=count(*)from'+@TableName+'where收费站点编号='''+@收费站点编号+'''and车道号='+cast(@车道号asvarchar(4))+'and进入时间='''+@进入时间+'''andUID='''+@UID+'''' set@sql=@sql+'if@Cnt=0' set@sql=@sql+'insert'+@TableName+'values('''+@收费站点编号+''','+cast(@车道号asvarchar(4))+','''+@进入时间+''','''+@Uid+''','''+@车牌+ ''','''+@车型+''','''+@识别车牌号+''','''+@识别车型+''','+Cast(@收费金额asvarchar(8))+','''+@交易状态+''','+cast(@有图像asvarchar(1))+ ','''+@离开时间+''','+Cast(@速度asvarchar(8))+')' --Execute(@sql) execsp_executesql@sql,N'@Cntintoutput',@HasInsertoutput end
这样大家基本上就有些了解了。