重写查询以进行分页

Posted

技术标签:

【中文标题】重写查询以进行分页【英文标题】:rewrite a query to have pagination 【发布时间】:2017-03-03 05:10:03 【问题描述】:

我有一个程序,其中用户提供了一个可以在数据库上执行的 sql 查询(要运行的数据库的详细信息也由用户提供)。此查询在数据库上执行,稍后处理结果。

一项新功能要求以分页方式执行查询,即如果用户的查询将正常返回 20 条记录,并且用户提供的页面大小为 5,则查询应执行 4 次,每次检索 5 条记录时间。

我可以为没有 CTE 的选择查询执行此操作,但我不确定如何处理包含 CTE 的一般查询。

我将 CTE 的查询修改如下:

public static String rewrite(String sql) 
    return "select * from ("
            + "select (row_number() over ()) as generated_row_number, t.* "
            + "from ("
            + sql
            + ") as t"
            + ") "
            + "where generated_row_number < ?"
            + " and generated_row_number >= ?"; 

起始索引和页面大小稍后作为参数添加。

我将如何处理包含 CTE 的查询的类似功能?

可以假设数据库是 DB2,但最好使用通用解决方案。

连接到数据库的用户也没有创建视图的权限。

【问题讨论】:

使用偏移量怎么样? "order by 1 offset 10((page number - 1) * pagesize) ROWS fetch NEXT 5(your page size) ROWS ONLY" 【参考方案1】:

在 SQL 中查询的一种方便方法是使用偏移提取。我经常用它来分页。

Select StockCode,Description,Quantity from Inventory order by StockCode offset 0 ROWS fetch NEXT 5 ROWS ONLY

所以在代码中它会是这样的

public static string(int Page, int PerPage)

    return "Select StockCode,Description,Quantity from Inventory order by StockCode offset " + ((Page - 1) * PerPage).ToString() + " ROWS fetch NEXT " + PerPage.ToString() + " ROWS ONLY"

如果您需要更通用的解决方案,您可以尝试嵌套选择:

public static String rewrite(String sql, int Page, int PerPage)

    return "Select * from (" + sql + ") order by 1 offset " + ((Page - 1) * PerPage).ToString() + " ROWS fetch NEXT " + PerPage.ToString() + " ROWS ONLY"

【讨论】:

我得到以下错误,使用这个:select * from test offset 20 rows fetch next 20 rows onlyAn unexpected token "from test" was found following "select * ". Expected tokens may include: "&lt;space&gt;".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.13.127 你需要有“order by” 还是不行:select * from test order by 1 offset 20 rows fetch next 20 rows only An unexpected token "offset 20 rows fetch next 20 rows only" was found following "m test order by 1 ". Expected tokens may include: "&lt;space&gt;".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.13.127 你运行的是什么版本的sql? 在本例中,服务器是 DB2 express c 10.5。【参考方案2】:

试试这个:

public static String rewrite(String sql) 

    return   "with tmptable as (" + sql + ")"
            + " select * from ("
            + " select row_number() over () as generated_row_number, t.* "
            + " from tmptable t
            + ") tmp"
            + " where tmp.generated_row_number < ?"
            + " and tmp.generated_row_number >= ?"; 

【讨论】:

如果原始查询还包含 WITH 子句,这将不起作用,这是我遇到的问题。它也不适用于一些简单的选择,失败并出现错误 -153

以上是关于重写查询以进行分页的主要内容,如果未能解决你的问题,请参考以下文章

以多页分页打印所有数据

dede织梦文章页分页导航副标题如何删除标题后面带的#号

JavaEE-05 分页与文件上传

react-slick 自定义分页分页道具使用

单页分页问题中的多个角度材料表

梦内容页分页标题提取