我对IBM i有点新,我来自Java / C#背景。所以,如果我使用错误的术语,请纠正我。我们目前使用的是IBM i 7.1,并将在明年内转向7.3。
我的任务是更新文件中的记录。我在这里写了两个RPGLE程序来做同样的事情。
原生I / O:
**free
dcl-f table1 usage(*update) keyed;
setll ('001': 'Y') table1;
reade ('001': 'Y') table1;
dow not %eof(table1);
letter = 'X';
update table1;
reade ('001': 'Y') table1;
enddo;
*inlr = *ON;
return;
嵌入式SQL:
**free
exec sql UPDATE table1
SET letter = 'X'
WHERE GroupCode = '001' AND Newbie = 'Y';
*inlr = *ON;
return;
在我看来,这是SQL与原生I / O相比具有强大优势的时代之一。
这是我的问题。我的公司依赖于CPF消息。像许多公司一样,我们并不完美并拥有遗留代码。有相当多的,有时我们得到记录锁。发生这种情况时,会向系统发送一条错误消息,并等待某人登录并回答。
这导致调用我们的内部支持,并且通常在有人访问它时,锁定文件的程序完成,我们只需要回答R重试,并且更新继续从中断。这种情况并不经常发生,以至于我们可以花时间来修复调度过程以及所有程序的记录锁定,但通常情况下,没有这种能力会导致我们大量的痛苦。
使用本机I / O会抛出这些消息。使用嵌入式SQL,SQLSTATE和SQLCODE变量已设置,程序将继续,而不向系统发送任何消息。我可以检查这个变量,编写我自己的消息,并在出现问题时向系统发送消息。然而;这不太理想。如果我手动提供重试选项,则无法从停止的位置恢复更新。我必须再次运行整个更新语句。
我已经查看过编译器选项,控制选项,sql选项和sql命令,而且我所看到的没有一个让我能够找到它的能力。
简而言之,我想知道,有没有一种方法可以让嵌入式SQL在不受监视的错误消息上表现得像本机I / O一样?
答案 0 :(得分:1)
简而言之......不。
SQL是一种不同的范例。 DB2 for i中的SQL错误处理就像SQL中的任何其他语言的错误处理一样......
您可能希望在承诺控制下运行UPDATE
。然后检查sqlstate。如果没有错误,COMMIT
交易。
否则,ROLLBACK
交易,并显示您的消息。此时,重试选项将循环返回并重新发出SQL UPDATE
。
<强>的刊登强>
在你添加了所有这些之后,你的SQL版本看起来并不那么简洁吗?哎呀RPG版本实际上可以减少到5或6行...如果你想上学和使用输入主文件。不是说我现在推荐它。
RPG与数据库的紧密集成为您做了很多工作。 SQL很好,我一直都在使用它,但有时候更多的控制更好。值得庆幸的是,在IBM i上有SQL的替代品。
答案 1 :(得分:1)
更好的解决方案是捕获记录锁定错误并自动重试数据库更新操作,直到锁定消失,或在特定超时间隔后挽救。这可以通过本机I / O或SQL轻松实现,并且应该减少相当大比例的支持事件。
答案 2 :(得分:1)
我一直在野外看到这一点。不使用乐观代码。如果失败了,即使传统程序正在运行,也许乐观的编码就会超越它。
当行被锁定时,如何重做呢?导致过时编码技术问题的老游戏会用一条消息来锁定进程,因为他们所做的就是编写依赖于人为干预的代码。现在队列中的任何其他内容都被阻止,等待操作员回复消息的更多事情将会失败。
现代计划在未来失败时将能够重新安排自己。当进程重新安排时,可能会发送电子邮件。就像将来安排的可运行一样。
exec sql UPDATE table1
SET letter = 'X'
WHERE GroupCode = '001' AND Newbie = 'Y'
and letter <> 'X'; /* and letter <> 'X' is the optimistic part */
*inlr = *ON;
return;
if calledpgm failed then reschedule to run in the future send an email to support if desired.
答案 3 :(得分:1)
如果您寻找完全改变方法的解决方案,可以有很多方法。仅在一个特定路径上(仅使用本机或仅使用sql等)缩小选项范围。
我试着看看上面的不同答案,这是我的观点
- 使用danny117的方法,如果没有依赖于“时间”,文件字段'字母'可以更新为'x'然后在'监视器'内部更新sql并让整个程序运行带有过滤器的多个计划在letter ='x'上可以是一个选项
- 对于jmarkmurphy的方法,但等待取决于文件属性,如果文件在外面锁定较长时间可能会有问题。
- 因为即使查尔斯选项也没有帮助偶尔锁定和释放
- 我正在考虑另一种选择,如果更新运行速度快于其他程序将锁定文件的持续时间。为此更新“专门”分配文件,并在成功更新后将其释放。在分配循环期间,延迟步骤直到你获得文件的独占锁定,然后更新。
答案 4 :(得分:0)
在这种情况下你可以:
**free
dou sqlstate = '00000' or sqlstate = '02000';
exec sql UPDATE table1
SET letter = 'X'
WHERE GroupCode = '001'
AND Newbie = 'Y'
and letter <> 'X';
enddo;
*inlr = *ON;
return;
锁定仍会在SQL中等待60秒左右,具体取决于文件的WAITRCD
属性或覆盖,因此这不会造成太大的问题。
您还可以创建一个过程,以便在锁定的情况下发送消息并将其实现为:
**free
dou sqlstate = '00000' or sqlstate = '02000';
exec sql UPDATE table1
SET letter = 'X'
WHERE GroupCode = '001'
AND Newbie = 'Y'
and letter <> 'X';
if sqlstate = '57033';
SendSqlMsg('SQL0913');
endif;
enddo;
*inlr = *ON;
return;
您甚至可以让该程序发送查询消息并检索回复。然后根据需要处理回复。我将把它作为练习留给你。