如何实现数据库引擎独立分页?

问题描述:

任务:实现适用于不同RDBMS的数据库记录的分页。方法应该适用于主流引擎 - MSSQL2000 +,Oracle,MySql等。如何实现数据库引擎独立分页?

请不要发布RDBMS特定的解决方案,我知道如何为大多数现代数据库引擎实现这一点。我正在寻找通用解决方案。目前只有临时表的解决方案出现在我的脑海中。

编辑:
我正在寻找SQL解决方案,而不是第三方库。

如果SQL规范包含了作为标准的分页,就会有一个通用的解决方案。任何RDBMS语言被称为RDBMS语言的要求也不包括分页支持。

许多数据库产品都支持带标准语言专有扩展的SQL。其中一些支持使用限制条款Rowid with Oracle进行类似MySQL的分页;每个处理不同。其他DBMS将需要添加一个名为rowid或类似的字段。我不认为你可以有一个通用的解决方案(任何人都可以*地在这里证明我是错误的;开放辩论),除非它是内置于数据库系统本身,或除非有公司说ABC使用Oracle,MySQL, SQL Server,他们决定让所有各种数据库系统通过其数据库开发人员提供他们自己的分页实现,为使用它的代码提供通用接口。

亚音速能为你做这个,如果你,如果你能忍受开源... http://subsonicproject.com/querying/webcast-using-paging/

除此之外,我知道NHib确实还有

JPA可以让你与查询类做到这一点:

Query q = ...; 
q.setFirstResult (0); 
q.setMaxResults (10); 

为您提供结果集中的前10个结果。

如果你想要一个DBMS独立的原始SQL解决方案,恐怕你运气不好。所有的供应商都以不同的方式做。

执行分页的最自然有效的方法是使用LIMIT/OFFSET(Sybase世界中的TOP)构造。独立于DB的方式必须知道它正在运行哪个引擎并应用适当的SQL构造。

至少,这是我在数据库独立库的代码中看到的。一旦从具有特定查询的引擎获取数据,就可以抽象出分页逻辑。

如果您确实在寻找单一的一个SQL语句解决方案,您能否展示您的想法?就像临时表解决方案的SQL一样。这可能会让你更相关的建议。

编辑:

我想看看你在想什么,因为我看不到的方式与临时表做到这一点,而不是使用一个引擎特定结构。您在示例中使用了特定的结构。我仍然没有看到只有(实现的)标准SQL在数据库中实现分页的方法。你可以把整个表格放在标准的SQL和应用程序的页面中,但这显然很愚蠢。

所以这个问题现在更像是“是否有一种方法来实现分页而不使用LIMIT/OFFSET或等价的?”我想这个答案是“Sanely,不。”你可以尝试使用游标,但你也会遇到数据库特定的句子/行为。

我刚才想到的一个奇怪的想法就是在表格中添加一个页面列,比如create table test(id int,name varchar,phone varchar,page int),然后就可以获取页面1与select * from table where page = 1。但是这意味着必须添加代码来维护该列,这也只能通过整个数据库或使用特定于数据库的构造来完成。除了必须为每个可能的排序和许多其他缺陷添加不同的列。

我不能提供证据,但我真的认为你不能这样做。

照常进行:
首先按照标准实施。然后处理角落案例,即不执行标准的DBMS。如何处理角落案件取决于您的开发环境。

您正在寻找一种“通用”方法。分页的最普遍方式是使用游标,但基于光标的分页与Web应用程序等非有状态环境不太吻合。

我已经写了有关标准和实现方式(包括光标)位置: http://troels.arvin.dk/db/rdbms/#select-limit-offset

+0

Troels Arvin,非常有用的页面,谢谢! – aku 2008-09-15 07:42:46

@Vinko Vrsalovic,

正如我在写的问题,我知道该怎么做,在大多数数据块。我该如何找到通用的解决方案或获得它不存在的证据。

这是一个基于临时表的愚蠢解决方案。这显然很糟糕,所以不必评论它。

N - upper bound 
M - lower bound 

create #temp (Id int identity, originalId int) 

insert into #temp(originalId) 
select top N KeyColumn from MyTable 
where ... 

select MyTable.* from MyTable 
join #temp t on t.originalId = MyTable.KeyColumn 
where Id between M and M 
order by Id asc 

drop #temp 
+0

这种方法的问题是虽然IDENTITY是标准的SQL,但它不适用于所有数据库。另外,SELECT TOP既不是标准的SQL,也不是广泛的实现。除此之外,与不使用临时表的方法相比,数据的复制操作可能会慢得多。 – 2008-09-15 08:01:03

+0

也许应用视图而不是创建临时表?你可以创建一个视图,其中一列是标识列吗? – 2008-09-15 09:00:52