AS400嵌入式SQL游标处理

时间:2018-09-07 14:19:07

标签: sql ibm-midrange

我相信我可能已经发现了生产错误,该错误会导致间歇性问题。基本上,我试图了解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;

我的担忧是在leafr线上。如果满足条件,它将离开子例程,该子例程将跳过光标T1的关闭。在作业日志中,有信息性消息,例如“光标T1已打开或已分配”。我认为这意味着它什么也没做,甚至没有从上一个游标中获取?我也想知道是否每次都执行一次define语句,或者它在第一次执行后是否跳过了那部分代码。我认为我需要在开放式声明前加一个封闭的T1声明,但我想得到第二个意见,因为由于测试与生产之间的安全密钥差异,几乎不可能重新创建生产问题。

谢谢!

2 个答案:

答案 0 :(得分:1)

DECLARE CURSOR实际上是一个编译时语句。

它永远不会在运行时执行。

在运行时完成:var1时,

OPEN被传递到数据库。这是一个带有详细示例Using cursor for multiple search conditions

的答案

是的,如代码所示,光标将保持打开状态。并可能在下一次运行时从中读取而不是打开一个新的光标。取决于编译过程中CLOSQLCUR选项是什么(或使用EXEC SQL SET OPTION进行设置)

您应该在OPENFETCH之后检查SQLSTATE / SQLCODE

另一种常见的做法是在CLOSE之前执行OPEN,再次确保检查SQLSTATE / SQLCODE并在结束时忽略CURSOR NOT OPEN

答案 1 :(得分:1)

查尔斯所说的话,而且我相信您在某些情况下甚至可以使用此代码创建无限循环!也许您没有给出完整的代码,但是如果获取成功(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;

这使您可以将所有数据库代码保存在一个位置,并仅从程序中调用它。数据库过程只是访问数据库并以某种方式报告错误。有时冗长的数据库和错误处理代码可能会使您的程序逻辑混乱不清。

另一件事,我不检查游标关闭时是否有错误,因为这里可以返回的唯一错误(语法错误除外)是游标没有打开。我不在乎,因为那正是我想要的。