Вложенный цикл для получения определенной строки не работает - PullRequest
0 голосов
/ 05 сентября 2010

Код ниже не работает. Цикл 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 ]

2 голосов
/ 05 сентября 2010

Попробуйте:

SELECT x.* 
  FROM (SELECT t.*,
               ROWNUM AS rn
          FROM iris t ) x
 WHERE x.rn >= 10
   AND ROWNUM <= 150
1 голос
/ 06 сентября 2010

Я собираюсь угнать ответ 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 распознает этот подход - он не выполняет полное сканирование/ sort на радужной оболочке, но получает первые N соответствующих записей (вы увидите STOPKEY в плане объяснения).

1 голос
/ 06 сентября 2010

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 должно работать. Есть похожая проблема здесь

0 голосов
/ 05 сентября 2010

Попробуйте изменить его на

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

Это может заставить его работать.

Это связано с тем, как оценивается rownum, и я видел похожие проблемы при переносе моей базы данных.от Oracle 9i до 10g.

Взгляд на эту тему может помочь!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...