Какой правильный способ проверить состояние SQL найден в ILE RPG?

При работе со встроенным SQL в RPG вы часто получаете курсор и dowцикл для обработки всех строк в вашем результате. Условие в цикле как-то зависит от SQLCOD и / или SQLSTTкакие глобально доступные переменные в SQLRPGLE-программе?

Но как правильно проверить эти значения? Некоторые предлагают SQLCOD = 0 другие not (SQLCOD = +100 or SQLSTT = '02000'), Один не на всех предупреждениях, другой не на некоторых ошибках, так что я не доволен.

Чтобы проиллюстрировать, что я делаю с некоторым кодом:

Pmain             B
D                 PI
Dmy_ds          E DS                  extname(SOME_TABLE)
D                                     qualified
 /free
  exec sql
    DECLARE cur CURSOR FOR
      SELECT *
      FROM some_table;
  exec sql 
    OPEN cur;
  exec sql
    FETCH cur
     INTO :my_ds;
  dow sql_found();
      exec sql
        FETCH cur
         INTO :my_ds;
  enddo;
  exec sql
    CLOSE cur;
 /end-free
Pmain             E


Psql_found        B
D                 PI              N
 /free
  // insert return statement here...
 /end-free
Psql_found        E

Здесь я ищу правильный оператор возврата, который заставит меня пройти по всем строкам, если не возникнет ошибка, и позволит мне уйти, когда возникнет ошибка. Бонусные баллы за какой-то достойный способ проверки на ошибки.

3 ответа

Решение

SQLSTATE лучше и рекомендуется IBM.

Справочник IBM по сообщениям и кодам SQL InfoCenter : концепции SQLCODE и SQLSTATE

SQLSTATE является предпочтительным стандартным кодом возврата.

SQLSTATE состоит из 5 символов, причем первые два байта идентифицируют класс условий.

  • '00' = Безусловное успешное завершение
  • '01' = Предупреждение
  • '02' = нет данных

Все остальное является ошибкой. Я обычно проверяю только на "00".

Просто. Легко. Более портативный.

Использование SQLCODE часто включает списки кодов, которые, IMHO, менее удобны для разработчиков.

Пример:

Лично я обычно включаю определения и код вроде этого:

 D xSQLState@      s               *   inz( %addr(SQLState) )
 D xSQLState       ds             5    based(xSQLState@)
 D  xSQLState2                    2a
 D   
 D Success_On_SQL  C                   const('00')
 D Warning_On_SQL  C                   const('01')
 D NoData_On_SQL   C                   const('02')

Затем после любой операции SQL я вообще проверяю

   if xSQLState2 <> Success_On_Sql;
     someflag = true;
   endif;

Рекомендуется обрабатывать ожидаемые SQLCODE (как часть ожидаемой обработки) и добавлять код исключения для обработки тех, которые вы не делаете. Одна реализация:

  dow 1=1;  // forever
      exec sql
        FETCH cur
         INTO :my_ds;
  // normal exit         
  if sqlstt = SQL_NODATA;
    SFLEND = *on;        
    leave;               
  endif;                 

  // can't CAST a value
  if sqlstt = SQL_CAST;         // CAST error                               
    ... tell user there's an error and read another
    iter;                                                                  
  endif;                                                                   

  // decimal data error
  if sqlstt = SQL_DDE;
    tell user to call IT and stop reading
    leave;                                      
  endif;                                        


  // whoops! not expected at all.  Dump for post-mortem
  if sqlstt <> SQL_NORMAL;                             
    ... tell user to call IT and stop reading
    dump(a);                             
    leave;                                              
  endif;                                               

  // test for end of loop
  // filled subfile page?
  enddo;  // forever

При таком типе реализации вы должны намеренно выйти из цикла; заполнили ли вы страницу подфайла, загрузили самый высокий элемент в массиве или обнаружили ошибку. Я не уверен, что есть одна, общая реализация, которая будет обрабатывать все обстоятельства. Иногда вам может потребоваться выйти из цикла чтения, если у вас есть блокировка записи, а иногда вы хотите отправить сообщение и повторить попытку (например).

Я сделал еще несколько поисков по этой теме и нашел что-то на сайте IBM (цитата):

The SQLCODE is also set by the database manager after each SQL 
statement is executed as follows: 
  - If SQLCODE = 0 and SQLWARN0 is blank, execution was successful.
  - If SQLCODE = 100, no data was found. For example, a FETCH 
    statement returned no data, because the cursor was positioned 
    after the last row of the result table.
  - If SQLCODE > 0 and not = 100, execution was successful with a 
    warning.
  - If SQLCODE = 0 and SQLWARN0 = 'W', execution was successful 
    with a warning.
  - If SQLCODE < 0, execution was not successful.

Что привело бы меня к sql_found() как это:

Pfound_sql        B
D                 PI              N
 /free
  return (SQLCOD >= 0) and (SQLCOD<>100);
 /end-free
Pfound_sql        E

Это должно позаботиться о состоянии "Конец данных" и завершиться ошибкой при всех ошибках. Я не уверен, есть ли какие-то предупреждения, о которых я должен позаботиться (не хочу зацикливаться на бесконечном цикле, если есть предупреждение, которое приводит к тому, что он не читается).

Другие вопросы по тегам