当前位置: 代码迷 >> Sql Server >> 存储过程中sp_executesql执行sql语句带参数有关问题
  详细解决方案

存储过程中sp_executesql执行sql语句带参数有关问题

热度:72   发布时间:2016-04-24 08:49:40.0
存储过程中sp_executesql执行sql语句带参数问题
小弟这个分页存储过程中where条件需要parameter参数化传递条件,不明白C#中如何将parameter一并加入进来



ALTER PROCEDURE [dbo].[sp_TablesPage]

    @tblName nvarchar(1000),            ----要显示的表或多个表的连接
    @fields nvarchar(1000)='*',        ----要显示的字段列表
    @sortfields    nvarchar(100)='',    ----如果多列排序,一定要带asc或者desc,则@singleSortType排序方法无效,反之,单列根据@singleSortType来处理
    @singleSortType    int = 1,                ----排序方法,0为升序,1为降序
    @pageSize int = 10,                ----每页显示的记录个数
    @pageIndex    int = 1,                ----要显示那一页的记录
    @strCondition    nvarchar(1000)='',    ----查询条件,不需where    
    @Counts    int =1 output           ----查询到的记录数


AS
/*
作者:
时间:2015-08-26
功能:实现多表分页查询;
*/
declare @sqlTmp nvarchar(2000)
declare @sqlGetCount nvarchar(2000)
declare @frontOrder nvarchar(200)
declare @behindOrder nvarchar(200)
declare @start nvarchar(20) 
declare @end nvarchar(20)
declare @pageCount INT
if @strCondition=''
set @strCondition=' where 1=1'
else
set @strCondition=' where '+@strCondition
begin
    if charindex(',',@sortfields,0)>0--多列排序,则@singleSortType排序方法无效
        begin
            set @frontOrder = @sortfields--获取分页前半部分数据的排序规则
            set @behindOrder = replace(@frontOrder,'desc','desctmp')
            set @behindOrder = replace(@behindOrder,'asc','desc')
            set @behindOrder = replace(@behindOrder,'desctmp','asc')--获取分页后半部分数据的排序规则
        end
    else--单列
        begin
            set @sortfields=replace(replace(@sortfields,'desc',''),'asc','')--替换掉结尾的规则,用@singleSortType值来处理排序
            if @singleSortType=1--倒序
                begin
                    set @frontOrder = @sortfields + ' desc'
                    set @behindOrder = @sortfields + ' asc'
                end
                
            else
                begin
                    set @frontOrder = @sortfields + ' asc'
                    set @behindOrder = @sortfields + ' desc'
                end
    end

    --获取记录数
    
      set @sqlGetCount = 'select @Counts=count(*) from ' + @tblName + @strCondition


    ----取得查询结果总数量-----
    exec sp_executesql @sqlGetCount,N'@Counts int out ',@Counts out
    declare @tmpCounts int
    if @Counts = 0
        set @tmpCounts = 1
    else
        set @tmpCounts = @Counts

    --取得分页总数
    set @pageCount=(@tmpCounts+@pageSize-1)/@pageSize

    /**当前页大于总页数 取最后一页**/
    if @pageIndex>@pageCount
        set @pageIndex=@pageCount
    /*-----数据分页2分处理-------*/
    declare @pageIndexNew int --总数/页大小
    declare @lastcount int --总数%页大小 最后一页的数据量

    set @pageIndexNew = @tmpCounts/@pageSize
    set @lastcount = @tmpCounts%@pageSize
    if @lastcount > 0
        set @pageIndexNew = @pageIndexNew + 1
    else
        set @lastcount = @pagesize

    --取得数据的逻辑分析
  if @pageIndexNew<2 or @pageIndex<=@pageIndexNew / 2 + @pageIndexNew % 2   --前半部分数据处理
