我比较菜 不懂分布式存储过程和一般的有什么区别? 这个么?1CREATE PROCEDURE sp_paging 2@sqlstr NVARCHAR(4000), --查询字符串 3@currentpage INT, --第N页>=1 4@pagesize INT --每页行数 5AS 6SET NOCOUNT ON 7declare @P1 INT, --P1是游标的id 8@rowcount INT 9declare @allPages int 10EXEC sp_cursoropen @P1 OUTPUT,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount OUTPUT 11set @allPages=CEILING(1.0*@rowcount/@pagesize) 12if(@currentpage>@allPages) 13begin 14 set @currentpage=@allPages 15end 16if(@currentpage<1) 17begin 18 set @currentpage=1 19end 20SELECT @allPages AS Totalpages,@rowcount as Rowcounts,@currentpage as CurrentPage 21SET @currentpage=(@currentpage-1)*@pagesize+1 22EXEC sp_cursorfetch @P1,16,@currentpage,@pagesize 23EXEC sp_cursorclose @P1 24SET NOCOUNT OFF 25GO
declare proc pager ( @pagesize int @pagecount int ) as select top (@pagecount) from table where id > (@pagesize * @pagecount) 类似这个,好久没有写了
先求出总记录数方法:select count(*) form tablename 设置pagesize 获得页数, 根据pageindexchanging 获取currentpageindex 可以算出 每页的标识列的id,startindex和endindex 然后select column form tablename where id>=startindex & id<=endindex 以上大体思路就那样。
ALTER proc [dbo].[proc_viewlist] @Table varchar(300), --表名 @Where varchar(7500),--查询条件 @Cou varchar(500),--查询的列,查询全部用* @NewPageIndex int,--当前页码 @PageSize int,--分页条数 @order varchar(100), --排序列, @isDistinct int=0 --是否带distinct 如果带,则isDistinct为1,不带 可以省略此参数 as declare @str varchar(8000) ---------------------------------------------查询总记录数------------------------------------ if @isDistinct <> 0 set @str='select count(1) from (select '+@cou+' from '+@table else set @str='select count(1) from '+@table if len(@where)<>0 set @str=@str+' where '+@where if @isDistinct <> 0 set @str=@str+' )a' ---------------------------------------------查询当前页记录----------------------------------- if @isDistinct <> 0 set @str=@str+' select * from(select *,row_number() over(order by '+@order+' ) as Rownum from ( select '+@cou+' from '+@table else set @str=@str+' select * from ( select '+@cou+' ,row_number() over(order by '+@order+') as Rownum from '+@table if len(@where)<>0 set @str=@str+' where '+@where if @isDistinct <> 0 set @str=@str+' )T1)T ' else set @str=@str+' )T ' set @str=@str+'where Rownum between '+cast((@NewPageIndex-1)*@PageSize+1 as varchar(20))+' and '+cast(@NewPageIndex*@PageSize as varchar(20)) if len(@order)<>0 set @str=@str+' order by '+@order exec(@str) print (@str)
通用的分页方法是 select top 10*2 * from table where id not in(top 10*2 id from table) 例子为取第三页 通常都是看第一页,速度非常快此方法看最后一页速度最慢, 所以尽量限定一下
写错 select top 10 * from table where id not in(top 10*2 id from table)
实现小数据量和海量数据的通用分页显示存储过程 建立一个 Web 应用,分页浏览功能必不可少。这个问题是数据库处理中十分常见的问题。经典的数据分页方法是:ADO 纪录集分页法,也就是利用ADO自带的分页功能(利用游标)来实现分页。但这种分页方法仅适用于较小数据量的情形,因为游标本身有缺点:游标是存放在内存中,很费内存。游标一建立,就将相关的记录锁住,直到取消游标。游标提供了对特定集合中逐行扫描的手段,一般使用游标来逐行遍历数据,根据取出数据条件的不同进行不同的操作。而对于多表和大表中定义的游标(大的数据集合)循环很容易使程序进入一个漫长的等待甚至死机。 更重要的是,对于非常大的数据模型而言,分页检索时,如果按照传统的每次都加载整个数据源的方法是非常浪费资源的。现在流行的分页方法一般是检索页面大小的块区的数据,而非检索所有的数据,然后单步执行当前行。 最早较好地实现这种根据页面大小和页码来提取数据的方法大概就是“俄罗斯存储过程”。这个存储过程用了游标,由于游标的局限性,所以这个方法并没有得到大家的普遍认可。 后来,网上有人改造了此存储过程,下面的存储过程就是结合我们的办公自动化实例写的分页存储过程: -- ============================================= -- Author: Takako_Yang -- Create date: 2009/10/20 -- Description: SQL如何分页以及优化 -- ============================================= CREATE PROCEDURE USP_Test_Select @pagesize int,--页面大小,如每页存储10条记录 @pageindex int,--目前页面 @startdate datetime,--开始日期 @duedate datetime--结束日期 ASBEGIN with A as ( select row_numer() over(order by date) as rowID,--依时间排序,定义一个自增列用作分页 * from TableA where date between @startdate and @duedate --by条件得到所有的资料 ) select * from A where rowID >(@pageindex-1)*@pagesize and rowID<=@pageindex*@pagesize order by date END GO/**//* 当然,with A as()这种写法还是可以再优化的. 表变量的效率>临时表的效率>with A as()的效率 以表变量为例,如下,省略Create部分 */BEGIN declare @indexTable table(rowID int identity(1,1),nid int) insert into @indexTable(nid) select gid from TableA where date between @startdate and @duedate order by date select A.* from TableA A inner join @indexTable B on A.gid=B.nid and B.rowID>(@pageindex-1)*@pagesize and B.rowID<=@pageindex*@pagesize order by B.rowID END下面一段SQL是Happyflystone整理的分页function。摘录如下:-- ============================================= -- Author: Happyflystone -- Create date: 2007/11/18 -- Description: SQL如何分页以及优化 -- ============================================= -- 这一段Happyflystone写的太长了,而且效率要在1000页以上才能体现出来..我没看-.-谁有兴趣的可以看看CREATE PROCEDURE pagination3 @tblName varchar(255), -- 表名 @strGetFields varchar(1000) = ''*'', -- 需要返回的列 @fldName varchar(255)='''', -- 排序的字段名 @PageSize int = 10, -- 页尺寸 @PageIndex int = 1, -- 页码 @doCount bit = 0, -- 返回记录总数, 非 0 值则返回 @OrderType bit = 0, -- 设置排序类型, 非 0 值则降序 @strWhere varchar(1500) = '''' -- 查询条件 (注意: 不要加 where) ASdeclare @strSQL varchar(5000) -- 主语句 declare @strTmp varchar(110) -- 临时变量 declare @strOrder varchar(400) -- 排序类型if @doCount != 0 begin if @strWhere !='''' set @strSQL = "select count(*) as Total from [" + @tblName + "] where "+@strWhere else set @strSQL = "select count(*) as Total from [" + @tblName + "]" end --以上代码的意思是如果@doCount传递过来的不是0,就执行总数统计。以下的所有代码都是@doCount为0的情况:else 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" endif @PageIndex = 1 begin if @strWhere != '''' set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " from [" + @tblName + "] where " + @strWhere + " " + @strOrder elseset @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " from ["+ @tblName + "] "+ @strOrder --如果是第一页就执行以上代码,这样会加快执行速度end else begin --以下代码赋予了@strSQL以真正执行的SQL代码 set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " from [" + @tblName + "] where [" + @fldName + "]" + @strTmp + "(["+ @fldName + "]) from (select top " + str((@PageIndex-1)*@PageSize) + " ["+ @fldName + "] from [" + @tblName + "]" + @strOrder + ") as tblTmp)"+ @strOrderif @strWhere != '''' set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " from [" + @tblName + "] where [" + @fldName + "]" + @strTmp + "([" + @fldName + "]) from (select top " + str((@PageIndex-1)*@PageSize) + " [" + @fldName + "] from [" + @tblName + "] where " + @strWhere + " " + @strOrder + ") as tblTmp) and " + @strWhere + " " + @strOrder end end exec (@strSQL)GO
这个我做过,分页存储过程可以。但只能用唯一性的主键排序,你想改成别的排序方式,对不起,你会发现翻页的时候页码在乱跳。 #28楼,你如果不能保证排序字段@fldName的唯一性,那这个存储过程就不能用。我举个例子,简单点的 id name 1 a 2 a 3 c 4 a 5 a 6 b 7 b 8 c 9 c 10 a where条件为空,如果pagesize=3,按name字段排序,可以看到表中name=a有5条 那么第一页取出的是id为1,2,4三条, 这时候点下一页,就把另两条name=a的过滤掉了 如果是唯一的id就没问题。
存储过程优化
在要查询的表上建立适当的索引
分区分页
http://topic.csdn.net/u/20080627/12/4a404bb1-6667-466a-925a-4d7bf690695e.html
http://topic.csdn.net/u/20090113/16/cac6480c-84ff-4ae3-8fa1-11cfa39fd8ea.html?28098
这个么?1CREATE PROCEDURE sp_paging
2@sqlstr NVARCHAR(4000), --查询字符串
3@currentpage INT, --第N页>=1
4@pagesize INT --每页行数
5AS
6SET NOCOUNT ON
7declare @P1 INT, --P1是游标的id
8@rowcount INT
9declare @allPages int
10EXEC sp_cursoropen @P1 OUTPUT,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount OUTPUT
11set @allPages=CEILING(1.0*@rowcount/@pagesize)
12if(@currentpage>@allPages)
13begin
14 set @currentpage=@allPages
15end
16if(@currentpage<1)
17begin
18 set @currentpage=1
19end
20SELECT @allPages AS Totalpages,@rowcount as Rowcounts,@currentpage as CurrentPage
21SET @currentpage=(@currentpage-1)*@pagesize+1
22EXEC sp_cursorfetch @P1,16,@currentpage,@pagesize
23EXEC sp_cursorclose @P1
24SET NOCOUNT OFF
25GO
(
@pagesize int
@pagecount int
)
as
select top (@pagecount) from table where id > (@pagesize * @pagecount)
类似这个,好久没有写了
设置pagesize
获得页数,
根据pageindexchanging
获取currentpageindex
可以算出 每页的标识列的id,startindex和endindex
然后select column form tablename where id>=startindex & id<=endindex
以上大体思路就那样。
ALTER proc [dbo].[proc_viewlist]
@Table varchar(300), --表名
@Where varchar(7500),--查询条件
@Cou varchar(500),--查询的列,查询全部用*
@NewPageIndex int,--当前页码
@PageSize int,--分页条数
@order varchar(100), --排序列,
@isDistinct int=0 --是否带distinct 如果带,则isDistinct为1,不带 可以省略此参数
as
declare @str varchar(8000)
---------------------------------------------查询总记录数------------------------------------
if @isDistinct <> 0
set @str='select count(1) from (select '+@cou+' from '+@table
else
set @str='select count(1) from '+@table
if len(@where)<>0
set @str=@str+' where '+@where
if @isDistinct <> 0
set @str=@str+' )a'
---------------------------------------------查询当前页记录-----------------------------------
if @isDistinct <> 0
set @str=@str+' select * from(select *,row_number() over(order by '+@order+' ) as Rownum from ( select '+@cou+' from '+@table
else
set @str=@str+' select * from ( select '+@cou+' ,row_number() over(order by '+@order+') as Rownum from '+@table
if len(@where)<>0
set @str=@str+' where '+@where
if @isDistinct <> 0
set @str=@str+' )T1)T '
else
set @str=@str+' )T '
set @str=@str+'where Rownum between '+cast((@NewPageIndex-1)*@PageSize+1 as varchar(20))+' and '+cast(@NewPageIndex*@PageSize as varchar(20))
if len(@order)<>0
set @str=@str+' order by '+@order
exec(@str)
print (@str)
例子为取第三页
通常都是看第一页,速度非常快此方法看最后一页速度最慢, 所以尽量限定一下
写错
select top 10 * from table where id not in(top 10*2 id from table)
更重要的是,对于非常大的数据模型而言,分页检索时,如果按照传统的每次都加载整个数据源的方法是非常浪费资源的。现在流行的分页方法一般是检索页面大小的块区的数据,而非检索所有的数据,然后单步执行当前行。
最早较好地实现这种根据页面大小和页码来提取数据的方法大概就是“俄罗斯存储过程”。这个存储过程用了游标,由于游标的局限性,所以这个方法并没有得到大家的普遍认可。
后来,网上有人改造了此存储过程,下面的存储过程就是结合我们的办公自动化实例写的分页存储过程:
-- =============================================
-- Author: Takako_Yang
-- Create date: 2009/10/20
-- Description: SQL如何分页以及优化
-- =============================================
CREATE PROCEDURE USP_Test_Select
@pagesize int,--页面大小,如每页存储10条记录
@pageindex int,--目前页面
@startdate datetime,--开始日期
@duedate datetime--结束日期
ASBEGIN
with A as
(
select row_numer() over(order by date) as rowID,--依时间排序,定义一个自增列用作分页
*
from TableA
where date between @startdate and @duedate --by条件得到所有的资料
)
select *
from A
where rowID >(@pageindex-1)*@pagesize and rowID<=@pageindex*@pagesize
order by date
END
GO/**//*
当然,with A as()这种写法还是可以再优化的.
表变量的效率>临时表的效率>with A as()的效率
以表变量为例,如下,省略Create部分
*/BEGIN
declare @indexTable table(rowID int identity(1,1),nid int)
insert into @indexTable(nid)
select gid from TableA where date between @startdate and @duedate order by date
select A.*
from TableA A inner join @indexTable B
on A.gid=B.nid
and B.rowID>(@pageindex-1)*@pagesize and B.rowID<=@pageindex*@pagesize
order by B.rowID
END下面一段SQL是Happyflystone整理的分页function。摘录如下:-- =============================================
-- Author: Happyflystone
-- Create date: 2007/11/18
-- Description: SQL如何分页以及优化
-- =============================================
-- 这一段Happyflystone写的太长了,而且效率要在1000页以上才能体现出来..我没看-.-谁有兴趣的可以看看CREATE PROCEDURE pagination3
@tblName varchar(255), -- 表名
@strGetFields varchar(1000) = ''*'', -- 需要返回的列
@fldName varchar(255)='''', -- 排序的字段名
@PageSize int = 10, -- 页尺寸
@PageIndex int = 1, -- 页码
@doCount bit = 0, -- 返回记录总数, 非 0 值则返回
@OrderType bit = 0, -- 设置排序类型, 非 0 值则降序
@strWhere varchar(1500) = '''' -- 查询条件 (注意: 不要加 where)
ASdeclare @strSQL varchar(5000) -- 主语句
declare @strTmp varchar(110) -- 临时变量
declare @strOrder varchar(400) -- 排序类型if @doCount != 0
begin
if @strWhere !=''''
set @strSQL = "select count(*) as Total from [" + @tblName + "] where "+@strWhere
else
set @strSQL = "select count(*) as Total from [" + @tblName + "]"
end
--以上代码的意思是如果@doCount传递过来的不是0,就执行总数统计。以下的所有代码都是@doCount为0的情况:else
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"
endif @PageIndex = 1
begin
if @strWhere != '''' set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ "
from [" + @tblName + "] where " + @strWhere + " " + @strOrder
elseset @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ "
from ["+ @tblName + "] "+ @strOrder
--如果是第一页就执行以上代码,这样会加快执行速度end
else
begin
--以下代码赋予了@strSQL以真正执行的SQL代码
set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " from ["
+ @tblName + "] where [" + @fldName + "]" + @strTmp + "(["+ @fldName + "])
from (select top " + str((@PageIndex-1)*@PageSize) + " ["+ @fldName + "]
from [" + @tblName + "]" + @strOrder + ") as tblTmp)"+ @strOrderif @strWhere != ''''
set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " from ["
+ @tblName + "] where [" + @fldName + "]" + @strTmp + "(["
+ @fldName + "]) from (select top " + str((@PageIndex-1)*@PageSize) + " ["
+ @fldName + "] from [" + @tblName + "] where " + @strWhere + " "
+ @strOrder + ") as tblTmp) and " + @strWhere + " " + @strOrder
end end exec (@strSQL)GO
http://blog.csdn.net/snoopy83101/archive/2009/09/09/4536582.aspx
#28楼,你如果不能保证排序字段@fldName的唯一性,那这个存储过程就不能用。我举个例子,简单点的
id name
1 a
2 a
3 c
4 a
5 a
6 b
7 b
8 c
9 c
10 a
where条件为空,如果pagesize=3,按name字段排序,可以看到表中name=a有5条
那么第一页取出的是id为1,2,4三条,
这时候点下一页,就把另两条name=a的过滤掉了
如果是唯一的id就没问题。