OCI 调用Oracle 存储过程实现

2/13/2017来源:SQL技巧人气:1285

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; }