Используя Pro * C, как извлечь из курсора, открытого в хранимой функции PL, без установки опции ‘sqlcheck = semantics’?

Я пытаюсь получить данные из переменной курсора, открытой в хранимой функции, но я всегда получаю сообщение об ошибке «Извлечь из последовательности».

Вот хранимая функция:

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 == '\0')
{
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;

1

Решение

Я думаю, что нашел проблему и одно решение. При открытии курсора в блоке PL / SQL индекс курсора начинается с 0, а у Pro * C — с 1. Проблема, я думаю, заключается в том, что Pro * C вообще не обновляет индекс курсора, поэтому одним из решений может быть увеличить вручную, как это видно Вот.

...
while (sqlca.sqlcode == '\0')
{
sql_cursor_pl.curocn++;
EXEC SQL FETCH :sql_cursor_pl INTO :string_field;
...
}
...
2

Другие решения

Проблема заключается в состоянии while, которое проверяется перед выполнением FETCH команда.

Я обычно разрешаю эти циклы, используя 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.
Вторая директива необходима для восстановления желаемого поведения (здесь требуется некоторое прерывание, но в остальной части кода это, вероятно, не лучший выбор).

1

По вопросам рекламы [email protected]