对快速变化的数据库内容进行分页

Lor*_*ori 7 sql database sql-server pagination

我需要使用分页读取 MS SQL 数据库表的内容,即获取第一页的 N 行,然后获取第二页的 N 行,依此类推。

如果数据库的内容在分页期间发生显着变化,则可以使用简单的分页查询,例如:

SELECT *
FROM (SELECT a.*,
    ROW_NUMBER() OVER (ORDER BY id) AS rnum
    FROM articles a)
WHERE rnum <= 10
AND   rnum >= 6;
Run Code Online (Sandbox Code Playgroud)

可能无法可靠工作。插入的行可以被跳过或可能导致后续行重复,而删除的行可能导致后续行被跳过。

我可以通过执行以下任一操作来避免此类问题:

  1. 在整个分页期间锁定行以防止更新 -限制太多
  2. 在分页之前将行复制到临时表 -太慢
  3. 通过行号和上一页末尾显示的排序值的组合进行选择,根据更改的表在适当的位置恢复,但仍然只获取接下来的 N 行

我有点喜欢第三种解决方案,但我发现当排序列中存在重复值时很难实现。

例如,假设我有一个按评级降序排序的文章列表。如果评分相同,则按ID升序排序(ID唯一):

ID      RATING
9       34
3       32
6       32
8       32
12      32
1       25
2       23
Run Code Online (Sandbox Code Playgroud)

现在,我想要包含 3 篇文章的页面,这意味着第一页将包含文章 9、3 和 6。这是通过查询排序列表中的前 3 篇文章来完成的。

现在,我想从第 8 篇文章中恢复接下来的 3 篇文章,并使用文章 ID 作为恢复位置的标记。

如果我告诉数据库采用第 8 篇文章的信誉,而不是采用信誉度低于此的 3 篇文章,我会跳过第 12 篇文章。

如果我告诉数据库取第 8 条的声誉,而不是取声誉低于或等于该声誉的 3 篇文章,我会重复第 3 条和第 6 条。

我可以使用什么 SQL 查询(或查询组合)来恢复第 8 篇文章的分页,并使用文章 ID 作为从何处恢复的标记?

Aar*_*and 4

将评论转换为答案,因为它似乎已经解决了用户的问题。

因此,您似乎应该缓存该用户的结果(例如,您可以将所有 ID 发送到应用程序,并让它在每次获取时一次只提取 3 篇文章),但还要添加一个免责声明,如果需要半个小时,小时滚动浏览列表,列表可能不再准确。