使⽤exec和sp_executesql动态执⾏SQL语句(转载)
需要根据外部输⼊的参数来决定要执⾏的SQL语句时,常常需要动态来构造SQL查询语句,个⼈觉得⽤得⽐较多的地⽅就是分页存储过程和执⾏搜索查询的SQL语句。⼀个⽐较通⽤的分页存储过程,可能需要传⼊表名,字段,过滤条件,排序等参数,⽽对于搜索的话,可能要根据搜索条件判断来动态执⾏SQL语句。
在SQL Server中有两种⽅式来执⾏动态SQL语句,分别是exec和sp_executesql。sp_executesql相对⽽⾔具有更多的优点,它提供了输⼊输出接⼝,可以将输⼊输出变量直接传递到SQL语句中,⽽exec只能通过拼接的⽅式来实现。还有⼀个优点就是sp_executesql,能够重⽤执⾏计划,这就⼤⼤提⾼了执⾏的性能。所以⼀般情况下建议选择sp_executesql来执⾏动态SQL语句。
使⽤sp_executesql需要注意的⼀点就是,它后⾯执⾏的SQL语句必须是Unicode编码的字符串,所以在声明存储动态SQL语句的变量时必须声明为nvarchar类型(如果不知道SQL语句有多长,可以直接⽤nvarchar(max)类型),否则在执⾏的时候会报“过程需要类型为
'ntext/nchar/nvarchar' 的参数 '@statement'”的错误,如果是使⽤sp_executesql直接执⾏SQL语句,则必须在前⾯加上⼤写字母N,以表明后⾯的字符串是使⽤Unicode类型编码的。
下⾯来看看⼏种动态执⾏SQL语句的情况
1.普通SQL语句
exec('select * from Student')
exec sp_executesql N'select * from Student'--此处⼀定要加上N,否则会报错
2.带参数的SQL语句
declare@sql nvarchar(1000)
declare@userId varchar(100)
set@userId='0001'
set@sql='select * from Student where UserID='''+@userId+''''
exec(@sql)
declare@sql nvarchar(1000)
declare@userId varchar(100)
set@userId='0001'
set@sql=N'select * from Student where UserID=@userId'
exec sp_executesql @sql,N'@userId varchar(100)',@userId
从这个例⼦中可以看出使⽤sp_executesql可以直接将参数写在sql语句中,⽽exec需要使⽤拼接的⽅式,这在⼀定程度上可以防⽌SQL注⼊,因此sp_executesql拥有更⾼的安全性。另外需要注意的是,存储sql语句的变量必须声明为nvarchar类型的。
3.带输出参数的SQL语句
create procedure[dbo].[sp_GetNameByUserId]
(
@userId varchar(100),
@userName varchar(100) output
)
as
begin
declare@sql nvarchar(1000)
set@sql=N'select @userName=UserName from Student where UserId=@userId'
exec sp_executesql @sql,N'@userId varchar(100),@userName varchar(100) output',@userId,@userName output
pdf转htmlselect@userName
end