| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 12082 人关注过本帖, 5 人收藏
标题:存储过程自定义分页详解
只看楼主 加入收藏
淡漠的茶
Rank: 1
等 级:新手上路
帖 子:48
专家分:0
注 册:2008-3-8
收藏
得分:0 
先回答风的问题
这个存储过程还有好处的
我们知道分页存储过程一般会采用一个字段作为分页的排除字段,一个或多个字段作为排序字段
目前网上很多分页存储过程会范一个毛病,就是排除字段和排序字段作为同一个参数传进来,这样就引发几个矛盾
1。由于排除字段的局限,无法多个字段排序
2。当这个字段为非主键时,就会发现一个问题,非主键代表不强制表内唯一,这就代表此字段可能有相同值,如果使用not in,就会把多条相同值排除掉,假如第一页中某一行和第二页中某一行上这个字段值相同,比如一个标记类别的非主键字段,都为数码相机,那么我们将第一页作为条件,使用not in来排除的话,那么第二页这行也会被排除,因为not in ,就是不等于这个序列中任何一个,而且后面都会被排除,这就造成丢失
3.当这个字段为非主键时,如果采用> < between and这样的排除方法时,也可能产生丢失,如果是连续几行这个字段值相同,就可能出现多取几行或者少取几行这样的不确定性,比如如果第二页10行,最后三行此字段相同,那么就会有7行 8行 ,如果第三页第一行还相同,那就可能第二页取到11行,这取决与你的表达式,总之是没有一个确切表达式

一般解决办法有三个,
第一种就是lz所用方法了,就是排除与排序参数分离,利用主键唯一性,使用not in将这页前的字段值全排除。这样通过重新排序和top选择,就会得到这页数据了,这是解决的方法之一,具备很大的通用性,对于中小型应用还是合适的
但是这样方法不是没有缺点的,就是在百万数据这个级别上 not in过于缓慢,一个原因是not in对索引不起作用(这点我不太确定,我只是听以前我们经理说的,呵呵),第二个原因由于sql执行顺序问题,导致必然的两次全表搜索,百万级数据上全表检索是很恐怖的,第三个原因not in所用的排除序列,在前面有百万条数据时,这个序列是很长的,可能有百万个值用逗号分隔,这个可能光内存就耗不少吧
 
第二种方法是查询时加入一个临时排序字段,用的不多

第三种方法是分离条件,将主键做一条件,非主键做一条件,或者根据需要就不利用非主键,再某些简单情况下
刚才我合了一个,写的不完全,大家补下吧

CREATE PROCEDURE List
@strFrom varchar(50) ,   --表名
@strFields varchar(200) = '*',  --查询列名
@strWhere  varchar(300) = '',     --查询条件
@strOrder varchar(100) = '', --排序列名
@pageIndex int = 1 ,         --页码
@pageSize int = 15,         --页面大小
@intOrder int = 0,        --排序类型  1为升序
@pk varchar(200)='',     --not in情况下给这个主键值
@countAll bigint output              --返回纪录总数用于计算页面数  
 AS
begin
--声明开始
declare   @countSQL   nvarchar(500) --记数语句
declare @strTemp varchar(100) --临时变量
declare @strOrders varchar(50) --排序语句
declare @strSQL varchar(1000)--主语句
declare   @R bigint
--声明结束

--统计记录总数开始
if @strWhere=''
    begin
        set @countSQL=N'select @R=count(*) from '+convert(nvarchar(50),@strFrom)
    end
else
    begin
        set @countSQL=N'select @R=count(*) from '+convert(nvarchar(50),@strFrom)+' where '+convert(nvarchar(300),@strWhere)
    end
exec SP_EXECUTESQL @countSQL, N' @R BIGINT OUTPUT',  @R OUTPUT
set   @countAll=  @R   
--统计记录总数结束

--排序开始
if @intOrder=0
    begin
        set @strTemp = '<(select min'
        set @strOrders = 'order by  '+@strOrder+' desc '
    end
else
   begin
       set @strTemp = '>(select max'
       set @strOrders = 'order by  '+@strOrder+' asc '
   end
--排序结束

--获取主语句开始
if @pageIndex=1
    begin
        if @strWhere=''
        begin
            set @strSQL='select top '+str(@pageSize)+'  '+@strFields+' from '+@strFrom+' '+@strOrders
        end
        else
        begin
            set @strSQL='select top '+str(@pageSize)+'  '+@strFields+' from '+@strFrom+' where '+@strWhere+' '+@strOrders
        end
    end
