Navicy's .NET

天将降大任于斯人也,必先苦其心智,劳其筋骨,饿其体肤,空乏其身......

导航

如何取出表中中间的部分记录?

昨天遇到了一个问题,就是如何取出SQL Server / Access数据表中中间的部分记录,例如要取出第9条到第16条的“最新”文章记录,仔细考虑了一下得到了一种方法,下面的代码示例都以下面的表结构为准:

 

  Articles 表 SQL Server 类型 Oracle 类型
PK Id int (自增) number(9) (插入时在当前最大值上加1)
  Author nvarchar(10) nvarchar2(10)
  Title nvarchar(50) nvarchar2(50)
  PubTime datetime date

这种方法是“拼凑” SQL 语句:用两次 TOP 命令取得我们所要的数据,例如:

 1SELECT * FROM 
 2     ( 
 3     SELECT TOP 8 * FROM 
 4     ( 
 5          SELECT TOP 16 * 
 6          FROM Articles 
 7          ORDER BY PubTime DESC 
 8     ) 
 9     ORDER BY PubTime ASC 
10
11ORDER BY PubTime DESC 

这个的想法就是“掐头去尾”,要取出按时间降序排列的第9到第16条这8条记录,首先先按时间降序取出前16条记录,由于这16条记录的后8条正是我们需要的记录,所以再对这16条记录按时间升序排列,取出前8条,这8条正是我们需要的记录,但是排序不对,最后再对这8条记录按时间降序排列,正好得到需要的记录和排序方式。
其实,取出中间数据的方法还有很多,这和分页的原理差不多,在网上还发现使用存储过程来实现的,这一种方式是以 ASP.NET Forum 为代表的、“临时表”方法:即在存储过程中建立一个临时表,该临时表包含一个序号字段(1,2,3,....)以及表的主键(其他能够唯一确定一行记录的字段也是可以的)字段。存储过程可能如下:

 1CREATE Procedure GetAllArticles_Paged
 2(
 3     @PageIndex int,
 4     @PageSize int,
 5     @TotalRecords out int,
 6     @TotalPages out int
 7)
 8AS
 9
10DECLARE @PageLowerBound int
11DECLARE @PageUpperBound int
12
13-- Set the page bounds
14SET @PageLowerBound = @PageSize * @PageIndex
15SET @PageUpperBound = @PageLowerBound + @PageSize + 1
16
17-- Create a temp table to store the select results
18CREATE TABLE #tmp
19(
20     RecNo int IDENTITY (11NOT NULL,
21     ArticleID int
22)
23
24INSERT INTO #tmp
25     SELECT [ID]
26     FROM Articles
27     ORDER BY PubTime DESC
28
29SELECT A.*
30FROM Articles A (nolock), #tmp T
31WHERE A.ID = T.ArticleID AND
32     T.RecNo > @PageLowerBound AND
33     T.RecNo < @PageUpperBound
34ORDER BY T.RecNo
35
36GO 

对于 Oracle 数据库,有几处不同严重妨碍了上面几个方法的实施,比如,Oracle 不支持 TOP 关键字:不过这个好像并不十分严重,因为它提供了 rownum 这个隐式游标,可以实现与 TOP 类似的功能,如:

SELECT TOP 10  FROM WHERE  

要写成

SELECT  FROM  WHERE  AND rownum <= 10 

rownum 是记录序号(1,2,3...),但有一个比较麻烦的事情是:如果 SQL 语句中有 ORDER BY ... 排序的时候,rownum 居然是先“标号”后排序!这样,这个序号如果不加处理是不合乎使用需求的。

至于临时表,Oracle 的临时表和 SQL Server 的有很大不同,

 1SELECT * FROM 
 2     ( 
 3     SELECT A.*, rownum r 
 4     FROM 
 5          ( 
 6          SELECT * 
 7          FROM Articles 
 8          ORDER BY PubTime DESC 
 9          ) A 
10     WHERE rownum <= PageUpperBound 
11     ) B 
12WHERE r > PageLowerBound; 

posted on 2005-05-09 08:28  Navicy  阅读(1409)  评论(0编辑  收藏  举报