用于检索特定行的嵌套循环不起作用

时间:2010-09-05 18:21:12

标签: java sql database oracle

以下代码不起作用。 while循环不显示任何值。如果我将其更改为0 and 150,它可以正常工作。除 0 之外的任何内容都不会检索任何值。我正在使用Oracle数据库。我尝试使用ORDER BY,但它仍无效。

ResultSet rset1 = stmt.executeQuery
    (" SELECT * FROM (SELECT * FROM iris ) WHERE rownum BETWEEN 10 and 150");
while(rset1.next())
{
    System.out.println(rset1.getString(1));
}
/////////////////////////////////////////////
java.util.Properties props = new java.util.Properties();
props.setProperty("user", "system");
props.setProperty("password", "weblogic");

DriverManager.registerDriver(new OracleDriver());
Connection conn = DriverManager.getConnection(url, props);

Statement stmt = conn.createStatement();

ResultSet rset1 = stmt.executeQuery(" WITH q AS  (SELECT * FROM iris ) 
                                      SELECT * 
                                        FROM q 
                                       WHERE ROWNUM BETWEEN 10 and 150");

while(rset1.next())
{
   System.out.println(rset1.getString(1));
}

4 个答案:

答案 0 :(得分:2)

尝试:

SELECT x.* 
  FROM (SELECT t.*,
               ROWNUM AS rn
          FROM iris t ) x
 WHERE x.rn >= 10
   AND ROWNUM <= 150

答案 1 :(得分:1)

ROWNUM有点奇怪。结果集中的第一行的ROWNUM为1.但是如果在WHERE子句中使用它,则会过滤掉结果集中的行。

说我从

开始
select rownum, table_name from all_tables where rownum in (1,2,3);

         ROWNUM TABLE_NAME
--------------- -----------
           1.00 CON$
           2.00 UNDO$
           3.00 CDEF$

然后我改为

select rownum, table_name from all_tables where rownum in (1,3);

         ROWNUM TABLE_NAME
--------------- -----------
           1.00 CON$

我只得到CON $。除非我有第二排,否则我不能排第三排。通过说我从不想要第2行,我从来没有看到第3行,因为我排除了每一个潜在的行。

 select rownum, table_name from all_tables 
 where rownum in (1,3) or table_name = 'CDEF$';

         ROWNUM TABLE_NAME
--------------- -----------
           1.00 CON$
           2.00 CDEF$
           3.00 CCOL$

现在变得有趣。 CON $符合ROWNUM 1,UNDO $被排除在外,因为它不是rownum 1或3,或者名称为'CDEF $'。但CDEF $符合资格并获得ROWNUM 2,这意味着现在可以包括第三行。

OMG Ponies解决方案应该有效。类似的问题here

答案 2 :(得分:1)

我要劫持OMG的答案,以便清楚地解释问题和解决方案。

您的原始查询是

WITH q AS  (SELECT * FROM iris ) 
SELECT * 
FROM q 
WHERE ROWNUM BETWEEN 10 and 150

无论如何,正如OMG所说,这是(好的)语法糖:

SELECT * 
FROM (SELECT * FROM iris )
WHERE ROWNUM BETWEEN 10 and 150

问题很简单。 ROWNUM是一个虚拟列,适用于仅在ROWNUM发生的级别的结果集

简而言之,这个SQL与:

相同
SELECT * FROM iris WHERE ROWNUM BETWEEN 10 and 150

在第一次测试失败时不返回任何行(每个可能的rownum 1都无法通过WHERE子句测试,因此从不存在ROWNUM 1,更不用说ROWNUM 10)。这不是很直观,但这就是它的工作原理。

对此的解决方案(由OMG提供)是将ROWNUM转换为内部选择中的列,然后在ROWNUM上执行过滤。我已经向SQL添加了一个订单,因为这很典型。

SELECT x.* 
FROM (SELECT t.*,
           ROWNUM AS rn
      FROM iris t
      ORDER BY something_on_iris ) x
WHERE x.rn >= 10
AND x.rn <= 150

我怀疑这是你尝试使用WITH子句做的事情? 重要的一点是将ROWNUM转换为“内部选择”中的rn - 位于以下的过滤器。

注意:Oracle会识别这种方法 - 它不会对虹膜进行全面扫描/排序,但会获得前N个匹配记录(您将在解释计划中看到STOPKEY)。

答案 3 :(得分:0)

尝试将其更改为

WITH q AS  (SELECT * , rownum myrownumber FROM iris ) 
SELECT * FROM   q
WHERE myrownumber BETWEEN 10 and 150

这可能会有效。

它与如何评估rownum有关,我在将数据库从Oracle 9i迁移到10g时遇到了类似的问题。

查看此topic可能有所帮助!