IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[pager]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[pager]
GO


CREATE procedure [dbo].[pager]
@TBName nvarchar(2000)='',--表名,如 pinyin
@PageSize int=10,--每页的记录数,默认为 10
@PageIndex int=1,--表示当前页 1
@KeyField nvarchar(100)='ID',--关键字段名，默认为 ID,该字段要求是表中的索引 或 无重复和不为空的字段
@KeyAscDesc nvarchar(4)='ASC',--关键字的升、降序，默认为升序 ASC , 降序为 DESC
@Fields nvarchar(2000)='*',--所选择的列名，默认为全选
@Condition nvarchar(2000)='',--where 条件,默认为空
@Order nvarchar(200)=''--排序条件,默认为空
as
if @TBName = ''
   begin
       raiserror('请指定表名！',11,1)
       return
   end
if @PageSize <=0 or @PageIndex < 0 
   begin
       raiserror('当前页数和每页的记录数都必须大于零！',11,1)
       return
   end
   
if @KeyAscDesc = 'DESC'
set @KeyAscDesc = '<'
else
set @KeyAscDesc = '>'
if @Condition <> ''
set @Condition = ' where ' + @Condition

declare @SQL nvarchar(4000)

set @SQL = ''
if @PageIndex = 1
   set @SQL = @SQL + 'SELECT Top ' + cast(@PageSize as nvarchar(20)) + ' ' + @Fields + ' FROM ' + @TBName + @Condition + ' ' + @Order
else
   begin
declare @iTopNum int
set @iTopNum = @PageSize * (@PageIndex - 1)
set @SQL = @SQL + 'declare @sLastValue nvarchar(100)' + char(13)
set @SQL = @SQL + 'SELECT Top ' + cast(@iTopNum as nvarchar(20)) + ' @sLastValue=' + @KeyField + ' FROM ' + @TBName + @Condition + ' ' + @Order + char(13)

declare @Condition2 nvarchar(2000)
if @Condition = ''
   set @Condition2 = ' where ' + @KeyField + @KeyAscDesc + '@sLastValue '
else
   set @Condition2 = ' and ' + @KeyField + @KeyAscDesc + '@sLastValue '
set @SQL = @SQL + 'SELECT Top ' + cast(@PageSize as nvarchar(20)) + ' ' + @Fields + ' FROM ' + @TBName + @Condition + @Condition2 + @Order
   end
EXECUTE sp_executesql @SQL
GO

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[pagerdup]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[pagerdup]
GO

CREATE PROC [dbo].[pagerdup]
@tbname     sysname,             --要分页显示的表名 
@FieldKey   nvarchar(1000),      --用于定位记录的主键(惟一键)字段,可以是逗号分隔的多个字段 
@PageCurrent int=1,              --要显示的页码 
@PageSize   int=10,              --每页的大小(记录数) 
@FieldShow  nvarchar(1000)='',   --以逗号分隔的要显示的字段列表,如果不指定,则显示所有字段 
@FieldOrder  nvarchar(1000)='',  --以逗号分隔的排序字段列表,可以指定在字段后面指定DESC/ASC用于指定排序顺序 
@Where     nvarchar(1000)='',    --查询条件 
@PageCount  int OUTPUT           --总页数 
AS 
SET NOCOUNT ON 
--检查对象是否有效 
IF OBJECT_ID(@tbname) IS NULL 
BEGIN 
RAISERROR(N'对象"%s"不存在',1,16,@tbname) 
RETURN 
END 
IF OBJECTPROPERTY(OBJECT_ID(@tbname),N'IsTable')=0 
AND OBJECTPROPERTY(OBJECT_ID(@tbname),N'IsView')=0 
AND OBJECTPROPERTY(OBJECT_ID(@tbname),N'IsTableFunction')=0 
BEGIN 
RAISERROR(N'"%s"不是表、视图或者表值函数',1,16,@tbname) 
RETURN 
END 

--分页字段检查 
IF ISNULL(@FieldKey,N'')='' 
BEGIN 
RAISERROR(N'分页处理需要主键（或者惟一键）',1,16) 
RETURN 
END 

