海东的技术资料

  博客园 :: 首页 ::  :: 联系 :: 订阅 订阅 :: 管理 ::
  205 随笔 :: 22 文章 :: 684 评论 :: 68 引用

 

/**//*
说明:1.支持多表查询 2.支持任意排序 3.不支持表别名
参考了
    evafly920:[分享]千万数量级分页存储过程(效果演示)
    地址:http://blog.csdn.net/evafly920/archive/2006/03/03/614813.aspx 

IF(EXISTS(SELECT * FROM sysobjects WHERE [id]=OBJECT_ID('usp_PagingLarge') AND xtype='P'))
    DROP PROCEDURE usp_PagingLarge
*/


GO

CREATE PROCEDURE usp_PagingLarge
@TableNames VARCHAR(200),    --表名,可以是多个表,但不能用别名
@PrimaryKey VARCHAR(100),    --主键,可以为空,但@Order为空时该值不能为空
@Fields    VARCHAR(200),        --要取出的字段,可以是多个表的字段,可以为空,为空表示select *
@PageSize INT,            --每页记录数
@CurrentPage INT,        --当前页,0表示第1页
@Filter VARCHAR(200= '',    --条件,可以为空,不用填 where
@Group VARCHAR(200= '',    --分组依据,可以为空,不用填 group by
@Order VARCHAR(200= ''    --排序,可以为空,为空默认按主键升序排列,不用填 order by
AS
BEGIN
    
DECLARE @SortColumn VARCHAR(200)
    
DECLARE @Operator CHAR(2)
    
DECLARE @SortTable VARCHAR(200)
    
DECLARE @SortName VARCHAR(200)
    
IF @Fields = ''
        
SET @Fields = '*'
    
IF @Filter = ''
        
SET @Filter = 'WHERE 1=1'
    
ELSE
        
SET @Filter = 'WHERE ' +  @Filter
    
IF @Group <>''
        
SET @Group = 'GROUP BY ' + @Group

    
IF @Order <> ''
    
BEGIN
        
DECLARE @pos1 INT@pos2 INT
        
SET @Order = REPLACE(REPLACE(@Order' asc'' ASC'), ' desc'' DESC')
        
IF CHARINDEX(' DESC'@Order> 0
            
IF CHARINDEX(' ASC'@Order> 0
            
BEGIN
                
IF CHARINDEX(' DESC'@Order< CHARINDEX(' ASC'@Order)
                    
SET @Operator = '<='
                
ELSE
                    
SET @Operator = '>='
            
END
            
ELSE
                
SET @Operator = '<='
        
ELSE
            
SET @Operator = '>='
        
SET @SortColumn = REPLACE(REPLACE(REPLACE(@Order' ASC'''), ' DESC'''), ' ''')
        
SET @pos1 = CHARINDEX(','@SortColumn)
        
IF @pos1 > 0
            
SET @SortColumn = SUBSTRING(@SortColumn1@pos1-1)
        
SET @pos2 = CHARINDEX('.'@SortColumn)
        
IF @pos2 > 0
        
BEGIN
            
SET @SortTable = SUBSTRING(@SortColumn1@pos2-1)
            
IF @pos1 > 0 
                
SET @SortName = SUBSTRING(@SortColumn@pos2+1@pos1-@pos2-1)
            
ELSE
                
SET @SortName = SUBSTRING(@SortColumn@pos2+1LEN(@SortColumn)-@pos2)
        
END
        
ELSE
        
BEGIN
            
SET @SortTable = @TableNames
            
SET @SortName = @SortColumn
        
END
    
END
    
ELSE
    
BEGIN
        
SET @SortColumn = @PrimaryKey
        
SET @SortTable = @TableNames
        
SET @SortName = @SortColumn
        
SET @Order = @SortColumn
        
SET @Operator = '>='
    
END

    
DECLARE @type varchar(50)
    
DECLARE @prec int
    
SELECT @type=t.name, @prec=c.prec
    
FROM sysobjects o 
    
JOIN syscolumns c on o.id=c.id
    
JOIN systypes t on c.xusertype=t.xusertype
    
WHERE o.name = @SortTable AND c.name = @SortName
    
IF CHARINDEX('char'@type> 0
    
SET @type = @type + '(' + CAST(@prec AS varchar+ ')'

    
DECLARE @TopRows INT
    
SET @TopRows = @PageSize * @CurrentPage + 1
    
print @TopRows
    
print @Operator
    
EXEC('
        DECLARE @SortColumnBegin 
' + @type + '
        SET ROWCOUNT 
' + @TopRows + '
        SELECT @SortColumnBegin=
' + @SortColumn + ' FROM  ' + @TableNames + ' ' + @Filter + ' ' + @Group + ' ORDER BY ' + @Order + '
        SET ROWCOUNT 
' + @PageSize + '
        SELECT 
' + @Fields + ' FROM  ' + @TableNames + ' ' + @Filter  + ' AND ' + @SortColumn + '' + @Operator + '@SortColumnBegin ' + @Group + ' ORDER BY ' + @Order + '    
    
')    
END

GO

--调用例子:
    --1.单表/单排序
    EXEC usp_PagingLarge 'bigtable','d_id','d_id,d_title,d_content,d_time',20,1,'','','d_id desc'
    
--2.单表/多排序
    EXEC usp_PagingLarge 'bigtable','d_id','*',20,0,'','','d_time asc,d_id desc'
    
--3.多表/单排序
    EXEC usp_PagingLarge 'bigtable left join bigtable_author on bigtable.d_id=bigtable_author.BigTable_id''bigtable.d_id''bigtable.d_id,bigtable.d_title,bigtable.d_content,bigtable.d_time,bigtable_author.d_author'200'''''bigtable.d_id asc'
    
--4.多表/多排序
    EXEC usp_PagingLarge 'bigtable left join bigtable_author on bigtable.d_id=bigtable_author.BigTable_id''bigtable.d_id''bigtable.d_id,bigtable.d_title,bigtable.d_content,bigtable.d_time,bigtable_author.d_author'200'''''bigtable.d_time asc,bigtable.d_id desc'

 

与自定义分页结合例子:
/Files/jiny-z/Paging_Custom.rar
alter PROCEDURE SP_Pagination
/*
***************************************************************
** 分页存储过程 **
***************************************************************
参数说明:
1.Tables :表名称,视图
2.PrimaryKey :主关键字
3.Sort :排序语句,不带Order By 比如:NewsID Desc,OrderRows Asc
4.CurrentPage :当前页码
5.PageSize :分页尺寸
6.Fields:字段
6.Filter :过滤语句,不带Where 
7.Group :Group语句,不带Group By
8.docount: 1返回总行数,0返回列表

**************************************************************
*/

(
@Tables varchar(1000),
@PrimaryKey varchar(100),
@Sort varchar(200= NULL,
@CurrentPage int = 1,
@PageSize int = 10,
@Fields varchar(1000= '*',
@Filter varchar(1000= NULL,
@Group varchar(1000= NULL,
@docount bit = 0
)
AS
/*默认排序*/
IF @Sort IS NULL OR @Sort = ''
SET @Sort = @PrimaryKey
DECLARE @SortTable varchar(100)
DECLARE @SortName varchar(100)
DECLARE @strSortColumn varchar(200)
DECLARE @operator char(2)
DECLARE @type varchar(100)
DECLARE @prec int


/*设定排序语句.*/
IF CHARINDEX('DESC',@Sort)>0
 
BEGIN
  
SET @strSortColumn = REPLACE(@Sort'DESC''')
  
SET @operator = '<='
 
END
ELSE
 
BEGIN
 
IF CHARINDEX('ASC'@Sort= 0
  
SET @strSortColumn = REPLACE(@Sort'ASC''')
  
SET @operator = '>='
 
END
IF CHARINDEX('.'@strSortColumn> 0
 
BEGIN
  
SET @SortTable = SUBSTRING(@strSortColumn0CHARINDEX('.',@strSortColumn))
  
SET @SortName = SUBSTRING(@strSortColumnCHARINDEX('.',@strSortColumn+ 1LEN(@strSortColumn))
 
END
ELSE
 
BEGIN
  
SET @SortTable = @Tables
  
SET @SortName = @strSortColumn
 
END

SELECT @type=t.name, @prec=c.prec
FROM sysobjects o 
JOIN syscolumns c on o.id=c.id
JOIN systypes t on c.xusertype=t.xusertype
WHERE o.name = @SortTable AND c.name = @SortName

IF CHARINDEX('char'@type> 0
 
SET @type = @type + '(' + CAST(@prec AS varchar+ ')'

DECLARE @strPageSize varchar(50)
DECLARE @strStartRow varchar(50)
DECLARE @strFilter varchar(200)
DECLARE @strSimpleFilter varchar(200)
DECLARE @strGroup varchar(200)

/*默认当前页*/
IF @CurrentPage < 1
 
SET @CurrentPage = 1

/*设置分页参数.*/
SET @strPageSize = CAST(@PageSize AS varchar(50))
SET @strStartRow = CAST(((@CurrentPage - 1)*@PageSize + 1AS varchar(50))

/*筛选以及分组语句.*/
IF @Filter IS NOT NULL AND @Filter != ''
 
BEGIN
  
SET @strFilter = ' WHERE ' + @Filter + ' '
  
SET @strSimpleFilter = ' AND ' + @Filter + ' '
 
END
ELSE
 
BEGIN
  
SET @strSimpleFilter = ''
  
SET @strFilter = ''
 
END

IF @Group IS NOT NULL AND @Group != ''
 
SET @strGroup = ' GROUP BY ' + @Group + ' '
ELSE
 
SET @strGroup = ''

 

declare @cTemp NVarChar(1000)
declare @PageCount int,  @lineCount decimal

CREATE TABLE #temp(linecount INT)

set @cTemp = 'insert into #temp (linecount)  select  count(*)  FROM ' + @Tables +  @strFilter + ' ' + @strGroup 
 
exec (@cTemp)

select @lineCount = linecount from #temp

drop table #temp


if(@docount=1)  
 
begin
  
select @lineCount '总行数' 
 
end
else  

begin
 
 
--得到总页数
 set @PageCount = CEILING(@lineCount/@strPageSize)
 
if @CurrentPage > @PageCount
  
begin
   
set @cTemp = 'SELECT ' + @Fields + ' FROM ' + @Tables + ' WHERE 1>2 ' 
  
end
 
else
  
begin
   
   
/*执行查询语句*/
   
   
set @cTemp = 'DECLARE @SortColumn ' + @type + '
   SET ROWCOUNT 
' + @strStartRow + '
   SELECT @SortColumn=
' + @strSortColumn + ' FROM ' + @Tables + @strFilter + ' ' + @strGroup + ' ORDER BY ' + @Sort + '
   SET ROWCOUNT 
' + @strPageSize + '
   SELECT 
' + @Fields + ' FROM ' + @Tables + ' WHERE ' + @strSortColumn + @operator + ' @SortColumn ' + @strSimpleFilter + ' ' + @strGroup + ' ORDER BY ' + @Sort + ''
   
  
end

 
--print @cTemp
 EXEC(@cTemp)
end 

-----------------------------------------------------

 

分页查询的方法已经很多很多,在这里我也加入成为其中一员。
      SQL Server中有一个Set Rowcount的的设置,它的意思是使命令的处理在响应指定的行数之后停止处理命令,利用这个特点,我们可以借用它来在一个千万行级数据表中实现高性能分页查询。先来说说实现方式:
      
1、我们来假定Table中有一个已经建立了索引的主键字段ID(整数型),我们将按照这个字段来取数据进行分页。
      
2、页的大小我们放在@PageSize中
      
3、当前页号我们放在@CurrentPage中
      
4、如何让记录指针快速滚动到我们要取的数据开头的那一行呢,这是关键所在!有了Set RowCount,我们就很容易实现了。
      
5、如果我们成功地滚动记录指针到我们要取的数据的开头的那一行,然后我们把那一行的记录的ID字段的值记录下来,那么,利用Top和条件,我们就很容易的得到指定页的数据了。当然,有了Set RowCount,我们难道还用Top么?
      看看Set Rowcount怎么来帮我们的忙吧:

Declare @ID int
Declare @MoveRecords int

--@CurrentPage和@PageSize是传入参数
Set @MoveRecords=@CurrentPage * @PageSize+1

--下面两行实现快速滚动到我们要取的数据的行,并把ID记录下来
Set Rowcount @MoveRecords
Select @ID=ID from Table1 Order by ID

Set Rowcount @PageSize
--最恨为了减少麻烦使用*了,但是在这里为了说明方便,暂时用一下
Select * From Table1 Where ID>=@ID Order By ID
Set Rowcount 0
      大家可以试试看,在一个1千W记录的表里面,一下子方翻页到第100页(每页100条),看看有多快!

 

分享]千万数量级分页存储过程(带效果演示)
效果演示:http:
//www.cn5135.com/_App/Opportunities/QueryResult.aspx

CREATE PROCEDURE CN5135_SP_Pagination
/*
***************************************************************
** 千万数量级分页存储过程 **
***************************************************************
参数说明:
1.Tables :表名称,视图
2.PrimaryKey :主关键字
3.Sort :排序语句,不带Order By 比如:NewsID Desc,OrderRows Asc
4.CurrentPage :当前页码
5.PageSize :分页尺寸
6.Filter :过滤语句,不带Where 
7.Group :Group语句,不带Group By
效果演示:http://www.cn5135.com/_App/Opportunities/QueryResult.aspx
**************************************************************
*/

(
@Tables varchar(1000),
@PrimaryKey varchar