如何实现数据库引擎独立分页?
任务:实现适用于不同RDBMS的数据库记录的分页。该方法应适用于主流引擎MSSQL2000 +,Oracle,MySql等。
请不要发布RDBMS特定的解决方案,我知道如何为大多数现代数据库引擎实现此功能。我正在寻找通用解决方案。目前,我只想到基于临时表的解决方案。
编辑:
我在寻找SQL解决方案,而不是第三方库。
解决方案
回答
如果我们可以容忍开放源代码,那么SubSonic可以为我们做到这一点。
http://subsonicproject.com/querying/webcast-using-paging/
除此之外,我知道NHib也能做到
回答
JPA允许我们使用Query类来做到这一点:
Query q = ...; q.setFirstResult (0); q.setMaxResults (10);
给我们结果集中的前10个结果。
如果我们想要一个独立于DBMS的原始SQL解决方案,恐怕我们不走运。所有供应商的操作方式都不同。
回答
执行分页的最自然,最有效的方法是使用LIMIT / OFFSET(在Sybase world中为TOP)构造。 DBindependent方式必须知道它在哪个引擎上运行,并应用适当的SQL构造。
至少,这就是我在独立于数据库的库的代码中看到的方式。使用特定查询从引擎获取数据后,就可以抽象出分页逻辑。
如果我们确实正在寻找一个单一的SQL语句解决方案,我们能否展示出想法?像用于临时表解决方案的SQL。那可能会给我们更相关的建议。
编辑:
我想看看我们在想什么,因为我看不到使用临时表执行此操作的方法,并且未使用引擎特定的构造。我们在示例中使用了特定的构造。我仍然没有看到仅使用(已实现的)标准SQL在数据库中实现分页的方法。我们可以将整个表带入标准SQL中,并带入应用程序页面中,但这显然是愚蠢的。
因此,现在的问题将更像是"有没有一种方法可以在不使用LIMIT / OFFSET或者等效值的情况下实现分页?"我猜答案是"理智的,不。"我们可以尝试使用游标,但同时也会成为数据库特定句子/行为的牺牲品。
我刚想到的一个怪诞的想法(是愚蠢的)是将一个表列添加到表中,例如创建表测试(id int,name varchar,phone varchar,page int),然后可以使用select *获得第1页from table where page =1. 但这意味着必须添加代码来维护该列,这只能通过引入整个数据库或者使用特定于数据库的构造来完成。除了必须为每种可能的顺序和许多其他缺陷添加不同的列。
我无法提供证据,但我真的认为我们无法理智地做到这一点。
回答
照常进行:
首先根据标准实施它。然后处理极端情况,即未实施该标准的DBMS。如何处理极端情况取决于开发环境。
我们正在寻找一种"通用"的方法。最通用的分页方式是使用游标,但是基于游标的分页与Web应用程序之类的无状态环境不太匹配。
我在这里写了有关标准和实现(包括游标)的文章:
http://troels.arvin.dk/db/rdbms/#select-limit-offset
回答
@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
回答
如果SQL规范将分页作为标准包含在内,那将是一个通用的解决方案。将任何RDBMS语言称为RDBMS语言的要求也不包括分页支持。
许多数据库产品都通过对标准语言的专有扩展来支持SQL。其中一些支持分页,例如带有limit子句的MySQL,带有Oracle的Rowid。每个人的处理方式都不一样。其他DBMS将需要添加一个称为rowid或者类似名称的字段。
我不认为我们可以有一个通用的解决方案(任何人都可以在这里自由地向我证明我的错误;可以公开辩论),除非它内置于数据库系统本身中,或者除非有公司说ABC使用Oracle,MySQL,SQL Server及其它们决定让所有不同的数据库系统由其数据库开发人员提供自己的分页实现,从而为使用该代码的代码提供通用接口。