我可以通过带有引用游标的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);
}
答案 0 :(得分:1)
我找到了解决方法。需要尝试更多的呼叫组合,但最终到达那里。我已经更正了原始代码以反映正确的解决方案。
关键是要在游标本身定义prefetch rows属性,而不是语句指针。