Java / DB2 FETCH FIRST:n带有自定义参数的ROWS

时间:2014-01-09 18:30:43

标签: java sql db2 fetch spring-jdbc

所以这就是我们正在研究的内容,我希望能够将一个参数传递给我的fetch子句,以便我可以使用自定义FETCH量进行查询。

从我在其他SO中读到的内容,遗憾的是,这不能通过DB2数据库获得。但是,我看到的答案并不是很好,所以我问的是我的具体情况。

我尝试过的其他选项:

  • 连接我的String语句以创建我的自定义查询。
  • 使用WHERE col_1 BETWEEN value1 AND value2
  • ,而不是使用FETCH
  • 如@bhamby评论,您还可以使用>替换BETWEEN stmt。和<在WHERE子句中

为您提供我正在寻找的基本示例(我正在使用带有命名参数的Spring JDBC btw)

private static final String SQL_FETCH_NEXT = ""
    + "SELECT * " 
    + "FROM ( SELECT "
    + "     (ROW_NUMBER() OVER(ORDER BY ID, AGE)) AS RUNNING_NO, ID, NAME, AGE "
    + "         FROM DATABASE1.TABLE1 PERSON "
    + "     ) AS TABLE_ONE "
    + "WHERE TABLE_ONE.RUNNING_NO > :rowNumber "
    + "ORDER BY TABLE_ONE.RUNNING_NO "
    + "FETCH FIRST :fetchCount ROWS ONLY ";

因此,根据我上面的查询(由于:fetchCount而无法工作)如何获得FETCH数量的自定义参数(或下降替代)?

2 个答案:

答案 0 :(得分:3)

由于您已经在使用ROW_NUMBER(),因此您已经拥有了所需的所有部分。你为什么不试试这个:

SELECT *
FROM (
    SELECT
         ROW_NUMBER() OVER(ORDER BY ID, AGE) AS RUNNING_NO
        ,ID
        ,NAME
        ,AGE
    FROM DATABASE1.TABLE1 PERSON
) AS TABLE_ONE
WHERE TABLE_ONE.RUNNING_NO  > :rowNumber
  AND TABLE_ONE.RUNNING_NO <= :rowNumber + :fetchCount
ORDER BY TABLE_ONE.RUNNING_NO

答案 1 :(得分:2)

Row_Number()函数是最好的选项之一,但使用它时不需要FETCH FIRST N ROWS语法,因为你已经在做大部分工作来生成row_number(),所以你可以使用它来使用row_number值过滤到您想要的行。

除了该选项之外,我认为您已经尝试过的第一个选项是最佳选择(将数字连接到查询字符串中)。假设您有正确的索引。 (没有索引,row_number选项总是更好)。

所以,如果你能在桌子上得到正确的索引:

由于您使用的是Java,您仍然可以通过在查询中将一个整数附加到“仅获取前N行”中来避免SQL注入并动态构建查询。

该策略的一个缺点是动态语句缓存必须缓存每页代码的一个版本,并且您将有额外的DAO代码旋转到正确的起始点(页面 - 每页1个项目) )。

只要您使用数字数据类型,就不应该进行SQL注入:

private static final String SQL_FETCH_NEXT = ""
    + " SELECT ID, NAME, AGE "
    + " FROM DATABASE1.TABLE1 PERSON "
    + " ORDER BY ID, AGE ";

private static Object runQuery(int pageNum, String filterText) {

//boilerplate code skipped

String sql = SQL_FETCH_NEXT + " fetch first " + pageNum * VALUES_PER_PAGE + " rows only ";

//the rest of the method

}

在这种情况下,FETCH FIRST N ROWS语法将得到保证,原因如下:排序避免,并避免结果的实现。排序可能是原始查询的最大成本,使用ROW_NUMBER将强制您实现整个结果集以排序和分配行号。避免排序需要ID和AGE的索引(与您的order by语句的顺序相同)。或者如果你有过滤器,你必须首先在索引上,然后是你的订购列。

这将起作用的原因是数据库引擎将使用索引以请求的顺序返回数据,并且它不必进行排序。

这种策略的缺点是,当你越过第一页时,你会带回额外的数据(因为你得到的是pageNumber * itemsPerPage行)。因此,要确定最佳行动方案,您必须评估让您的用户页面超过前两页或三页是否常见。

即便如此,很难说你撤回的额外数据量是多少。您必须运行一些测试来检查哪个查询更快:具有排序(ROW_NUMBER)或退回(pageNumber-1)* itemsPerPage的行太多。

我应该注意:你也可以避免ROW_NUMBER策略中的排序。因此,实现是主要关注点。

我猜想,如果表中包含大量数据,最好避免实现(因为您对结果集中的所有数据进行操作以在查询中对其进行排序和实现)。使用少量数据,最好进行排序,而不是通过网络撤回额外的行。

但是,如果您的用户几乎没有页面,那么排序规避选项是最好的,原因很明显。

因此,在两种策略之间,它归结为两种权衡:

  1. 在将数据限制为子集之前,在数据库引擎中实现结果集以指定行号。但只是将你想要的东西拉回到Java中。
  2. 第一页的性能最快,但是在整个网络中拉回(pageNumber-1)* itemsPerPage的数据超过了后续页面所需的子集所需的数据。(以及java中的一些旋转)。