Вызов OCIStmtExecute () с курсором ссылки и OCI_ATTR_PREFETCH_ROWS?

0

Я могу вызвать хранимую процедуру через OCI с помощью курсора ref, а затем перебрать результаты, используя вызов OCIStmtFetch2() каждый раз. Мой вопрос в том, как я могу перебирать ряд строк, поэтому мне не нужно каждый раз вызывать OCIStmtFetch2()? Предположим, что ответ будет что-то с OCI_ATTR_PREFETCH_ROWS, но я не могу заставить это работать, поскольку доступ к файлам создается каждый раз, когда я вызываю OCIStmtExecute.

http://www.sqlines.com/oracle/oci/array_fetch работает для операторов select, но я хочу использовать его для курсора, который разбивается на мою реализацию. Извините за длину кода, но вот полная функция:

OCIError* pOciError;
OCIStmt* pOciStatement;
char* sqlCharArray = "BEGIN fxt.fxt_get_risk_trns('SOD', '29-SEP-2014', :refCursor ); END;";
OCIEnv* g_pOciEnvironment = NULL;
OCIServer* g_pOciServer = NULL;
OCISession* g_pOciSession = NULL;
OCISvcCtx* g_pOciServiceContext = NULL;
sb2* pIndicator=0;
OCIDefine* pOciDefine2;
OCIBind* pBind;
OCIStmt* cursor;

int answer = OCIEnvCreate((OCIEnv **)&g_pOciEnvironment, (ub4)OCI_THREADED ,
     (void  *)0, (void  * (*)(void  *, size_t))0,
     (void  * (*)(void  *, void  *, size_t))0,
     (void (*)(void  *, void  *))0,
     (size_t)0, (void  **)0);

<snip boilerplate code>
const int prefetchSize(PREFETCH_ROWS_SIZE);
answer = OCIHandleAlloc(g_pOciEnvironment , (void **)(&pOciStatement), OCI_HTYPE_STMT, 0, NULL);
answer = OCIAttrSet(pOciStatement, OCI_HTYPE_STMT, (void*)&prefetchSize, sizeof(int), OCI_ATTR_PREFETCH_ROWS, pOciError);

answer = OCIStmtPrepare(pOciStatement, pOciError, (unsigned char *)sqlCharArray, strlen(sqlCharArray),OCI_NTV_SYNTAX, OCI_DEFAULT);
answer = OCIHandleAlloc(g_pOciEnvironment, (void **)(&cursor), OCI_HTYPE_STMT, 0, NULL);
answer = OCIBindByPos(pOciStatement, &pBind, pOciError, 1, &cursor, 0, SQLT_RSET, pIndicator, 0, NULL, 0, 0, OCI_DEFAULT);

// Fetched data indicators, lengths and codes
char dealSTSCode[PREFETCH_ROWS_SIZE][4000];
sb2 dealSTSCode_ind[PREFETCH_ROWS_SIZE];
ub2 dealSTSCode_len[PREFETCH_ROWS_SIZE], dealSTSCode_code[PREFETCH_ROWS_SIZE];

answer = OCIAttrSet(cursor, OCI_HTYPE_STMT, (void*)&prefetchSize, sizeof(int), OCI_ATTR_PREFETCH_ROWS, pOciError);

// Unhandled exception thrown here, Access violation reading location xxx
answer = OCIStmtExecute(g_pOciServiceContext, pOciStatement, pOciError, PREFETCH_ROWS_SIZE, 0, NULL, NULL, OCI_DEFAULT);
answer = OCIDefineByPos(cursor,&pOciDefine2, pOciError,6, (void*)&dealSTSCode, 4000, SQLT_STR, dealSTSCode_ind, dealSTSCode_len, dealSTSCode_code,OCI_DEFAULT);    

if (answer == 0)
{
    int rowsFetched = 0;
    do
    {
        if (!OCIStmtFetch2(cursor, pOciError, 100, OCI_FETCH_NEXT,0,OCI_DEFAULT))
        {
            OCIAttrGet(cursor, OCI_HTYPE_STMT, (void*)&rowsFetched, NULL, OCI_ATTR_ROWS_FETCHED, pOciError);
            for (int i = 0; i != rowsFetched; ++i)
            {
                // process row
            }
        }
    }
    while (rowsFetched > 0);
}
  • 0
    Привет @ hoganj_lv_426, Вам нужно было установить атрибут предварительной выборки OCI_ATTR_PREFETCH_ROWS до и после выполнения оператора? Не могли бы вы объяснить, какой из них сделал разницу видимой для вас?
Теги:
oci

1 ответ

0

Я нашел решение этого. Нужно было попробовать еще несколько комбинаций звонков, но в итоге попало туда. Я исправил исходный код, чтобы отразить правильное решение.

Главное - определить атрибут prefetch rows на самом курсоре, а не указатель оператора.

  • 0
    Я думаю, что определение вызова после StmtExecute () может быть удалено.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню