2010-09-05 82 views
0

下面的代码不起作用。 while循环不显示任何值。如果我将其更改为0 and 150,它工作正常。请帮我在这里。除之外的任何值都不会检索任何值。使用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)); 
} 
+0

“WITH”子句只是语法糖 - 使用WITH的查询与不使用WITH的查询没有区别。 – 2010-09-05 18:50:57

回答

0

尝试将其更改为

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

这可能使它工作。

它与rownum如何评估以及我在从Oracle 9i迁移数据库到10g时看到过类似的问题。

看看这个topic可能会有所帮助!

+0

它不再工作。我试图阅读你共享的链接,但没有解决这个问题。 – user414977 2010-09-05 18:37:49

+0

你可以分享查询计划吗?另外,你在什么数据库+版本? – InSane 2010-09-05 18:39:40

+0

数据库版本11g – user414977 2010-09-05 18:43:24

2

尝试:

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

我试图得到“java.sql.SQLSyntaxErrorException:ORA-00923:FROM关键字找不到预期的地方” – user414977 2010-09-05 21:39:29

+0

@ user414977:你是否按原样运行查询?因为我没有看到什么会触发你得到的错误。不过我更新了一直使用表别名。 – 2010-09-05 22:01:35

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小马解决方案应该可以工作。还有一个类似的问题here

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转换为内部选择BEFORE中的列,并在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)。