OCI 呼叫Oracle 儲存過程實現
阿新 • • 發佈:2019-01-02
OCI呼叫儲存過程
最近的風控框架開發中,遇到一個場景,即程式需要呼叫Oracle中的儲存過程,但是目前的框架中並不支援,只支援呼叫組裝好的SQL語句,即基本的資料庫增刪改查操作,這樣就需要開發OCI呼叫儲存過程。
基於這個需求,開始網上找尋資料。由於使用到的是OCI介面,而該介面文件只有英文版,而且很不全面,偏偏需要使用到的OCI呼叫儲存過程API程式例子沒有,所以只能從網上一些部落格等找尋。經過不停的搜尋,關鍵字換來換去的搜尋,搜尋引擎從百度,Google映象網站,最後到微軟的必應搜尋,都使用到了,仍然沒有搜尋到一個正確的完整的程式碼示例。找到了一兩個類似的感覺可以使用的,編譯,執行發現都是不行的。驗證了那就話,中國的很多技術部落格就是你抄我,我抄你。然後開始往一些國外的網站搜尋,StackOverflow等等,都沒有搜尋到完整的正確的示例,最後根據之前的OCI程式封裝,推測出呼叫儲存過程的類似寫法,把整體的呼叫函式寫完了,之後就是引數的問題了,引數比較多,使用起來特別複雜,需要知道每個引數的意義。經過不斷的編譯,執行,測試,最後將所有的引數除錯正確執行完整。
最後的完整示例程式碼如下,方便以後的開發人員使用。不用像我這樣發費這麼大精力去搜索和試驗。
int ora_procedure_execute(structS_OracleContext*oractx, constchar*pszSQL,char*userid,char*exptype,char*conditionexp,char**resultof,int*errorcode,char**errormsg){
OCIBind * bidhp[6];
sb2 sb2aInd[3];
OCIStmt*stmthp=NULL;
swordretcode = 0;
sb4errcode = 0;
*resultof= NULL;
*errorcode=NULL ;
*errormsg= NULL;
char *pszGBKSQL;
//資料庫需要 GBK的SQL語句。因此需要轉換字符集
pszGBKSQL= UTF8ToGBK(pszSQL);
if (!pszGBKSQL)
{
LogMessage("utf8 to gbk failed in ora_execute()");
return -1;
}
if (NULL ==oractx->envhp)
{
LogMessage("oractx->envhp==NULL inora_execute()." );
delete pszGBKSQL;
return -2;
}
retcode= OCIHandleAlloc( (dvoid *) oractx->envhp, (dvoid **) &stmthp,OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0);
ora_check_error(oractx->errhp,retcode,&errcode);
if (0!=retcode || NULL==stmthp)
{
LogMessage("OCIHandleAlloc()failed in ora_execute().");
delete pszGBKSQL;
return -3;
}
retcode= OCIStmtPrepare(stmthp, oractx->errhp, (text *)pszGBKSQL, (ub4) strlen(pszGBKSQL), (ub4)OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT);
ora_check_error(oractx->errhp,retcode, &errcode);
if(retcode!=OCI_SUCCESS&& retcode!=OCI_SUCCESS_WITH_INFO)
{
LogMessage("OCIStmtPrepare() failed %d,%d. reconnect ORACLE,sql=%s", retcode,errcode,pszGBKSQL);
if(errcode != 1756)
{
OCIHandleFree(stmthp,OCI_HTYPE_STMT);
ora_clean(oractx);
delete pszGBKSQL;
return -4;
}
LogMessage("Error 1756, minor error, ignore it.");
OCIHandleFree(stmthp,OCI_HTYPE_STMT);
delete pszGBKSQL;
return 0;
}
//繫結3個輸入變數
if ((retcode=OCIBindByPos(stmthp, &bidhp[0],oractx->errhp,(ub4) 1, (dvoid *)userid,(sb4)(strlen(userid)+1),SQLT_STR,NULL, NULL, NULL, 0, NULL, (ub4)OCI_DEFAULT))!=OCI_SUCCESS)
{
ora_check_error(oractx->errhp,retcode, &errcode);
LogMessage("ora_procedure_execute Error when OCIBindByPosuserid\n");
return -9;
}
if ((retcode=OCIBindByPos(stmthp, &bidhp[1],oractx->errhp,(ub4) 2, (dvoid *)exptype,(sb4)(strlen(exptype)+1),SQLT_STR,NULL, NULL, NULL, 0, NULL, (ub4)OCI_DEFAULT))!=OCI_SUCCESS)
{
ora_check_error(oractx->errhp,retcode, &errcode);
LogMessage("ora_procedure_execute Error when OCIBindByPosexptype\n");
return -9;
}
if ((retcode=OCIBindByPos(stmthp, &bidhp[2],oractx->errhp,(ub4) 3, (dvoid*)conditionexp,(sb4)(strlen(conditionexp)+1),SQLT_STR, NULL, NULL, NULL, 0,NULL, (ub4)OCI_DEFAULT))!=OCI_SUCCESS)
{
ora_check_error(oractx->errhp,retcode, &errcode);
LogMessage("ora_procedure_execute Error when OCIBindByPosconditionexp\n");
return -9;
}
//定義3個變數儲存輸出引數
char szResult[4096];
memset(szResult,0,sizeof(szResult));
int nErrorcode = 0 ;
char szErrorMsg[4096];
memset(szErrorMsg,0,sizeof(szErrorMsg));
if ((retcode= OCIBindByPos(stmthp, &bidhp[3], oractx->errhp,(ub4)4,(dvoid*)(szResult),(sword)4096, SQLT_STR, &sb2aInd[0], NULL, NULL, 0, NULL, (ub4)OCI_DEFAULT))!=OCI_SUCCESS)
{
ora_check_error(oractx->errhp,retcode, &errcode);
LogMessage("ora_procedure_execute Error when OCIBindByNamebusiness_date \n");
return -9;
}
if ((retcode=OCIBindByPos(stmthp, &bidhp[4], oractx->errhp,(ub4)5,(&nErrorcode),(sizeof(int)),SQLT_INT,&sb2aInd[1], NULL, NULL, 0, NULL,(ub4)OCI_DEFAULT))!=OCI_SUCCESS)
{
ora_check_error(oractx->errhp,retcode, &errcode);
LogMessage("ora_procedure_execute Error when OCIBindByNamebussiness_nodeid \n");
return -9;
}
if ((retcode=OCIBindByPos(stmthp, &bidhp[5], oractx->errhp,(ub4)6, (dvoid*)(szErrorMsg), (sword)4096,SQLT_STR, &sb2aInd[2], NULL, NULL, 0, NULL,(ub4)OCI_DEFAULT))!=OCI_SUCCESS)
{
ora_check_error(oractx->errhp,retcode, &errcode);
LogMessage("ora_procedure_execute Error when OCIBindByNamebusiness_date \n");
return -9;
}
retcode= OCIStmtExecute(oractx->svchp, stmthp, oractx->errhp, (ub4) 1,(ub4)0, (OCISnapshot *)NULL,(OCISnapshot*)NULL,(ub4)OCI_DEFAULT);
ora_check_error(oractx->errhp, retcode, &errcode);
if (0!=retcode)
{
LogMessage("OCIStmtExecute() failed.retcode=%d,errcode=%d,sql:%s", retcode, errcode, pszGBKSQL);
if (OCI_ERROR==retcode&& errcode!=1756)
{
LogMessage("OCIStmtExecute() failed. erroroccured,disconnect");
OCIHandleFree(stmthp,OCI_HTYPE_STMT);
ora_clean(oractx);
delete pszGBKSQL;
return -5;
}
}
*errorcode= nErrorcode;
*errormsg= newchar[sizeof(szErrorMsg) + 1];
memcpy(*errormsg,(char*)szErrorMsg,strlen(szErrorMsg)+ 1);
*resultof= newchar[sizeof(szResult) + 1];
memcpy(*resultof,(char*)szResult,strlen(szResult)+ 1);
//commit
if((retcode=OCITransCommit(oractx->svchp, oractx->errhp, (ub4) 0)) !=OCI_SUCCESS)
{
ora_check_error(oractx->errhp,retcode, &errcode);
LogMessage("ora_dbbind_execute Error when OCIStmtCommit\n");
return -6;
}
delete pszGBKSQL;
OCIHandleFree(stmthp,OCI_HTYPE_STMT);
return 0;
}