分页存储过程

来源:互联网 发布:淘宝怎么更换账户开店 编辑:程序博客网 时间:2024/05/21 06:35

1------------------------------------------------
--游标不是明智的选择,在小数据量时可以使用
create   procedure hahaha
  @sqlstr nvarchar(4000), --查询字符串
  @currentpage int, --第N页
  @pagesize int --每页行数
  as
  set nocount on
  declare @P1 int, --P1是游标的id
  @rowcount int
  exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount output
  select ceiling(1.0*@rowcount/@pagesize) as 总页数--,@rowcount as 总行数,@currentpage as 当前页
  set @currentpage=(@currentpage-1)*@pagesize+1
  exec sp_cursorfetch @P1,16,@currentpage,@pagesize  
  exec sp_cursorclose @P1
  set nocount off
 
  测试: hahaha '任何条件的SQL语句',2,10
 
 
  2----------------
 
 
  CREATE PROCEDURE GetRecordFromPage
    @tblName     varchar(255),     -- 表名
    @fldName     varchar(255),     -- 字段名
    @PageSize     int = 10,         -- 页尺寸
    @PageIndex   int = 1,         -- 页码
    @IsCount     bit = 0,         -- 返回记录总数, 非 0 值则返回
    @OrderType   bit = 0,         -- 设置排序类型, 非 0 值则降序
    @strWhere     varchar(1000) = ''   -- 查询条件 (注意: 不要加 where)
  AS
 
  declare   @strSQL   varchar(1000)     -- 主语句
  declare @strTmp   varchar(300)     -- 临时变量
  declare @strOrder varchar(400)     -- 排序类型
 
  if @OrderType != 0
  begin
    set @strTmp = "<(select min"
    set @strOrder = " order by [" + @fldName +"] desc"
  end
  else
  begin
    set @strTmp = ">(select max"
    set @strOrder = " order by [" + @fldName +"] asc"
  end
 
  set @strSQL = "select top " + str(@PageSize) + " * from ["
    + @tblName + "] where [" + @fldName + "]" + @strTmp + "(["
    + @fldName + "]) from (select top " + str((@PageIndex-1)*@PageSize) + " ["
    + @fldName + "] from [" + @tblName + "]" + @strOrder + ") as tblTmp)"
    + @strOrder
 
  if @strWhere != &apos;&apos;
    set @strSQL = "select top " + str(@PageSize) + " * from ["
      + @tblName + "] where [" + @fldName + "]" + @strTmp + "(["
      + @fldName + "]) from (select top " + str((@PageIndex-1)*@PageSize) + " ["
      + @fldName + "] from [" + @tblName + "] where (" + @strWhere + ") "
      + @strOrder + ") as tblTmp) and (" + @strWhere + ") " + @strOrder
 
  if @PageIndex = 1
  begin
    set @strTmp = ""
    if @strWhere != &apos;&apos;
      set @strTmp = " where (" + @strWhere + ")"
 
    set @strSQL = "select top " + str(@PageSize) + " * from ["
      + @tblName + "]" + @strTmp + " " + @strOrder
  end
 
  if @IsCount != 0
    set @strSQL = "select count(*) as Total from [" + @tblName + "]"
 
  exec (@strSQL)
  GO
3--------------------------------

 


CREATE Proc p_show
@QueryStr nvarchar(4000), --表名、视图名、查询语句
@PageSize int=10,   --每页的大小(行数)
@PageCurrent int=1,   --要显示的页
@FdShow nvarchar (4000)= &apos; &apos;, --要显示的字段列表,如果查询结果有标识字段,需要指定此值,且不包含标识字段
@FdOrder nvarchar (1000)= &apos; &apos; --排序字段列表
as
declare @FdName nvarchar(250) --表中的主键或表、临时表中的标识列名
  ,@Id1 varchar(20),@Id2 varchar(20) --开始和结束的记录号
  ,@Obj_ID int   --对象ID
--表中有复合主键的处理
declare @strfd nvarchar(2000) --复合主键列表
  ,@strjoin nvarchar(4000) --连接字段
  ,@strwhere nvarchar(2000) --查询条件


