我相信我可能已经发现了生产错误,该错误会导致间歇性问题。基本上,我试图了解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声明,但我想得到第二个意见,因为由于测试与生产之间的安全密钥差异,几乎不可能重新创建生产问题。
谢谢!
答案 0 :(得分:1)
DECLARE CURSOR
实际上是一个编译时语句。
它永远不会在运行时执行。
在运行时完成:var1
时, OPEN
被传递到数据库。这是一个带有详细示例Using cursor for multiple search conditions
是的,如代码所示,光标将保持打开状态。并可能在下一次运行时从中读取而不是打开一个新的光标。取决于编译过程中CLOSQLCUR
选项是什么(或使用EXEC SQL SET OPTION
进行设置)
您应该在OPEN
和FETCH
之后检查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;
这使您可以将所有数据库代码保存在一个位置,并仅从程序中调用它。数据库过程只是访问数据库并以某种方式报告错误。有时冗长的数据库和错误处理代码可能会使您的程序逻辑混乱不清。
另一件事,我不检查游标关闭时是否有错误,因为这里可以返回的唯一错误(语法错误除外)是游标没有打开。我不在乎,因为那正是我想要的。