使用 Pro*C,如何在不设置 'sqlcheck=semantics' 选项的情况下从 PL 存储函数中打开的游标中获取数据?
Using Pro*C, how to fetch from a cursor opened in PL stored function without setting 'sqlcheck=semantics' option?
我试图从在存储函数中打开的游标变量中获取数据,但我总是收到 "fetch out of sequence" 错误消息。
这是存储函数:
CREATE OR REPLACE FUNCTION test_function RETURN SYS_REFCURSOR AS
p_recordset SYS_REFCURSOR;
BEGIN
OPEN p_recordset FOR SELECT '1' FROM DUAL UNION SELECT '2' FROM DUAL;
RETURN p_recordset;
END TEST_FUNCTION;
Pro*C 代码:
int myfunction()
{
...
EXEC SQL BEGIN DECLARE SECTION;
SQL_CURSOR sql_cursor_pl;
VARCHAR string_field[20];
EXEC SQL END DECLARE SECTION;
EXEC SQL ALLOCATE :sql_cursor_pl;
// It is not possible to use embedded PL/SQL block as seen in other
// examples because it requieres a compilation time access to database
// that I don't have, so as far as I know I have to use EXEC SQL CALL
EXEC SQL CALL sch.test_function() INTO :sql_cursor_pl;
EXEC SQL WHENEVER NOT FOUND DO break;
//for ( ; ; )
while (sqlca.sqlcode == '[=12=]')
{
EXEC SQL FETCH :sql_cursor_pl INTO :string_field;
...
}
EXEC SQL CLOSE :sql_cursor_pl;
...
}
如果我像下面这样在其他 PL 块中使用存储的函数,它就可以正常工作,所以我认为问题应该出在 Pro*C 代码中。
DECLARE
mycursor sys_refcursor;
string_field VARCHAR(20)
BEGIN
mycursor := sch.test_function();
LOOP
FETCH mycursor INTO string_field;
EXIT WHEN mycursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(string_field);
END LOOP;
CLOSE mycursor;
END;
问题出在执行FETCH
命令之前测试的while条件。
我通常使用 EXEC SQL WHENEVER NOT FOUND
指令来解决这些循环。以下是有关如何操作的示例:
while(1)
{
EXEC SQL WHENEVER NOT FOUND DO break; // Where a no data found occurs execute a C "break" instruction.
EXEC SQL FETCH :sql_cursor_pl INTO :string_field;
EXEC SQL WHENEVER NOT FOUND DO ???; // Restore desired behaviour.
...
}
第一条指令指示 Pro*C/C++ 在出现未发现数据错误时执行 break
,这意味着退出 while 循环。
需要第二个指令来恢复所需的行为(此处需要在 while 内进行中断,但在其余代码中可能不是最佳选择)。
我想我已经找到了问题所在和一个解决方案。在 PL/SQL 块中打开游标时,游标索引从 0 开始,但 Pro*C 的从 1 开始。我认为问题是 Pro*C 根本不更新游标索引,因此一种解决方案可能是像这样手动增加 here.
...
while (sqlca.sqlcode == '[=10=]')
{
sql_cursor_pl.curocn++;
EXEC SQL FETCH :sql_cursor_pl INTO :string_field;
...
}
...