else
    begin
        if @pk=''
        begin
        if @strWhere =''
        begin
             set @strSQL= 'select top '+str(@pageSize)+' '+@strFields+' from '+@strFrom+' where '+@strOrder+@strTemp+' ('+@strOrder+')' +' from (select top '+str((@pageIndex-1)*@pageSize)+' '+@strFields+' from '+@strFrom+ ' '+@strOrders+ ') as tempTable ) '+@strOrders
        end
        else
        begin
             set @strSQL= 'select top '+str(@pageSize)+' '+@strFields+' from '+@strFrom+' where '+@strOrder+@strTemp+' ('+@strOrder+')' +' from (select top '+str((@pageIndex-1)*@pageSize)+' '+@strFields+' from '+@strFrom+ ' where '+@strWhere+' '+@strOrders+ ') as tempTable ) AND '+@strWhere+' '+@strOrders
        end
        end
        else
        begin
            if @strWhere=''
            begin
                set @strSQL= 'select top '+str(@pageSize)+' '+@strFields+' from '+@strFrom+' where '+@pk+' not in (select top '+str((@pageIndex-1)*@pageSize)+' '+@pk+' from '+@strFrom+ ' '+@strOrders+ ') '+@strOrders
            end
            else
            begin
                set @strSQL= 'select top '+str(@pageSize)+' '+@strFields+' from '+@strFrom+' where '+@pk+' not in (select top '+str((@pageIndex-1)*@pageSize)+' '+@pk+' from '+@strFrom+' where '+@strWhere+ ' '+@strOrders+ ') and '+@strWhere+' '+@strOrders
            end
        end
    end
--获取主语句结束

exec(@strSQL) --执行
end
GO

写的不太好,大家一起完善吧。可以根据情况减的
楼主,咱第一个问题就不讨论?

[[it] 本帖最后由 淡漠的茶 于 2008-4-5 18:58 编辑 [/it]]
2008-04-05 18:53
风风风风
Rank: 1
等 级:禁止发言
帖 子:26
专家分:0
注 册:2008-3-30
收藏
得分:0 
提示: 作者被禁止或删除 内容自动屏蔽
2008-04-05 19:19
hebingbing
Rank: 6Rank: 6
来 自:黄土高坡
等 级:贵宾
威 望:27
帖 子:3417
专家分:371
注 册:2007-10-22
收藏
得分:0 
我先从功能上分析一下淡漠的茶的这段代码:
首先淡漠的茶的这段代码可以说比我的多考虑了一个情况.就是在没有主键的情况下,我们先给表排序,完了再开始进行……,其他的方面基本上就差不多了……
再者我从性能上说说:
如果将我和他谈论的第一个问题作为比较的条件的话,他的是比我的多出来了一个将第一页分离的情况。虽然他给出了没有主键的情况的代码,但是这个不能作为性能方面的比较,首先很少有表没有主键的吧,甚至可以说是没有吧,再者……(这个再者留到下一段说)
我们来对比核心的内容:要执行的sql语句……但是好像没有区别……他还是采取了我的那种思想,而且要执行的过程也是没有减少……
总结的说就是如果不将第一个问题做为比较的条件的话,这两个存储过程在性能方面就没有什么区别可言……
而分有主键和没有主键我认为说不上多余反正也用途不是太大,因为很少有表是没有主键的……
不过我还是要感谢淡漠的茶一起探讨

[[it] 本帖最后由 hebingbing 于 2008-4-5 20:18 编辑 [/it]]
2008-04-05 20:12
ilovetea
Rank: 1
来 自:辽宁省锦州市
等 级:新手上路
帖 子:177
专家分:4
注 册:2008-3-31
收藏
得分:0 
精彩的交流,看了有收获,呵呵

我是爱喝茶的胖子,有空一起喝茶啊
我的百度博客:http://hi.baidu.com/33806380
2008-04-06 22:08
狂砍程序
Rank: 1
等 级:新手上路
帖 子:127
专家分:0
注 册:2007-9-27
收藏
得分:0 
精彩 大家加这个群 58808531
  里面都是我们这个论坛的朋友,希望大家都加入
2008-04-06 23:31
myyetao
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2008-8-11
收藏
得分:0 
怎么加了where不能用
@SelectWhere=''里面是要加where的吧,看了你的句子有2个句子前面没有写where.
还有where写了后还是出错,找不出什么原因.
你的加了where能用?
2008-08-11 16:53
masterpi
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2007-10-11
收藏
得分:0 
1111
2008-08-25 11:09
tiray
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2008-8-27
收藏
得分:0 
佩服佩服!楼主写得好,淡漠的茶回帖更好!

www.
2008-08-27 11:57
高阁逆风
Rank: 5Rank: 5
等 级:职业侠客
威 望:8
帖 子:508
专家分:321
注 册:2006-4-29
收藏
得分:0 
<div class="notice" style="width: 500px">提示: <em>作者被禁止或删除 内容自动屏蔽</em></div>

      上天安排我做了个多情的人,却又安排我遭遇了无数绝情的人,所以我最终把自己磨练成了一个滥情的人。别人是人见人爱,我是见人爱人.......
2008-08-27 17:03
高阁逆风
Rank: 5Rank: 5
等 级:职业侠客
威 望:8
帖 子:508
专家分:321
注 册:2006-4-29
收藏
得分:0 
"<div class="notice" style="width: 500px">提示: <em>作者被禁止或删除 内容自动屏蔽</em></div>"

      上天安排我做了个多情的人,却又安排我遭遇了无数绝情的人,所以我最终把自己磨练成了一个滥情的人。别人是人见人爱,我是见人爱人.......
2008-08-27 17:03
快速回复:存储过程自定义分页详解
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.029879 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved