使用引用游标和OCI_ATTR_PREFETCH_ROWS调用OCIStmtExecute()?

时间:2014-10-10 14:08:36

标签: c++ oracle oci

我可以通过带有引用游标的OCI调用存储过程,然后每次使用对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);
}

1 个答案:

答案 0 :(得分:1)

我找到了解决方法。需要尝试更多的呼叫组合,但最终到达那里。我已经更正了原始代码以反映正确的解决方案。

关键是要在游标本身定义prefetch rows属性,而不是语句指针。