laifangsong's blog

取长补短,精益求精。 (打个广告,想做手机网站和asp/asp.net网站的可以跟我联系.QQ:25313644)
posts - 51, comments - 187, trackbacks - 0, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

不错的分页存储过程(转)

Posted on 2007-04-12 14:32 laifangsong 阅读(383) 评论(10)  编辑 收藏 所属分类: sqlserver2000

原文地址:
http://www.113317.com/blog/article.asp?id=252

做了简单修改,以适应多表联合查询。


CREATE  PROCEDURE sp_Paging
@tblName varchar(255) , -- 表名
@strGetFields varchar(1000= '*'-- 需要返回的列 
@fldName varchar(255)=''-- 排序的字段名
@pageSize int = 10-- 页尺寸
@pageIndex int = 1-- 页码
@recordCount int = 0 output, -- 返回记录总数
@pageCount int = 0 output, --分页总数
@orderType int = 0-- 设置排序类型, 非 0 值则降序
@strWhere varchar(1500= '' -- 查询条件 (注意: 不要加 where)
AS
declare @strSQL nvarchar(3000-- 主语句
declare @strTmp varchar(110-- 临时变量
declare @strOrder varchar(400-- 排序类型

    
begin
        
if @strWhere !=''
            
set @strSQL = 'select @recordCount = count(*) from ' + @tblName + ' where '+@strWhere
        
else
            
set @strSQL = 'select @recordCount = count(*) from ' + @tblName
    
end 

    
exec sp_executesql @strSQL,N'@recordCount int out ',@recordCount out

    
if @recordCount % @pageSize = 0
        
set @pageCount = @recordCount / @pageSize
    
else
        
set @pageCount = @recordCount / @pageSize + 1
  
--以上代码的意思是计算出记录是总数和求出总共的页数

   
begin
      
if @orderType != 0
         
begin
            
set @strTmp = '<(select min'
            
set @strOrder = ' order by ' + @fldName +' desc'
         
--如果@orderType不是0,就执行降序,这句很重要!
         end
      
else
         
begin
            
set @strTmp = '>(select max'
            
set @strOrder = ' order by ' + @fldName +' asc'
         
end

     
if @pageIndex = 1
        
begin
           
if @strWhere != '' 

              
set @strSQL = 'select top ' + str(@pageSize+' '+@strGetFields+ ' from ' + @tblName + ' where ' + @strWhere + ' ' + @strOrder
           
else

              
set @strSQL = 'select top ' + str(@pageSize+' '+@strGetFields+ ' from '+ @tblName + ' '+ @strOrder
      
--如果是第一页就执行以上代码,这样会加快执行速度
        end
     
else
         
begin
           
if @strWhere != ''
                 
set @strSQL = 'select top ' + str(@pageSize+' '+@strGetFields+ ' from '
                        
+ @tblName + ' where ' + @fldName + '' + @strTmp + '('
                        
+ substring(@fldNamecharindex('.',@fldName)+1len(@fldName)) + ') from (select top ' + str((@pageIndex-1)*@pageSize+ ' '
                        
+ @fldName + ' from ' + @tblName + ' where ' + @strWhere + ' '
                        
+ @strOrder + ') as tblTmp) and ' + @strWhere + ' ' + @strOrder
       
else
         
set @strSQL = 'select top ' + str(@pageSize+' '+@strGetFields+ ' from '
                        
+ @tblName + ' where ' + @fldName + '' + @strTmp + '('
                        
+ substring(@fldNamecharindex('.',@fldName)+1len(@fldName)) + ') from (select top ' + str((@pageIndex-1)*@pageSize+ ' '
                        
+ @fldName + '  from ' + @tblName + '' + @strOrder + ') as tblTmp)'
                        
+ @strOrder
         
end
   
end
--print @strSQL
exec sp_executesql @strSQL
GO


Feedback

#1楼    回复  引用  查看    

2007-04-12 14:47 by 汤智程      
不错,但是 如果 @strWhere 中含有 ' 你试过没有

#2楼 [楼主]   回复  引用  查看    

2007-04-13 09:20 by laifangsong      

试了下,发现确实可以注入。

其实很多分页存储过程TSQL语句都是这样写的,基本都有注入问题。
declare @sqlstr
set @sqlstr = '...'
exec(@sqlstr )
/*
先 生成一个大的sql语句串,再调用执行;如果查询条件中传入逗号,逗号全部变成执行语句的一部分了,注入漏洞就出现了。
即使在asp.net中,通过sqlparam那种形式构建参数,还是免不了sql注入
*/
或者
exec sp_executesql(@sqlstr)


防止注入:

1.
如果不是构造成大的sql语句串来执行,就不会有注入问题。
例如:
select * from admin where username=@username and password=@password

2.参数传入之前先过滤
//过滤提交的非法字符串(防止sql注入)
public static string GetSafeStr(string str)
{
return str.Replace("'", "").Replace("\"", "").Replace(":", "");
}

#3楼    回复  引用    

2007-09-18 16:15 by 等了你一年了 [未注册用户]
老大,以前你那个老的我在用,经常符合条件的有时却查不到.呵呵,等你一年了,终于等到这个多表查询的了.

#4楼 [楼主]   回复  引用  查看    

2007-09-18 17:49 by laifangsong      
回楼上:
这个存储过程是别人写的,我只是修改了他的代码而已

#5楼    回复  引用    

2007-09-19 12:24 by 等了你一年了 [未注册用户]
呵呵,无论如何都要谢谢.
还有一个问题请教,在存储过程里设定定超过最大页数时的一个判断,例如
if @pageIndex > @pageCount
@pageIndex = @pageCount
可是这样会出错,只能在ASP里设吗,在ASP里怎么设呢?还望能指教.

#6楼 [楼主]   回复  引用  查看    

2007-09-19 12:46 by laifangsong      
if @pageIndex > @pageCount
set @pageIndex = @pageCount

#7楼    回复  引用    

2007-09-19 13:39 by 等了你一年了 [未注册用户]
谢谢.这样就好多了.呵呵

#8楼    回复  引用    

2007-12-30 13:06 by vv [未注册用户]
真的能用多表查询吗?有人做过测试吗?

#9楼    回复  引用    

2007-12-30 13:46 by gg [未注册用户]
第 1 行: ' ' 附近有语法错误。
第 1 行: ' ' 附近有语法错误。

这是那里错了?

#10楼    回复  引用    

2007-12-30 14:26 by gg [未注册用户]
可以转换成SQL语句给我吗?谢谢!!