微软提供了两种命令用来动态执行sql语句,分别是execute和sp_executesql,也就是说我们可以通过动态拼接字符串的方式来构建我们所需要的sql语句。我们可以通过传参的方式传递sql命令,我们也可以在执行的时候构建sql命令。虽然这两者都能实现动态拼接sql,但是通常来说sp_executesql来的更好些,sp_executesql有利于重用执行计划,而且也支持输入输出参数,而execute则不支持,所以除非有让你信服的理由使用execute,否则建议使用sp_execute。

1、execute的使用

execute可能比较熟悉了,常常用来执行某个存储过程来,如exec sp_who列出目前的连接信息。当然execute的另一个用途就是用来执行一段字符串型的sql命令了,语法类似exec('sqlString') ;括号里的sqlString代表一段sql命令语句。当然也可以传入字符串类型的变量。如下查询学号为200601的学生姓名

declare @sqlString varchar(100);
declare @stuNo int;
set @stuNo=200601;
set @sqlString='select stuName from student where stuNo='+cast(@stuNo as varchar(10));
execute (@sqlString);

 如果不是通过@sqlString字符串变量来传参而类似下面的语句,且看下面

execute('select stuName from student where stuNo='+cast(@stuNo as varchar(10)));
'cast' 附近有语法错误。

declare @sqlstr2 varchar(100);
set @sqlstr2='where stuNo='+cast(@stuNo as varchar(10));
execute('select * from student '+@sqlstr2);


--上面能正常执行

 所以最佳的做法就是将字符串的构造结果存一个变量中,然后传递给execute执行

总得来说execute命令的动态执行还是挺灵活的,可以随意构造自己所想要的sql命令。但是也有不足的地方,它不能在字符串命令中传参。如下

declare @sqlString varchar(100);
declare @stuNo int;
set @sqlString='select stuName from student where stuNo=@stuNo';
execute (@sqlString);


'必须声明标量变量@stuNo'

 也就是说在execute执行的批处理里面是访问不到上下文定义的局部变量的,而且也无法通过传参的方式将赋值给字符串命令中的@stuNo变量。动态的条件赋值只能能过上面所讲的字符串拼接的方式。当然也不支持输出参数。

再则其实每次执行该sql命令都会产生新的执行计划,每次进行编译,无法进行重复的使用。

2、sp_executesql的使用

相较于上面的execute命令的无法重复使用执行计划,以及对输入输出参数的不支持,sp_executesql在这方面就显得方便多了。从命名中我们就可以看出该命令其实就是一个存储过程,只不过它是系统定义好的,我们直接拿来利用。首先也来看一下它的使用语法。

exec sp_executesql N'sqlStatement',N'params defined,……', value1,……

使用sp_executesq存储过程通常会传递3部分参数

第一部分参数即sqlStatement,它是一段sql命令,可以包含参数,也可以不包含, 但是其语句必须为一个unicode字符串变量或常量

如N'select stuName from student where stuNo=@stuNo'其中这里的@stuNo为该语句中的变量,对外是不可见的,但是我们可以通过后面的输入参数赋值给@stuNo变量。

第二部分定义参数,即定义那些将在sqlStatement语句中使用到的那些变量,因为刚才的上面的语句中我们使用到了@stuNo所以我们必须在这里定义N'@stuNo int' ,发现其定义规则也是必须为一个unicode字符串变量或常量。当然如果没用使用到变量这里可以不定义,默认为NULL。当然定义的时候也可以指定为输出参数只要定义这样N'@stuName int output'。

第三部分传参,传那些定义变量的值或者接受值,如果没有定义则可以不传。

下面看例子

declare @sqlString nvarchar(100);--这边定义成nvarchar
declare @sqlParams nvarchar(50);--这边定义成nvarchar
declare @stuNo int;
set @sqlString=N'select stuName from student where stuNo=@stuNo';
set @stuParams=N'@stuNo int';
set @stuNo=200601;
execute sp_executesql @sqlString,@sqlParams,@stuNo;

 sp_executesql也支持输出参数

declare @sqlString nvarchar(100);--这边定义成nvarchar
declare @sqlParams nvarchar(50);--这边定义成nvarchar
declare @stuNo int;
declare @stuName varchar(20);
set @sqlString=N'select @stuName=stuName from student where stuNo=@stuNo';
set @stuParams=N'@stuNo int,@stuName varchar(20) output';
set @stuNo=200601;
execute sp_executesql @sqlString,@sqlParams,@stuNo,@stuName output;
select @stuName;