我正在用IBM RDI进行编码,并在5250仿真器上运行该程序。我正在编写一个简单程序,该程序从单个SQL表读取并将结果输出到打印机文件。该代码基本上可以按预期工作,但是遇到了一些奇怪的事情。当我尝试按desc顺序对游标select语句进行排序时,它返回空值,但是当我不按或按ASC进行排序时,它可以正常工作。我不明白发生了什么。我真的很想解释。
下面的代码。
DCL-F BOOKRPT2 PRINTER OFLIND(*IN01);
DCL-S INDGENRE BINDEC(4:0);
DCL-S CATEGORY CHAR(30);
DCL-S TOTALRECORDS PACKED(5:0);
DCL-S TOTALCOST ZONED(5:2);
DCL-S EOF IND;
DCL-S DUMMY ZONED(1);
DCL-DS BOOKRECORD;
BOOK CHAR(50);
DURATION TIME(*ISO);
AUTHOR CHAR(30);
BOOKID ZONED(7:0);
PRICE PACKED(5:2);
GENRE CHAR(20);
END-DS;
//DCL-DS AUDIBLEBKS EXT END-DS;
//**************************************************************************
//* *** M A I N R O U T I N E ***
//**************************************************************************
EXSR PREPFILES;
EXSR GETSYS;
WRITE TITLE;
WRITE COLHDG;
EXSR GETROW;
WRITE GENREREC;
CATEGORY = GENRE;
DOW NOT EOF;
IF *IN01 = *ON;
WRITE TITLE;
WRITE COLHDG;
*IN01 = *OFF;
ENDIF;
IF CATEGORY = GENRE;
WRITE DETAIL;
TOTALRECORDS +=1;
TOTALCOST += PRICE;
ELSE;
WRITE TOTALS;
CATEGORY = GENRE;
WRITE GENREREC;
TOTALRECORDS = 0;
TOTALCOST = 0;
ENDIF;
TOTALBOOKS = TOTALRECORDS;
TOTALPRICE = TOTALCOST;
EXSR GETROW;
ENDDO;
WRITE TOTALS;
EXSR WRAPUP;
*INLR = *ON;
RETURN;
BEGSR PREPFILES;
EXEC SQL
DECLARE BOOKCURSOR CURSOR
FOR
SELECT BOOK, DURATION, AUTHOR, BOOKID, PRICE, GENRE
FROM BCI433LIB/AUDIBLEBKS
ORDER BY GENRE DESC;
//FOR READ ONLY;
EXEC SQL
OPEN BOOKCURSOR;
IF SQLCODE <> 0 OR SQLWN0='W';
EOF = *ON;
ENDIF;
ENDSR;
BEGSR GETROW;
EXEC SQL
FETCH NEXT
FROM BOOKCURSOR
INTO :BOOKRECORD;
IF SQLCODE <> 0 OR SQLWN0 = 'W';
EOF = *ON;
ENDIF;
ENDSR;
BEGSR WRAPUP;
EXEC SQL
CLOSE BOOKCURSOR;
IF SQLCODE <> 0 OR SQLWN0 ='W';
EOF = *ON;
ENDIF;
ENDSR;
BEGSR GETSYS;
EXEC SQL
SELECT CURRENT SERVER, CURRENT DATE
INTO :SYSTEMNAME, :REPORTDATE
from SYSIBM/SYSDummy1;
ENDSR;
除了代码格式化问题之外,我看到的最可能的答案是,当您按ASC
排序时,查询中的最后一条记录存在问题,而当您按DESC
排序时,它是第一个记录问题。如其他答案所述,应该通过查看SQLSTATE
轻松检查。最快的方法是在RDi调试器中或通过STRDBG
运行它。
IMO,您的程序应始终检查SQLSTATE并具有处理异常SQLSTATE值的代码。它可能正在写入作业日志,发送电子邮件警报等。
If SQLSTATE <> '00000'; // sucess
// handle abnormal condition
Endif;
如果您无法/不会更改代码,请使用RDi调试代码并在每次操作后检查SQLSTATE。
正如其他人所说,您应该检查SQL状态,但是我忽略警告。光标的最后一行很有可能引起警告而不是错误。因此STRSQL会显示记录,但是由于您不满意警告(但未指出警告可能),因此您什么也收不到。
这是我在程序中几乎所有SQL语句之后都放置的错误检查代码。
exec sql
...
if %subst(sqlstate: 1: 2) < '00' or %subst(sqlstate: 1: 2) > '02';
exec sql get diagnostics condition 1
:message = message_test;
SendSqlMsg(message);
endif;
这里有一些说明,消息是varchar(6000),SendSqlMsg()是我编写的用于发送转义消息的子过程。
关于SQLSTATE类的更多说明(SQLSTATE的前两个字符:
其他一切都是错误。
还有一个说明,我说过我实际上在每个SQL语句之后都放了这个,但是在结束游标之后我不检查它。这就是原因。 CLOSE
引发的唯一状态是“光标已关闭”。我不在乎关闭游标是否由于这个原因而失败,因为我希望关闭游标,并且它已关闭,没问题。