7

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

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

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

4

6 回答 6

5

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

许多数据库产品支持对标准语言进行专有扩展的 SQL。其中一些支持分页,例如带有限制子句的 MySQL,带有 Oracle 的 Rowid;每个处理不同。其他 DBMS 将需要添加一个名为 rowid 或类似的字段。

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

于 2008-09-24T10:53:47.080 回答
3

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

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

如果你真的在寻找一个单一的、一个 SQL 语句的解决方案,你能说出你的想法吗?就像临时表解决方案的 SQL 一样。这可能会给你更多相关的建议。

编辑:

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

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

我刚刚想到的一个古怪(读傻)的想法是在表中添加一个页面列,比如创建表测试(id int,name varchar,phone varchar,page int),然后您可以使用 select * 获取第 1 页from table where page = 1。但这意味着必须添加代码来维护该列,而这又只能通过引入整个数据库或使用数据库特定的结构来完成。除了必须为每个可能的排序和许多其他缺陷添加不同的列之外。

我无法提供证据,但我真的认为你不能理智地做到这一点。

于 2008-09-15T06:36:59.887 回答
1

照常进行:
首先按照标准实施。然后处理极端情况,即不执行标准的 DBMS。如何处理极端情况取决于您的开发环境。

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

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

于 2008-09-15T07:05:03.550 回答
0

如果您可以容忍开源,SubSonic 可以为您执行此操作... http://subsonicproject.com/querying/webcast-using-paging/

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

于 2008-09-15T00:26:58.653 回答
0

JPA 允许您使用 Query 类来做到这一点:

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

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

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

于 2008-09-15T00:31:06.350 回答
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
于 2008-09-15T07:49:41.990 回答