AS400 嵌入式 SQL 游标处理
AS400 embedded SQL cursor handling
我相信我可能发现了一个导致间歇性问题的生产错误。基本上,我试图了解 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 的关闭。在作业日志中,有 "Cursor T1 already open or allocated." 等信息性消息。我认为这意味着它没有做任何事情,或者甚至可能从前一个游标中获取?我还想知道是否每次都执行 declare 语句,或者它是否只是在第一次执行后跳过那部分代码。我想我需要在 open 语句之前放置一个 close T1 语句,但我想获得第二意见,因为这是一个生产问题,由于测试和生产之间的安全密钥差异,几乎不可能重新创建。
谢谢!
a DECLARE CURSOR
实际上是一个编译时语句。
从未在 运行 时执行。
当 OPEN
在 运行 时间完成时,:var1
被传递给数据库。这是一个带有详细示例的答案 Using cursor for multiple search conditions
是的,如代码所示,光标将保持打开状态。并可能在下一个 运行 期间读取而不是打开一个新游标。取决于 CLOSQLCUR
选项在编译期间是什么(或使用 EXEC SQL SET OPTION
设置)
您应该在 OPEN
和 FETCH
之后检查 SQLSTATE/SQLCODE
另一种常见的做法是在 OPEN
之前做一个 CLOSE
,再次确保检查 SQLSTATE/SQLCODE 并在收盘时忽略 CURSOR NOT OPEN
。
Charles 所说的,而且我相信您在某些情况下甚至可以用这段代码创建一个无限循环!也许您没有给出完整的代码,但如果获取成功 (SQLCOD = 0) 并且 a <> b,那么您将陷入循环。
我喜欢将提取放在子过程中,returns *如果成功读取记录则打开。然后你可以这样做:
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;
这让您可以将所有数据库代码保存在一个地方,只需从您的程序中调用它。数据库过程只是访问数据库并以某种方式报告错误。您的程序逻辑可以通过有时冗长的数据库和错误处理代码保持整洁。
另外一件事,我不检查游标关闭时的错误,因为这里可以返回的唯一错误(语法错误除外)是游标未打开。我不在乎那个,因为这就是我想要的。
我相信我可能发现了一个导致间歇性问题的生产错误。基本上,我试图了解 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 的关闭。在作业日志中,有 "Cursor T1 already open or allocated." 等信息性消息。我认为这意味着它没有做任何事情,或者甚至可能从前一个游标中获取?我还想知道是否每次都执行 declare 语句,或者它是否只是在第一次执行后跳过那部分代码。我想我需要在 open 语句之前放置一个 close T1 语句,但我想获得第二意见,因为这是一个生产问题,由于测试和生产之间的安全密钥差异,几乎不可能重新创建。
谢谢!
a DECLARE CURSOR
实际上是一个编译时语句。
从未在 运行 时执行。
当OPEN
在 运行 时间完成时,:var1
被传递给数据库。这是一个带有详细示例的答案 Using cursor for multiple search conditions
是的,如代码所示,光标将保持打开状态。并可能在下一个 运行 期间读取而不是打开一个新游标。取决于 CLOSQLCUR
选项在编译期间是什么(或使用 EXEC SQL SET OPTION
设置)
您应该在 OPEN
和 FETCH
另一种常见的做法是在 OPEN
之前做一个 CLOSE
,再次确保检查 SQLSTATE/SQLCODE 并在收盘时忽略 CURSOR NOT OPEN
。
Charles 所说的,而且我相信您在某些情况下甚至可以用这段代码创建一个无限循环!也许您没有给出完整的代码,但如果获取成功 (SQLCOD = 0) 并且 a <> b,那么您将陷入循环。
我喜欢将提取放在子过程中,returns *如果成功读取记录则打开。然后你可以这样做:
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;
这让您可以将所有数据库代码保存在一个地方,只需从您的程序中调用它。数据库过程只是访问数据库并以某种方式报告错误。您的程序逻辑可以通过有时冗长的数据库和错误处理代码保持整洁。
另外一件事,我不检查游标关闭时的错误,因为这里可以返回的唯一错误(语法错误除外)是游标未打开。我不在乎那个,因为这就是我想要的。