`

SQL分页排序的实现与分页数据重复问题

阅读更多
转自:http://www.linuxidc.com/Linux/2011-02/32593p2.htm

在oracle分页查询中,我们采用类似以下所示的公认的比较高效的数据库分页查询语句(Effective Oracle by Design中有描述、众多oracle使用者也做过测试)。

写道
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A
WHERE ROWNUM <= n)
WHERE RN > m

基于Rownum进行分页,表面上看运行起来似乎也没问题。但经过我们实践检验,其实实际上有时是不安全的,在某些情况下会出错,原因在于它没有排序。在分页情况下,第一页和第二页的数据是来自两次相对独立的SQL,如果没有排序,则SQL第一次和第二次执行时返回的结果是不一致的。
不一致是什么意思?假设有一个无排序的SQL,我们把SQL执行两次:

第一次执行后会返回有1、2、3、4、5共5条记录
第二次执行后还是会返回有1、2、3、4、5共5条记录
大部分情况下,这两次返回结果的顺序是完全一样的。但不幸的是,也许数据库有问题了,也许有人改了数据,反正有时候它会不一样,比如第二次执行时第2条和第4条对调了,返回的是1、4、3、2、5共5条记录,如下:

第一次:1、2、3、4、5
第二次:1、4、3、2、5
假设我们对这个SQL进行分页,每页3条记录,共两页,正常情况下结果是这样的:

拉第一页时,执行第一次SQL,按1、2、3、4、5排序,返回1、2、3三条记录
拉第二页时,执行第一次SQL,按1、2、3、4、5排序,返回4、5两条记录
但如果发生排序混乱的问题,结果会这样:

拉第一页时,执行第一次SQL,按1、2、3、4、5排序,返回1、2、3三条记录
拉第二页时,执行第二次SQL,按1、4、3、2、5排序,返回2、5两条记录
结果我们会发现,分页结果很不正常,2这条记录出现了两次,4则消失了。正常来说,我们不会注意到有数据丢失,但我们会注意到分页的数据有重复。

怎么办呢?那我们就加一个排序吧,排序子句要加在最里层的SQL里,这样分页出来的结果才会是排序后的结果。比如按名称、类别或作者排序的order by子句:

select xxx.*
  from (
            select rownum as recordno
              from (
                         select ID,NAME,ATYPE,CREATEDATE,CREATOR,ASTATUS from TAB001 where ATYPE='SOME_TYPE'
                          order by NAME,ATYPE,CREATOR
                      ) xx
           ) xxx
where recordno >= :开始记录号
    and recordno <= :结束记录号

这样是不是可以了呢?答案还是不行,因为这些字段的值不是唯一的。可考虑一个极端情况,就是这个表里500万条记录的名称、类别和作者都完全一样,会有什么结果呢?结果仍然是无序。

最终解决这个问题的办法,就是一定要用ID主键排序。不管前面有多少个order by字段,最后面一定要加上ID主键:


select xxx.*
  from (
            select rownum as recordno
              from (
                         select ID,NAME,ATYPE,CREATEDATE,CREATOR,ASTATUS from TAB001 where ATYPE='SOME_TYPE'
                          order by NAME,ATYPE,CREATOR,ID
                      ) xx
           ) xxx
where recordno >= :开始记录号
    and recordno <= :结束记录号

由于主键ID是唯一的,所以只要ID不变,按ID排序就能保证每次执行分页SQL都是一致的顺序了。
分享到:
评论

相关推荐

    LINQ To SQL实现分页效果源码

    在本例中,我们关注的是LINQ to SQL,这是一种特定的LINQ实现,它用于与关系数据库进行交互,如SQL Server 2005。在VS2008中,LINQ to SQL提供了直观的方式来映射数据库模式到.NET类,从而简化了数据访问。 分页是...

    SQL分页加载数据demo

    "SQL分页加载数据"是指通过SQL查询来实现数据的分批次、按页展示,以提高性能和用户体验。下面我们将深入探讨SQL分页加载数据的相关知识点。 1. **基本概念**:分页是将数据集分割成若干个固定大小的部分,每个部分...

    经典的分页、排序SQL 通用存储过程.rar

    在MySQL中,一个经典的分页排序存储过程可能如下: ```sql DELIMITER // CREATE PROCEDURE GetPagedSortedData(IN page INT, IN pageSize INT, IN sortColumn VARCHAR(255), IN sortOrder ENUM('ASC', 'DESC')) ...

    sql2005 非常强大的 分页 支持排序

    此存储过程通过动态构建 SQL 语句来实现复杂的数据筛选与排序需求,并返回两个结果集:一是分页后的数据记录,二是总记录数。 #### 存储过程参数详解 - **@tblName** (varchar(255)): 指定查询的目标表名称。 - **...

    C# SQL2005 分页排序存储过程

    本篇将深入探讨如何在C#中调用SQL Server 2005的存储过程来实现分页排序功能。 首先,我们需要理解什么是分页排序。分页是指将大量的数据分成多个小块(页),每次只显示其中一部分,让用户可以逐页浏览,避免一次...

    mysql数据库实现分页

    二、SQL语句实现分页 在MySQL中,最常用的分页查询方式是使用`LIMIT`和`OFFSET`关键字。`LIMIT`用于指定每页显示的记录数,而`OFFSET`用于跳过多少条记录,达到从特定位置开始返回结果的目的。 例如,要获取第2页,...

    mybatis中进行sqlserver分页

    mybatis中,sqlserver分页

    如何解决Oracle分页查询中排序与效率问题

    本文主要解决 Oracle 分页查询中排序与效率问题,通过实践和分析,提供了两种解决方案,并对比了两种方法的优缺点。 知识点 1: Oracle 分页查询的基本概念 Oracle 分页查询是指在查询结果中,通过限制行数来实现...

    SQL分页读取海量数据存储过程

    本文将深入探讨如何通过存储过程实现SQL分页读取海量数据。 首先,理解“分页”概念是至关重要的。分页是指将大量结果集分成多个小部分(页),每次只显示一页,用户可以逐页浏览。这在Web应用中非常常见,如搜索...

    Oracle的SQL分页实践

    在Oracle数据库中,SQL分页是一种非常常见的查询技术,它允许我们从大量数据中按需获取一部分结果,而不是一次性加载所有记录。这对于提高用户体验和优化系统性能至关重要,尤其是在处理大数据量的Web应用中。本实践...

    数据库分页SQL语句实现

    ### 数据库分页SQL语句实现 在开发MIS系统或Web应用系统时,经常会遇到对数据库进行分页处理的需求。这是因为数据量庞大时,一次性加载所有数据会给系统带来很大的负担,同时也会影响用户体验。因此,分页技术成为...

    关于SQL 数据分页

    在SQL中,数据分页是一种常见的技术,用于在大量数据中分批次地显示结果,以提高用户界面的可读性和性能。在这个例子中,作者针对一个包含20万条记录和69个字段的`TORDER`表,设计了一种分页方法,主要基于`...

    千万级数据分页查询存储过程SQLServer

    本文将深入探讨如何利用SQL Server的存储过程实现高效的大数据分页查询。 首先,理解分页查询的基本概念。分页查询是指从海量数据中按指定的页码和每页大小获取数据,通常用于网页展示或报表生成。在SQL Server中,...

    sql分页 sqlserver中存储过程分页

    - **子查询与嵌套查询**:使用了子查询和嵌套查询来实现分页功能,确保了数据的准确性。 #### 总结 通过上述分析可以看出,这个存储过程通过动态生成 SQL 语句的方式实现了较为灵活且高效的分页查询。这种实现方式...

    SQL简单分页教程~~~详细

    SQL分页是一种在数据库中实现数据检索时,限制返回结果集大小的方法,使得用户可以逐页浏览大量数据。本教程将详细介绍一个简单的SQL分页实现,适合初学者理解。 ### 基本原理 SQL分页的核心是通过`ROW_NUMBER()`...

    海量数据分页sql server经典

    ### 海量数据分页在SQL Server中的实现与优化 #### 概述 在Web应用程序开发中,分页浏览是一项非常重要的功能。特别是在处理大量数据时,如何高效地实现分页变得尤为关键。传统的ADO记录集分页法因其内存占用高、...

Global site tag (gtag.js) - Google Analytics