AS400 встроенная обработка курсора SQL - PullRequest
0 голосов
/ 07 сентября 2018

Я считаю, что, возможно, обнаружил производственную ошибку, которая вызывает периодические проблемы. По сути, я пытаюсь понять, что делает AS400 при работе со встроенным SQL и курсорами. Я думаю, что курсор в некоторых случаях не закрывается, что приводит к сбою следующего случая, так как курсор все еще открыт.

Вот снимок кода:

begsr checkfile;

exec sql                               
declare T1 cursor for               
select * from FILE1              
where field1 = :var1;             

exec sql                               
open T1;                            

exec sql                               
fetch next from T1 into :vrDS;      

dow SQLCOD = *zeros;            
  if a=b;
    eval found = 'Y';
    leavesr;
  endif;     
enddo;

exec sql
close T1;

endsr;

Мое беспокойство связано с листвой. Если условие выполнено, оно покидает подпрограмму, которая пропускает закрытие курсора T1. В журнале заданий есть информационные сообщения типа «Курсор T1 уже открыт или выделен». Я предполагаю, что это означает, что он ничего не делал или, может быть, даже извлечен из предыдущего курсора? Мне также интересно, выполняется ли каждый раз оператор объявлений или просто пропускает эту часть кода после его первого выполнения. Я думаю, что мне нужно поставить оператор закрытия T1 перед оператором open, но я хотел бы получить второе мнение, поскольку это производственная проблема, которую практически невозможно воссоздать из-за различий в ключах безопасности между тестированием и производством.

Спасибо!

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

То, что сказал Чарльз, а также я считаю, что в некоторых случаях вы можете даже создать бесконечный цикл с этим кодом! Возможно, вы не передаете весь код, но если выборка прошла успешно (SQLCOD = 0) и a <> b, то вы застряли в цикле.

Мне нравится помещать выборку в подпроцедуру, которая возвращает * On, если запись успешно прочитана. Тогда вы можете сделать что-то вроде этого:

dcl-proc MyProc;
  dcl-pi *n;
    ... parameters ...
  end-pi;

  C1_OpenCursor(parameters);
  dow C1_FetchCursor(record);
    ... do something with the record ...
  enddo;
  C1_CloseCursor();
end-proc;

// ------------------------
// SQL Open the cursor
dcl-proc C1_OpenCursor;
  dcl-pi *n;
    ... parameters ...
  end-pi;

  exec sql
    declare C1 cursor for ...

  exec sql
    open C1;
  if SQLCOD < 0;
    .. error processing ...
  endif;
end-proc;

// ------------------------
// SQL Read the cursor
dcl-proc C1_FetchCursor;
  dcl-pi *n Ind;
    ... parameters ...
  end-pi;

  exec sql
    fetch C1 into ...
  if SQLCOD = 100;
    return *Off;
  elseif SQLCOD < 0;
    ... error handling ...
    return *Off;
  endif;

  return *On;
end-proc;

// ------------------------
// SQL Close the cursor
dcl-proc C1_CloseCursor;

  exec sql close C1;
end-proc;

Это позволяет вам хранить весь код вашей базы данных в одном месте и просто вызывать его из вашей программы. Процедуры базы данных просто обращаются к базе данных и каким-то образом сообщают об ошибках. Логика вашей программы может оставаться загроможденной иногда многословной базой данных и кодом обработки ошибок.

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

0 голосов
/ 07 сентября 2018

a DECLARE CURSOR на самом деле является оператором времени компиляции.

Он никогда не выполняется во время выполнения.

:var1 передается в БД, когда OPEN выполняется во время выполнения. Вот ответ с подробным примером Использование курсора для нескольких условий поиска

Да, поскольку код отображается, курсор остается открытым. И, возможно, читать из, а не открывать свежий курсор во время следующего запуска. Зависит от того, что опция CLOSQLCUR во время компиляции (или как установлено с помощью EXEC SQL SET OPTION)

Вы должны проверять SQLSTATE / SQLCODE после OPEN и FETCH

Другой распространенной практикой является выполнение CLOSE перед OPEN, снова обязательно проверьте SQLSTATE / SQLCODE и проигнорируйте CURSOR NOT OPEN при закрытии.

...