升序-降序
这个方法在子查询中使用默认排序,在主查询中使用反向排序,原理是这样的:
declare @temp table(
pk /* pktype */
not null primary
)
insert into @temp select top @pagesize pk from
(
select top(@startrow + @pagesize )
pk,
sortcolumn /* if sorting column is defferent from the pk,sortcolumn must
be fetched as well,otherwise just the pk is necessary
*/
order by sortcolumn
/*
defaultorder–typicallyasc
*/
)
order by sortcolumn
/*
reversed default order–typicallydesc
*/
select from table join @temp temp on table .pk= temp .pk
order by sortcolumn
/*
defaultorder
*/
行计数
这个方法的基本逻辑依赖于sql中的set rowcount表达式,这样可以跳过不必要的行并且获得需要的行记录:
declare @sort /* the type of the sorting column */
set rowcount @startrow
select @sort=sortcolumn from table order by sortcolumn
set rowcount @pagesize
select from table where sortcolumn >= @sort order by sortcolumn
子查询
还有两个方法也是我考虑过的,他们的来源不同。第一个是众所周知的三角查询(triple query)或者说自查询方法,在本文中,我也用一个类似的包含所有其他存储过程的通用逻辑。这里的原理是连接到整个过程中,我对原始代码做了一些缩减,因为recordcount在我的测试中不需要)
select from table where pk in(
select top @pagesize pk from table where pk not in
(
select top @startrow pk from table order by sortcolumn)
order by sortcolumn)
order by sortcolumn
游标
在看google讨论组的时候,我找到了最后一个方法。该方法是用了一个服务器端动态游标。许多人试图避免使用游标,因为游标没有关系可言,以及有序性导致其效率不高,但回过头来看,分页其实是一个有序的任务,无论你使用哪种方法,你都必须回到开始行记录。在之前的方法中,先选择所有在开始记录之前的所有行,加上需要的行记录,然后删除所有之前的行。动态游标有一个fetch relative选项可以完成魔法般的跳转。基本的逻辑如下:
declare @pk /* pktype */
declare @tblpk
table(
pk /*pktype*/ not null primary key
)
declare pagingcursor cursor dynamicread_only for
select @pk from table order by sortcolumn
open pagingcursor
fetch relative @startrow from pagingcursor into @pk
while @pagesize>0 and @@fetch_status =0
begin
insert @tblpk(pk) values(@pk)
fetch next from pagingcursor into @pk
set @pagesize = @pagesize - 1
end
close
pagingcursor
deallocate
pagingcursor
select from table join @tblpk temp on table .pk= temp .pk
order by sortcolumn
复杂查询的通用化
我在之前指出,所有的存储过程都是用动态sql实现通用性的,因此,理论上它们可以用任何种类的复杂查询。下面有一个基于northwind数据库的复杂查询例子。
select customers.contactname as customer, customers.address + ' , ' + customers.city + ', '+ customers.country
as address, sum([orderdetails].unitprice*[ orderdetails ] .quantity)
as [totalmoneyspent]
from customers
inner join orders on customers.customerid = orders.customerid
inner join [ orderdetails ] on orders.orderid = [ orderdetails].orderid
where customers.country <> 'usa' and customers.country <> 'mexico '
group by customers.contactname,customers.address,customers.city, customers.country
having(sum([orderdetails].unitprice * [ orderdetails ] .quantity)) > 1000
order by customer desc ,address desc
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器