begin 
--计算开始结束的行号
set @start = @pageSize*(@pageIndex-1)+1
set @end =     @start+@pageSize-1 
set @sqlTmp='SELECT * FROM (select '+@fields+',ROW_NUMBER() OVER ( Order by '+@frontOrder+' ) AS RowNumber From '+@tblName+@strCondition+') T WHERE T.RowNumber BETWEEN '+@start+' AND '+@end
end
else
begin
set @pageIndex = @pageIndexNew-@pageIndex+1 --后半部分数据处理
if @lastcount=@pageSize --如果正好是整数页
begin
set @start = @pageSize*(@pageIndex-1)+1
set @end =     @start+@pageSize-1
end
else
begin
set @start = @lastcount+@pageSize*(@pageIndex-2)+1
set @end =     @start+@pageSize-1
end
set @sqlTmp='select top '+@end+' * FROM (select '+@fields+',ROW_NUMBER() OVER ( Order by '+@behindOrder+' ) AS RowNumber From '+@tblName+@strCondition+') T WHERE T.RowNumber BETWEEN '+@start+' AND '+@end+' order by RowNumber desc '
end
        end
exec sp_executesql @sqlTmp


调用:


public DataTable TablesPage(string tableName, string fields, string sortfield, bool singleSortType, int pageSize, int pageIndex, string condition, out int count, List<IDbDataParameter> listParameters = null)
        {
            var outParmeter = DbManager.OutputParameter("@Counts", SqlDbType.Int);
            ListParameters = new List<IDbDataParameter>
            {
                DbManager.InputParameter("@tblName", tableName),
                DbManager.InputParameter("@fields", fields),
                DbManager.InputParameter("@sortfields", sortfield),
                DbManager.InputParameter("@singleSortType", singleSortType ? "1" : "0"),
                DbManager.InputParameter("@pageSize", pageSize),
                DbManager.InputParameter("@pageIndex", pageIndex),
                DbManager.InputParameter("@strCondition", condition),
                outParmeter
            };
            DbManager.Command.Parameters.Add(new SqlParameter("@@ForumId", "123"));
            //if (listParameters != null) ListParameters.AddRange(listParameters);
            var dt = DbManager.SetCommand(CommandType.StoredProcedure, "sp_TablesPage", ListParameters.ToArray()).ExecuteDataTable();
            count = (int)outParmeter.Value;
            return dt;
        }


用的BLToolkit这个ORM
------解决思路----------------------

好复杂啊 

exec sp_executesql @sqlGetCount,N'@Counts int out ',@Counts out 
实际上 就是通过这个sp_executesql来执行存储过程时,会定义变量 @Counts ,然后执行你的语句把值放到@Counts 里,最后返回。

另外,本质上这个和exec语句是一样的都是动态执行sql。
------解决思路----------------------
引用:
忘了说一句
DbManager.Command.Parameters.Add(new SqlParameter("@ForumId", "123"));
@ForumId是where 条件中的参数
where = " ForumId=@ForumId  ";

Parameter就是参数,你的存储过程里没有@ForumId参数,怎么传进去
应该@strCondition 参数才是where附加条件的参数
------解决思路----------------------
--数值型的判断参数,合并成取判断值的语句
declare @m_sentence NVarchar(2000);
set @m_sentence = 'select @m_par_num=par_num from youtable where primary_col=1';
exec sp_executesql @m_sentence,N'@m_par_num numeric(18,0) output',@m_par_num output;
------解决思路----------------------
ALTER PROCEDURE [dbo].[sp_TablesPage]

    @tblName nvarchar(1000),            ----要显示的表或多个表的连接
    @fields nvarchar(1000)='*',        ----要显示的字段列表
    @sortfields    nvarchar(100)='',    ----如果多列排序,一定要带asc或者desc,则@singleSortType排序方法无效,反之,单列根据@singleSortType来处理
    @singleSortType    int = 1,                ----排序方法,0为升序,1为降序
    @pageSize int = 10,                ----每页显示的记录个数
    @pageIndex    int = 1,                ----要显示那一页的记录
    @strCondition    nvarchar(1000)='',    ----查询条件,不需where    
    @Counts    int =1 output           ----查询到的记录数
)

C#只要关心参数部分,下面和调用无关。
8个参数对8个参数,所以额外添加 @@ForumId 参数是错误的。