Курсор SQLRPGLE правильно возвращается при сортировке по порядку AS C, но ничего не возвращает при заказе по порядку DES C. Почему? - PullRequest
1 голос
/ 12 апреля 2020

Я пишу код в IBM RDI и запускаю программу на эмуляторе 5250. Я пишу простое чтение программы из одной таблицы SQL и вывод результатов в файл принтера. Код работает в основном как ожидалось, но я столкнулся с чем-то странным. Когда я пытаюсь отсортировать свой оператор выбора курсора по порядку des c, он возвращается пустым, но когда я не упорядочиваю по или когда я упорядочиваю по AS C, он работает нормально. Я не понимаю, что происходит. Я действительно хотел бы объяснения.

Код ниже.


       DCL-F BOOKRPT2 PRINTER OFLIND(*IN01);

       DCL-S INDGENRE BINDEC(4:0);
       DCL-S CATEGORY CHAR(30);
       DCL-S TOTALRECORDS PACKED(5:0);
       DCL-S TOTALCOST ZONED(5:2);
       DCL-S EOF   IND;
       DCL-S DUMMY ZONED(1);

       DCL-DS BOOKRECORD;
         BOOK CHAR(50);
         DURATION TIME(*ISO);
         AUTHOR CHAR(30);
         BOOKID ZONED(7:0);
         PRICE PACKED(5:2);
         GENRE CHAR(20);
       END-DS;
       //DCL-DS AUDIBLEBKS EXT END-DS;
        //**************************************************************************
        //*                        ***   M A I N   R O U T I N E   ***
        //**************************************************************************
        EXSR PREPFILES;
        EXSR GETSYS;
        WRITE TITLE;
        WRITE COLHDG;
        EXSR GETROW;
        WRITE GENREREC;
        CATEGORY = GENRE;
        DOW NOT EOF;

        IF *IN01 = *ON;
           WRITE TITLE;
           WRITE COLHDG;

          *IN01 = *OFF;
        ENDIF;
          IF CATEGORY = GENRE;
            WRITE DETAIL;
            TOTALRECORDS +=1;
            TOTALCOST += PRICE;
         ELSE;

           WRITE TOTALS;
           CATEGORY = GENRE;
           WRITE GENREREC;
           TOTALRECORDS = 0;
           TOTALCOST = 0;
          ENDIF;
           TOTALBOOKS = TOTALRECORDS;
           TOTALPRICE = TOTALCOST;
        EXSR GETROW;
        ENDDO;
        WRITE TOTALS;
        EXSR WRAPUP;
        *INLR = *ON;
        RETURN;

       BEGSR PREPFILES;
         EXEC SQL
         DECLARE BOOKCURSOR  CURSOR
           FOR
            SELECT BOOK, DURATION, AUTHOR, BOOKID, PRICE, GENRE
            FROM BCI433LIB/AUDIBLEBKS
             ORDER BY GENRE DESC;
         //FOR READ ONLY;
           EXEC SQL
             OPEN  BOOKCURSOR;
                 IF SQLCODE <> 0 OR SQLWN0='W';
                   EOF = *ON;
                 ENDIF;
       ENDSR;

        BEGSR GETROW;
          EXEC SQL
            FETCH NEXT
              FROM BOOKCURSOR
              INTO :BOOKRECORD;
           IF SQLCODE <> 0 OR SQLWN0 = 'W';
              EOF = *ON;
            ENDIF;
        ENDSR;

        BEGSR WRAPUP;
           EXEC SQL
               CLOSE BOOKCURSOR;

             IF SQLCODE <> 0  OR SQLWN0 ='W';
               EOF = *ON;
             ENDIF;
        ENDSR;

        BEGSR GETSYS;
         EXEC SQL
         SELECT CURRENT SERVER, CURRENT DATE
           INTO :SYSTEMNAME, :REPORTDATE
         from SYSIBM/SYSDummy1;
        ENDSR; 

No Order By

with DESC order By

Ответы [ 3 ]

1 голос
/ 14 апреля 2020

Помимо проблем с форматированием кода, наиболее вероятный ответ, который я вижу, состоит в том, что у вас есть проблема с последней записью в запросе, когда вы сортируете по ASC, но это первая запись, когда вы сортируете по DESC. Как уже говорилось в других ответах, это легко проверить, посмотрев на SQLSTATE. Самый быстрый способ сделать это - просто запустить его в отладчике RDi или через STRDBG.

1 голос
/ 14 апреля 2020

Как уже говорили другие, вы должны проверить SQL State, но я игнорирую предупреждения. Есть большая вероятность, что последняя строка в вашем курсоре вызывает предупреждение, а не ошибку. Таким образом, STR SQL будет показывать записи, но, так как вы вспыхиваете предупреждение (но не указываете, что это может быть), вы ничего не получаете.

Вот код проверки ошибок, который я поставил после фактически каждое SQL утверждение в моих программах.

exec sql
  ...
if %subst(sqlstate: 1: 2) < '00' or %subst(sqlstate: 1: 2) > '02';
  exec sql get diagnostics condition 1
    :message = message_test;
  SendSqlMsg(message);
endif;

Некоторое объяснение здесь - это сообщение varchar (6000), а SendSqlMsg () - это подпрограмма, которую я написал для отправки сообщения escape.

Дополнительная информация о классах SQLSTATE (первые 2 символа SQLSTATE):

  • 00 - нормальное завершение
  • 01 - предупреждения
  • 02 - нет данных

Все остальное - ошибка.

Еще одно замечание. Я сказал, что ставлю это практически после каждого оператора SQL, но я не проверяю его после закрытия курсора. Вот причина этого. Единственное состояние, которое выбрасывает CLOSE, это «курсор уже закрыт». Мне все равно, если закрыть курсор по этой причине не удалось, так как я хочу, чтобы курсор был закрыт, и он закрылся, нет проблем.

0 голосов
/ 13 апреля 2020

IMO, ваша программа всегда должна проверять SQLSTATE и иметь код для обработки аномальных значений SQLSTATE. Это может быть запись в журнал заданий, отправка оповещения по электронной почте и т. Д. c.

If SQLSTATE <> '00000'; // sucess
  // handle abnormal condition
Endif;

Если вы не можете / не хотите изменить код, используйте RDi для отладки кода и проверки SQLSTATE. после каждой операции.

...