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

时间:2008-09-15 00:22:47

标签: database paging

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

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

修改
我正在寻找SQL解决方案,而不是第三方库。

6 个答案:

答案 0 :(得分:5)

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

许多数据库产品都支持带有标准语言专有扩展的SQL。其中一些支持像MySQL这样的分页,带有限制子句,Rowid with Oracle;每个处理方式不同其他DBMS需要添加一个名为rowid的字段或类似的东西。

我不认为你可以有一个通用的解决方案(任何人都可以自由地在这里证明我的错误;开放辩论),除非它内置于数据库系统本身或除非有公司说ABC使用Oracle,MySQL,SQL服务器和他们决定让所有各种数据库系统由他们的数据库开发人员提供他们自己的分页实现,为使用它的代码提供通用接口。

答案 1 :(得分:3)

进行分页的最自然有效的方法是使用LIMIT / OFFSET(Sybase世界中的TOP)构造。 DBindependent方法必须知道它正在运行哪个引擎并应用正确的SQL构造。

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

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

编辑:

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

所以问题现在更像是“有没有办法在不使用LIMIT / OFFSET或等效的情况下实现分页?”我猜答案是“Sanely,不。”你可以尝试使用游标,但你也会成为数据库特定句子/行为的牺牲品。

我刚刚想到的一个wacko(读取愚蠢的)想法是向表中添加一个页面列,比如create table test(id int,name varchar,phone varchar,page int)然后你可以得到第1页使用select * from table where page = 1.但这意味着必须添加代码来维护该列,这也只能通过引入整个数据库或使用特定于数据库的结构来完成。除了必须为每个可能的顺序添加不同的列和许多其他缺陷。

我不能提供证据,但我真的认为你不能做得很清楚。

答案 2 :(得分:1)

像往常一样继续:
首先按照标准实施。然后处理极端情况,即没有实现标准的DBMS。如何处理极端情况取决于您的开发环境。

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

我在这里写过关于标准和实现(包括游标)的文章: http://troels.arvin.dk/db/rdbms/#select-limit-offset

答案 3 :(得分:0)

如果您能够容忍开源,SubSonic可以为您做到这一点...... http://subsonicproject.com/querying/webcast-using-paging/

除此之外,我知道NHib也是如此

答案 4 :(得分:0)

JPA允许您使用Query类:

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

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

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

答案 5 :(得分:0)

@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