--其他参数检查及规范 
IF ISNULL(@PageCurrent,0)<1 SET @PageCurrent=1 
IF ISNULL(@PageSize,0)<1 SET @PageSize=10 
IF ISNULL(@FieldShow,N'')=N'' SET @FieldShow=N'*' 
IF ISNULL(@FieldOrder,N'')=N'' 
SET @FieldOrder=N'' 
ELSE 
SET @FieldOrder=N'ORDER BY '+LTRIM(@FieldOrder) 
IF ISNULL(@Where,N'')=N'' 
SET @Where=N'' 
ELSE 
SET @Where=N'WHERE ('+@Where+N')' 

--如果@PageCount为NULL值,则计算总页数(这样设计可以只在第一次计算总页数,以后调用时,把总页数传回给存储过程,避免再次计算总页数,对于不想计算总页数的处理而言,可以给@PageCount赋值) 
IF @PageCount IS NULL 
BEGIN 
DECLARE @sql nvarchar(4000) 
SET @sql=N'SELECT @PageCount=COUNT(*)' 
+N' FROM '+@tbname 
+N' '+@Where 
EXEC sp_executesql @sql,N'@PageCount int OUTPUT',@PageCount OUTPUT 
SET @PageCount=(@PageCount+@PageSize-1)/@PageSize 
END 

--计算分页显示的TOPN值 
DECLARE @TopN varchar(20),@TopN1 varchar(20) 
SELECT @TopN=@PageSize, 
@TopN1=@PageCurrent*@PageSize 

--第一页直接显示 
IF @PageCurrent=1 
EXEC(N'SELECT TOP '+@TopN 
+N' '+@FieldShow 
+N' FROM '+@tbname 
+N' '+@Where 
+N' '+@FieldOrder) 
ELSE 
BEGIN 
--生成主键(惟一键)处理条件 
DECLARE @Where1 nvarchar(4000),@s nvarchar(1000) 
SELECT @Where1=N'',@s=@FieldKey 
WHILE CHARINDEX(N',',@s)>0 
SELECT @s=STUFF(@s,1,CHARINDEX(N',',@s),N''), 
@Where1=@Where1 
+N' AND a.'+LEFT(@s,CHARINDEX(N',',@s)-1) 
+N'='+LEFT(@s,CHARINDEX(N',',@s)-1) 
SELECT @Where1=STUFF(@Where1+N' AND a.'+@s+N'='+@s,1,5,N''), 
@TopN=@TopN1-@PageSize 

--执行查询 
EXEC(N'SET ROWCOUNT '+@TopN1 
+N' SELECT '+@FieldKey 
+N' INTO # FROM '+@tbname 
+N' '+@Where 
+N' '+@FieldOrder 
+N' SET ROWCOUNT '+@TopN 
+N' DELETE FROM #' 
+N' SELECT '+@FieldShow 
+N' FROM '+@tbname 
+N' a WHERE EXISTS(SELECT * FROM # WHERE '+@Where1 
+N') '+@FieldOrder) 
END 
GO



IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[udp_Pagination]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[udp_Pagination]
GO


CREATE              PROCEDURE [dbo].[udp_Pagination] 
@TableName varchar(8000), 	--表名
@Fieldlist varchar(8000), 	--字段列表
@TableField varchar(200), 	--主键
@Where varchar(8000), 		--Where条件
@OrderFld varchar(500)='', 	--排序列表
@FieldIndex int =1, 		--当前页码
@PageSize int = 15, 		--页记录
@Sort varchar(8)='asc', 	--排序
@RecordCount int= -1 output 	--记录数
AS 
BEGIN 

	Declare @cmd nvarchar(4000) 
	Declare @uprecord int 
	Declare @Op varchar(2) -- 操作符 
	Declare @max_min varchar(4) -- 最大/最小计算
	declare @TopPageSize nvarchar(300)
	
	Set @op = '<' 
	Set @max_min = 'MIN' 
	If @Sort = 'asc' 
	Begin 
		set @Op = '>' 
		set @max_min = 'MAX' 
	End 
	
	If @Where = '' 
	Begin
		set @Where = '1=1'
	End

	If @OrderFld <> ''
	Begin
		set @OrderFld = ' Order by ' + @OrderFld + ' '
	End

	set @cmd = 'SELECT @RecordCount = count(1) FROM '+@TableName+' where '+@Where
	Exec sp_executesql @cmd, N'@RecordCount int output', @RecordCount output 
	if(@PageSize = 0)
		set @TopPageSize = ''
	else
		set @TopPageSize = 'top ' + cast(@PageSize AS NVARCHAR);

	set @uprecord=@FieldIndex * @PageSize 
	set @cmd = ''
	set @cmd = 'select ' + @TopPageSize +' '+ @Fieldlist + ' from ' + @TableName + 
			' where ' + @TableField + ' not in( ' +
				'select top '+ cast(@uprecord AS NVARCHAR)+' '+ @TableField + ' from ' + @TableName + ' where ' + @Where + @OrderFld +
			') and ' +  @Where + @OrderFld