select @Obj_ID=object_id(@QueryStr)
  ,@FdShow=case isnull(@FdShow, &apos; &apos;) when &apos; &apos; then &apos; * &apos; else &apos; &apos;+@FdShow end
  ,@FdOrder=case isnull(@FdOrder, &apos; &apos;) when &apos; &apos; then &apos; &apos; else &apos; order by &apos;+@FdOrder end
  ,@QueryStr=case when @Obj_ID is not null then &apos; &apos;+@QueryStr else &apos; ( &apos;+@QueryStr+ &apos;) a &apos; end

--如果显示第一页,可以直接用top来完成
if @PageCurrent=1
begin
  select @Id1=cast(@PageSize as varchar(20))
  exec( &apos;select top &apos;+@Id1+@FdShow+ &apos; from &apos;+@QueryStr+@FdOrder)
  return
end

--如果是表,则检查表中是否有标识更或主键
if @Obj_ID is not null and objectproperty(@Obj_ID, &apos;IsTable &apos;)=1
begin
  select @Id1=cast(@PageSize as varchar(20))
  ,@Id2=cast((@PageCurrent-1)*@PageSize as varchar(20))

  select @FdName=name from syscolumns where id=@Obj_ID and status=0x80
  if @@rowcount=0   --如果表中无标识列,则检查表中是否有主键
  begin
  if not exists(select 1 from sysobjects where parent_obj=@Obj_ID and xtype= &apos;PK &apos;)
  goto lbusetemp   --如果表中无主键,则用临时表处理

  select @FdName=name from syscolumns where id=@Obj_ID and colid in(
  select colid from sysindexkeys where @Obj_ID=id and indid in(
    select indid from sysindexes where @Obj_ID=id and name in(
    select name from sysobjects where xtype= &apos;PK &apos; and parent_obj=@Obj_ID
  )))
  if @@rowcount> 1   --检查表中的主键是否为复合主键
  begin
  select @strfd= &apos; &apos;,@strjoin= &apos; &apos;,@strwhere= &apos; &apos;
  select @strfd=@strfd+ &apos;,[ &apos;+name+ &apos;] &apos;
    ,@strjoin=@strjoin+ &apos; and a.[ &apos;+name+ &apos;]=b.[ &apos;+name+ &apos;] &apos;
    ,@strwhere=@strwhere+ &apos; and b.[ &apos;+name+ &apos;] is null &apos;
    from syscolumns where id=@Obj_ID and colid in(
    select colid from sysindexkeys where @Obj_ID=id and indid in(
    select indid from sysindexes where @Obj_ID=id and name in(
    select name from sysobjects where xtype= &apos;PK &apos; and parent_obj=@Obj_ID
    )))
  select @strfd=substring(@strfd,2,2000)
    ,@strjoin=substring(@strjoin,5,4000)
    ,@strwhere=substring(@strwhere,5,4000)
  goto lbusepk
  end
  end
end
else
  goto lbusetemp

/*--使用标识列或主键为单一字段的处理方法--*/
lbuseidentity:
  exec( &apos;select top &apos;+@Id1+@FdShow+ &apos; from &apos;+@QueryStr
  + &apos; where &apos;+@FdName+ &apos; not in(select top &apos;
  +@Id2+ &apos; &apos;+@FdName+ &apos; from &apos;+@QueryStr+@FdOrder
  + &apos;) &apos;+@FdOrder
  )
  return

/*--表中有复合主键的处理方法--*/
lbusepk:  
  exec( &apos;select &apos;+@FdShow+ &apos; from(select top &apos;+@Id1+ &apos; a.* from
  (select top 100 percent * from &apos;+@QueryStr+@FdOrder+ &apos;) a
  left join (select top &apos;+@Id2+ &apos; &apos;+@strfd+ &apos;
  from &apos;+@QueryStr+@FdOrder+ &apos;) b on &apos;+@strjoin+ &apos;
  where &apos;+@strwhere+ &apos;) a &apos;
  )
  return

/*--用临时表处理的方法--*/
lbusetemp:  
select @FdName= &apos;[ID_ &apos;+cast(newid() as varchar(40))+ &apos;] &apos;
  ,@Id1=cast(@PageSize*(@PageCurrent-1) as varchar(20))
  ,@Id2=cast(@PageSize*@PageCurrent-1 as varchar(20))

exec( &apos;select &apos;+@FdName+ &apos;=identity(int,0,1), &apos;+@FdShow+ &apos;
  into #tb from &apos;+@QueryStr+@FdOrder+ &apos;
  select &apos;+@FdShow+ &apos; from #tb where &apos;+@FdName+ &apos; between &apos;
  +@Id1+ &apos; and &apos;+@Id2
  )

