如何以通用方式实现 SQL 标准的分页机制?

How to implement paging mechanism in generic way for SQL standards?

在一个项目中,我们已经成功实现了SQL服务器的分页机制,但根据我们的要求,我们正在尝试以通用方式实现Oracle,SQL服务器的分页机制、DB2 和 DB400 数据库。是否可以通过这种方式实现分页?实现此类查询的最简单通用方法是什么?

我的理解。试试这个:

WITH MyCte AS 
(
    SELECT row_number() OVER (ORDER BY FieldName) ID, *  FROM TableName
)
SELECT  *
FROM    MyCte
WHERE   ID BETWEEN 1 AND 10

据我所知,没有通用的功能来实现所有数据库的分页机制。

实现分页的语法也可能随着数据库的不同而改变,所以很难说有一个通用的功能可以在所有数据库中实现它。

你可以参考There are a method to paging using ANSI Sql only? where the accepted answer refers to a link,里面说可以这样使用

SELECT * FROM (
  SELECT
    ROW_NUMBER() OVER (ORDER BY key ASC) AS rownum,
    columns
  FROM tablename
) AS foo
WHERE rownum > skip AND rownum <= (n+skip)

在Oracle中,有多种方式:

  • ROWNUM 在子查询中和 ORDER BY 在外部查询
  • 解析ROW_NUMBER()
  • 新 Oracle 12c
  • 中的 TOP-n 行限制子句

使用 ROWNUM:

SQL> WITH DATA AS(
  2  SELECT level col
  3  FROM   dual
  4  CONNECT BY LEVEL <= 10
  5  )
  6  SELECT col
  7  FROM   (SELECT col, rownum AS rnum
  8          FROM   (SELECT col
  9                  FROM   data
 10                  ORDER BY col)
 11          WHERE rownum <= 8)
 12  WHERE  rnum >= 5;

       COL
----------
         5
         6
         7
         8

使用解析 ROW_NUMBER():

SQL> WITH DATA AS(
  2  SELECT level col
  3  FROM   dual
  4  CONNECT BY LEVEL <= 10
  5  )
  6  SELECT * FROM (
  7    SELECT
  8      ROW_NUMBER() OVER (ORDER BY col) rn
  9    FROM DATA
 10  )
 11  WHERE rn >= 5 AND rn <= 8;

        RN
----------
         5
         6
         7
         8

使用前n行限制子句:

SQL> WITH DATA AS(
  2  SELECT level col
  3  FROM   dual
  4  CONNECT BY LEVEL <= 10
  5  )
  6  SELECT col
  7  FROM   DATA
  8  ORDER BY col
  9  OFFSET 4 ROWS FETCH NEXT 4 ROWS ONLY;

       COL
----------
         5
         6
         7
         8