--	print @cmd
	
-- 	IF @FieldIndex = 0 
-- 		set @cmd = 'SELECT TOP '+cast(@PageSize AS NVARCHAR)+' '+@Fieldlist+' FROM '+@TableName+' where '+@Where+@OrderFld 
-- 	ELSE 
-- 		set @cmd = 'SELECT TOP '+cast(@PageSize AS NVARCHAR)+' '+@Fieldlist+' FROM '+@TableName+' where '+ @Where+' AND '+ @TableField+' '+@op+' (SELECT '+@max_min+'('+@TableField+') FROM (SELECT TOP '+cast(@uprecord AS NVARCHAR)+' '+@TableField+' FROM '+@TableName+' where '+ @Where+@OrderFld+' ) AS TmpTbl ) '+@OrderFld 
	
	EXEC(@cmd) 

End
GO


IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[proc_Pager]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[proc_Pager]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


CREATE PROCEDURE [dbo].[proc_Pager]

	@tblName     nvarchar(500),				   ----要显示的表或多个表的连接 
	@fldName     nvarchar(500) = '*',          ----要显示的字段列表 
	@pageSize    int = 10,					   ----每页显示的记录个数 
	@page        int = 1,                      ----要显示那一页的记录 
	@fldSort    nvarchar(200) = null,		   ----排序字段列表或条件 
	@Sort        bit = 0,				       ----排序方法，0为升序，1为降序(如果是多字段排列Sort指代最后一个排序字段的排列顺序(最后一个排序字段不加排序标记)--程序传参如：' SortA Asc,SortB Desc,SortC ') 
	@strCondition    nvarchar(1000) = null,    ----查询条件,不需where
	@Counts    int = 0 output                  ----查询到的记录数 

AS
	SET NOCOUNT ON

	DECLARE @strOrder nvarchar(2000)
	declare @sql nvarchar(4000)

	IF @strCondition IS NOT NULL AND @strCondition != ''
		BEGIN
			SET @strCondition = ' where 1>0 ' + @strCondition + ' '
		END
	ELSE
		BEGIN
			SET @strCondition = ''
		END

	set @sql = 'select @Counts=count(*) from ' + @tblName + @strCondition  

	exec sp_executesql @sql,N'@Counts int out ',@Counts out

	IF @Sort=1 
		BEGIN
			SET @strOrder = ' order by '+@fldSort+ ' DESC'
		END
	ELSE
		BEGIN
			SET @strOrder = ' order by '+@fldSort+ ' ASC'
		END

	IF @page < 1
	   SET @page = 1

	if @page = 1 --第一页提高性能
		begin 
			set @sql = 'select top '+str(@pageSize)+' '+@fldName+' from '+@tblName+' '+@strCondition+@strOrder
		end 
	else
		begin
			 DECLARE @START_ID varchar(50)
			 DECLARE @END_ID varchar(50)
			 SET @START_ID = str((@page - 1) * @pageSize + 1)
			 SET @END_ID = str(@page * @pageSize)
				SET @sql = 'with temptbl as 
					(select ROW_NUMBER() OVER ('+@strOrder+')AS Row,'+@fldName+' from '+@tblName+@strCondition+') 
					select '+@fldName+' from temptbl where Row between '+@START_ID+' and '+@END_ID
				END

exec sp_executesql @sql
print @sql
GO