GO


create table ta(col1 int,col2 char(2))
go
insert ta select 1,&apos;2&apos;

exec p_show &apos;(select * from ta)&apos;,10,1,&apos;col1,col2&apos;,&apos;col2&apos;


drop table ta
drop proc p_show

/*

col1    col2
----------- ----
1     2

(所影响的行数为 1 行)
*/

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

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

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

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

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

--第一页直接显示
IF @PageCurrent=1
EXEC(N&apos;SELECT TOP &apos;+@TopN
+N&apos; &apos;+@FieldShow
+N&apos; FROM &apos;+@tbname
+N&apos; &apos;+@Where
+N&apos; &apos;+@FieldOrder)
ELSE
BEGIN
--处理别名
IF @FieldShow=N&apos;*&apos;
SET @FieldShow=N&apos;a.*&apos;

--生成主键(惟一键)处理条件
DECLARE @Where1 nvarchar(4000),@Where2 nvarchar(4000),
@s nvarchar(1000),@Field sysname
SELECT @Where1=N&apos;&apos;,@Where2=N&apos;&apos;,@s=@FieldKey
WHILE CHARINDEX(N&apos;,&apos;,@s)>0
SELECT @Field=LEFT(@s,CHARINDEX(N&apos;,&apos;,@s)-1),
@s=STUFF(@s,1,CHARINDEX(N&apos;,&apos;,@s),N&apos;&apos;),
@Where1=@Where1+N&apos; AND a.&apos;+@Field+N&apos;=b.&apos;+@Field,
@Where2=@Where2+N&apos; AND b.&apos;+@Field+N&apos; IS NULL&apos;,
@Where=REPLACE(@Where,@Field,N&apos;a.&apos;+@Field),
@FieldOrder=REPLACE(@FieldOrder,@Field,N&apos;a.&apos;+@Field),
@FieldShow=REPLACE(@FieldShow,@Field,N&apos;a.&apos;+@Field)
SELECT @Where=REPLACE(@Where,@s,N&apos;a.&apos;+@s),
@FieldOrder=REPLACE(@FieldOrder,@s,N&apos;a.&apos;+@s),
@FieldShow=REPLACE(@FieldShow,@s,N&apos;a.&apos;+@s),
@Where1=STUFF(@Where1+N&apos; AND a.&apos;+@s+N&apos;=b.&apos;+@s,1,5,N&apos;&apos;),
@Where2=CASE
WHEN @Where=&apos;&apos; THEN N&apos;WHERE (&apos;
ELSE @Where+N&apos; AND (&apos;
END+N&apos;b.&apos;+@s+N&apos; IS NULL&apos;+@Where2+N&apos;)&apos;

--执行查询
EXEC(N&apos;SELECT TOP &apos;+@TopN
+N&apos; &apos;+@FieldShow
+N&apos; FROM &apos;+@tbname
+N&apos; a LEFT JOIN(SELECT TOP &apos;+@TopN1
+N&apos; &apos;+@FieldKey
+N&apos; FROM &apos;+@tbname
+N&apos; a &apos;+@Where
+N&apos; &apos;+@FieldOrder
+N&apos;)b ON &apos;+@Where1
+N&apos; &apos;+@Where2
+N&apos; &apos;+@FieldOrder)
END
GO

 

5--------------------------简单精炼的通用分页存储过程------------------------------------

----------------------------------------------------------
create proc procPagination
@pageSize int=10,--每一页显示的条数
@pageIndex int=1,--当前页的索影
@tablename varchar(200),--要分页的表名或视图名
@filed varchar(50)--一般为表的主键或唯一的字段
as
    declare @sql varchar(1000)
    declare @where varchar(200)
    set @sql='select top '+str(@pageSize)+' * from ['+@tablename+ '] where '
    set @where='['+@filed+'] not in (select top '+str((@pageIndex-1)*@pagesize)+' ['+@filed+'] from ['+@tablename +'] order by ['
+@filed+']) order by ['+@filed+']'
  set @sql=@sql+@where
  exec (@sql)
go
-----------------------------------------------------------------------
测试语句:exec procPagination 页条数,页索引,'表名','主键或唯一标识'
    如 :exec procPagination 10,90,'info','aa'

 

 

原创粉丝点击