一、环境的配置
1、系统环境:要想使用OCI编程需要安装Oracle的客户端,而这个普通的客户端比较大,方便起见,可以安装即时客户端(Instantclient)作为Oracle的访问客户端。
具体的配置可以参考这里: http://www.cnblogs.com/ychellboy/archive/2010/04/16/1713884.html
2、执行环境:
windows下的配置可以参考这里: http://blog.csdn.net/sherlockhua/article/details/4353531 linux下的配置可以参考这里: http://blog.csdn.net/sherlockhua/article/details/4353531
二、基本理论
1、首先要创建OCI环境,即创建和初始化OCI工作环境,其他的OCI函数需要OCI环境才能执行。 2、分配OCI环境句柄:它定义所有OCI函数的调用环境,是其他句柄的父句柄。( 由OCIEnvInit 或OCIEnvCreate 生成 ) 。 3、错误句柄:作为一些OCI函数的参数,用来记录这些OCI函数操作过程中所产生的错误,当有错误发生时,可用OCIErrorGet()来读取错误句柄中记录的错误信息。 4、服务器环境句柄:定义OCI调用的服务器操作环境,它包含服务器、用户会话和事务三种句柄。 5、服务器句柄:标识数据源,它转换为与服务器的物理连接。
6、用户会话句柄:定义用户角色和权限及OCI调用的执行环境。 7、事务句柄:定义执行SQL操作的事务环境,事务环境中包含用户的会话状态信息。
注意:Bind/Define 句柄在执行具体的SQL语句的时候,被隐含创建并连接到表达句柄(Statement Handle)上,当表达句柄释放时,它们也被隐含释放。所以在执行每一个sql语句时,先分配表达句柄,执行结束后,释放表达句柄,这样做保证不发生由于定位句柄和绑定变量句柄引起的内存泄漏。
三、操作步骤
OCI连接Oracle数据库的步骤比较复杂,除了分配设置各个基本句柄外,还要明确彼此之间的联系,大致流程如下:
1、创建环境句柄: OCIEnvCreate(&envhp, ?); 2、创建一个指定环境的错误句柄: OCIHandleAlloc((dvoid *)envhp, (dvoid **)&errhp,?); 3、创建一个指定环境的服务器句柄: OCIHandleAlloc((dvoid *)envhp, (dvoid **)&servhp,?); 4、建立到数据源的访问路径 : OCIServerAttach(servhpp, errhpp,?); 5、创建一个指定环境的服务上下文句柄: (void) OCIHandleAlloc((dvoid *)envhpp,?); 6、为指定的句柄及描述符设置特定的属性: (void) OCIAttrSet((dvoid *)svchpp,?); 7、创建一个指定环境的用户连接句柄: (void) OCIHandleAlloc((dvoid *)envhpp,?); 8、为用户连接句柄设置登录名及密码: (void) OCIAttrSet((dvoid *)usrhpp,?); 9、认证用户建立一个会话连接: OCISessionBegin(svchpp, errhpp,?); 10、创建一个句子句柄: OCIHandleAlloc((dvoid *)envhpp,?); 11、准备 SQL 语句: OCIStmtPrepare(stmthpp, errhpp,?); 12、绑定输入变量: OCIBindByPos(stmtp &hBind, errhp,?); 13、绑定输出变量: OCIDefineByPos(stmthpp, &bhp1, errhpp,?); 14、获得 SQL 语句类型: OCIAttrGet ((dvoid *)stmthpp, (ub4)OCI_HTYPE_STMT,?); 15、执行 SQL 语句: OCIStmtExecute(svchpp, stmthpp,?); 17、释放一个会话: OCISessionEnd(); 18、删除到数据源的访问 : OCIServerDetach(servhpp, errhpp, OCI_DEFAULT); 19、释放句柄: OCIHandleFree((dvoid *) stmthpp, OCI_HTYPE_STMT);
四、示例
程序1
//============================================================================ // Name : CExercise.cpp // Author : Haier // Version : 0.1 // Copyright : Your copyright notice // Description : Connect Oracle in C++, Ansi-style //============================================================================ #include <oci.h> #include <iostream> #include <stdio.h> #include <string> #include <string.h> #include <stdlib.h> #include <ociapr.h> #include <ocidem.h> using namespace std; Lda_Def lda; cda_def cda; dvoid oci_error(void) { text msg[600]; sword rv; //取错误信息 rv=oerhms(&lda,cda.rc,msg,600); //显示错误码和错误信息 printf("\n\n%.*s",rv,msg); //显示发生错误的oci函数 printf("processing oci function %s\n",oci_func_tab[cda.fc]); //关闭光标 if(oclose(&cda)) printf("error closing cursor!\n"); if(ologof(&lda)) printf("error logging off!\n"); exit(1); } int main() { char szDbUser[]="[email protected]"; char szPassword[] ="1qaz!QAZ"; char pc_msg[256]; char sql[256] = "update so1.ins_prod_a set state=‘1‘ where bill_id=‘15238075968‘"; if(olon( &lda,(OraText*)szDbUser, -1, (OraText*)szPassword, -1, 0)) { oci_error(); } cout<<"Connect to Oracle DB Successed!"<<endl; if(oopen(&cda,&lda,(OraText*)0,-1,-1,(OraText*)0,-1)) { oci_error(); } cout<<"Open Curse Successed!"<<endl; if(oparse(&cda,(OraText*)sql,-1,0,2)) { oci_error(); } cout<<"Parse Sql Successed!"<<endl; if(oexn( &cda, 1, 0 )) { oci_error(); } cout<<"exec Sql Successed!"<<endl; if(oparse(&cda,(text*)"commit",-1,0,2)) { oci_error(); } cout<<"Commit Successed!"<<endl; if(oclose(&cda)) { printf("error closing cursor!/n"); exit(1); } //结束事务,退出oracle if(ologof(&lda)) { printf("error logging off!/n"); exit(1); } return 0; }
运行
Connect to Oracle DB Successed! Open Curse Successed! Parse Sql Successed! exec Sql Successed! Commit Successed!
程序2
//============================================================================ // Name : CExercise.cpp // Author : Haier // Version : 0.1 // Copyright : Your copyright notice // Description : Connect Oracle in C++ by oci, Ansi-style //============================================================================ #include <iostream> #include <stdio.h> #include <string> #include <string.h> #include <stdlib.h> #include <oci.h> #include <ociapr.h> #include <ocidem.h> using namespace std; Lda_Def lda; cda_def cda; dvoid oci_error(void) { text msg[600]; sword rv; //取错误信息 rv=oerhms(&lda,cda.rc,msg,600); //显示错误码和错误信息 printf("\n\n%.*s",rv,msg); //显示发生错误的oci函数 printf("processing oci function %s\n",oci_func_tab[cda.fc]); //关闭光标 oclose(&cda); ologof(&lda); exit(1); } sword Login() { char username[20]; char password[20] ; int times=0; do { if(++times>3) { return 1; } cout<<"Enter user-name:"; cin>>username; cout<<"Enter password:"; cin>>password; }while(olon( &lda,(OraText*)username, -1, (OraText*)password, -1, 0)); return 0; } int main() { char bill_id[20]; char password[20]; char sql[256] = "select bill_id,password from so1.ins_prod_a where bill_id=‘15238075968‘"; //登陆oracle if(Login()) { oci_error(); } //禁止自动提交 if(ocof(&lda)) { oci_error(); } //打开curse if(oopen(&cda,&lda,(OraText*)0,-1,-1,(OraText*)0,-1)) { oci_error(); } //分析sql if(oparse(&cda,(OraText*)sql,-1,0,2)) { oci_error(); } //定义输入 if(odefin(&cda,1,(ub1 *)bill_id,sizeof(bill_id),5,-1,(sb2 *)0,(OraText *)0,0,-1,(ub2 *)0,(ub2 *)0)) { oci_error(); } if(odefin(&cda,2,(ub1 *)password,sizeof(password),5,-1,(sb2 *)0,(OraText *)0,0,-1,(ub2 *)0,(ub2 *)0)) { oci_error(); } //执行sql if(oexn( &cda, 1, 0 )) { oci_error(); } //提取结果 if(ofen(&cda,1)) { oci_error(); } //输出结果 cout<<"\n"<<bill_id<<"\t"<<password<<endl; //关闭curse if(oclose(&cda)) { printf("error closing cursor!/n"); exit(1); } //结束事务,退出oracle if(ologof(&lda)) { printf("error logging off!/n"); exit(1); } return 0; }
运行
Enter user-name:[email protected] Enter password:1qaz!QAZ 15238075968 W*_6oJ
程序3
//============================================================================ // Name : CExercise.cpp // Author : Haier // Version : 0.1 // Copyright : Your copyright notice // Description : Connect Oracle in C++ by oci, Ansi-style //============================================================================ #include <iostream> #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #include <oci.h> #include <oratypes.h> #include <ocidfn.h> #include <ociapr.h> #include <ocidem.h> using namespace std; #define MAX_BINDS 12 #define MAX_ITEM_BUFFER_SIZE 32 #define MAX_SELECT_LIST_SIZE 12 #define MAX_SQL_IDENTIFIER 31 #define PARSE_NO_DELAY 0 #define PARSE_V7_LNG 2 #define RAWWIDTH 18 struct describe { sb4 dbsize; sb2 dbtype; sb1 buf[MAX_ITEM_BUFFER_SIZE]; sb4 buflen; sb4 dsize; sb2 precision; sb2 scale; sb2 nullok; }; struct define { ub1 buf[MAX_ITEM_BUFFER_SIZE]; float flt_fuf; sword int_buf; sb2 indp; sb2 col_retlen,col_retcode; }; Lda_Def lda; Cda_Def cda; ub1 hda[256]; text errorMsg[600]; sword stmtLevel; static text sqlStatement[2048]; static sword sqlFunction; static sword numwidth = 8; struct describe desc[MAX_SELECT_LIST_SIZE]; struct define def[MAX_SELECT_LIST_SIZE]; text bindValue[MAX_BINDS][MAX_ITEM_BUFFER_SIZE]; sword connect() { text username[20]; text password[20]; sword n; printf("Copyright (c) 1982, 2014, Oracle. All rights reserved.\n"); printf("Connected to Oracle Database:\n\n"); for(n=3; --n>=0; ) { setbuf(stdout,NULL); printf("Enter user-name: "); gets((char*)username); printf("Enter password: "); gets((char*)password); if(orlon(&lda,hda,(OraText*)username,-1,(OraText*)password,-1,-1)) { oerhms(&lda,lda.rc,(OraText*)errorMsg,sizeof(errorMsg)); printf("%sPlease try again.\n",errorMsg); } else return TRUE; } printf("Connect failed.Exiting...\n"); return FALSE; } sword getSqlStatement() { text sqlBuf[1024]; text *cp; while(1) { if(1==(++stmtLevel)){ *sqlStatement=‘\0‘; printf("\nSQL>"); }else{ printf("%3d>",stmtLevel); } fflush(stdin); gets((char*)sqlBuf); if(*sqlBuf==‘\0‘){ continue; }else { if(!strncmp((char*)sqlBuf,"exit",4) || !strncmp((char*)sqlBuf,"quit",4)) { return 1; } } if(stmtLevel>1) { strcat((char*)sqlStatement," "); } strcat((char*)sqlStatement,(char*)sqlBuf); cp = &sqlStatement[strlen((char*)sqlStatement)-1]; while(isspace(*cp)) { cp--; } if(*cp==‘;‘) { *cp=‘\0‘; break; } } return 0; } void exitOracle(sword code) { if(oclose(&cda)) { oerhms(&cda,cda.rc,(OraText*)errorMsg,sizeof(errorMsg)); printf("%s\n",errorMsg); } if(ologof(&lda)) { oerhms(&lda,lda.rc,(OraText*)errorMsg,sizeof(errorMsg)); printf("%s\n",errorMsg); } exit(code); } void oci_error(Cda_Def *cda) { char choice; oerhms(&lda,lda.rc,(OraText*)errorMsg,sizeof(errorMsg)); printf("%s\n",errorMsg); fprintf(stderr,"Do you want to continue ?[y/n]"); fscanf(stdin,"%c",&choice); if(toupper(choice)!=‘Y‘) { exitOracle(1); } fputc(‘\n‘,stdout); } sword bind(Cda_Def *cda,text *sqlStatement) { sword i,inLiteral,n; text *cp,*ph; for(i=0,inLiteral=0,cp=sqlStatement; *cp && i<MAX_BINDS; cp++) { /* if(*cp==‘\‘‘) { inLiteral=-n; }*/ if(*cp==‘:‘ && !inLiteral) { for(ph=(++cp),n=0; *cp && (isalnum(*cp) || *cp==‘_‘) && n<MAX_SQL_IDENTIFIER; cp++,n++) { } *cp=‘\0‘; printf("Enter value for %s:",ph); gets((char*)&bindValue[i][0]); if(obndrv(cda,(OraText *)ph,-1,(ub1*)bindValue[i],-1,VARCHAR2_TYPE,-1,(sb2*)0,(OraText*)0,-1,-1)) { oci_error(cda); return -1; } i++; } } return i; } sword describeDefine(Cda_Def *cda) { sword col,deflen,deftype; static ub1 *defptr; for(col=0; col<MAX_SELECT_LIST_SIZE; col++) { desc[col].buflen = MAX_ITEM_BUFFER_SIZE; if(odescr(cda,col+1,(sb4*)&desc[col].dbsize,(sb2*)&desc[col].dbtype,(sb1*)(int)desc[col].buf,(sb4*)&desc[col].buflen,(sb4*)desc[col].dsize,(sb2*)(int)desc[col].precision,(sb2*)(int)desc[col].scale,(sb2*)(int)desc[col].nullok)) { if(cda->rc==VAR_NOT_IN_LIST) { break; }else{ oci_error(cda); return -1; } } switch(desc[col].dbtype) { case NUMBER_TYPE: { desc[col].dbsize = numwidth; if(desc[col].scale != 0) { defptr = (ub1*)&def[col].flt_fuf; deflen = (sword)sizeof(float); deftype= FLOAT_TYPE; desc[col].dbtype = FLOAT_TYPE; }else{ defptr = (ub1*)&def[col].int_buf; deflen = (sword)sizeof(sword); deftype= INT_TYPE; desc[col].dbtype = INT_TYPE; } break; } case DATE_TYPE: { desc[col].dbsize = 9; defptr = def[col].buf; deflen = desc[col].dbsize > MAX_ITEM_BUFFER_SIZE ? MAX_ITEM_BUFFER_SIZE : desc[col].dbsize+1; deftype= STRING_TYPE; break; } case ROWID_TYPE: { desc[col].dbsize = 18; defptr = def[col].buf; deflen = desc[col].dbsize > MAX_ITEM_BUFFER_SIZE ? MAX_ITEM_BUFFER_SIZE : desc[col].dbsize+1; deftype= STRING_TYPE; break; } default: { defptr = def[col].buf; deflen = desc[col].dbsize > MAX_ITEM_BUFFER_SIZE ? MAX_ITEM_BUFFER_SIZE : desc[col].dbsize+1; deftype= STRING_TYPE; break; } } if(odefin(cda,col+1,(ub1*)defptr,deflen,deftype,-1,(sb2*)(int)def[col].indp,(OraText*)0,-1,-1,(ub2*)&def[col].col_retlen,(ub2*)(int)def[col].col_retcode)) { oci_error(cda); return -1; } } return col; } void printHeader(sword ncols) { sword col,n,i; for(col=0; col<ncols; col++) { n=RAWWIDTH -desc[col].buflen; if(desc[col].dbtype==FLOAT_TYPE || desc[col].dbtype==INT_TYPE) { printf("%*.*s",desc[col].buflen,desc[col].buflen,desc[col].buf); printf("%*c",n,‘ ‘); }else{ printf("%*.*s",desc[col].buflen,desc[col].buflen,desc[col].buf); printf("%*c",n,‘ ‘); } } fputc(‘\n‘,stdout); for(col=0; col<ncols; col++) { n=RAWWIDTH -desc[col].buflen; for(i=desc[col].buflen; i; i--) { fputc(‘-‘,stdout); } if(desc[col].dbtype==FLOAT_TYPE || desc[col].dbtype==INT_TYPE) { printf("%*c",n,‘ ‘); }else { printf("%*c",n,‘ ‘); } } fputc(‘\n‘,stdout); } void printRaw(Cda_Def *cda,sword ncols) { sword col,n; while(1) { fputc(‘\n‘,stdout); if(ofetch(cda)) { if(cda->rc==NO_DATA_FOUND) { break; } if(cda->rc!=NULL_VALUE_RETURNED) { oci_error(cda); } } for(col=0; col<ncols; col++) { if(def[col].indp<0) { printf("%*c",desc[col].dbsize,‘ ‘); }else{ switch(desc[col].dbtype) { case FLOAT_TYPE: { n = printf("%f",def[col].flt_fuf); n = RAWWIDTH - n; if(n) { printf("%*c",n,‘ ‘); } break; } case INT_TYPE: { n = printf("%d",def[col].int_buf); n = RAWWIDTH - n; if(n) { printf("%*c",n,‘ ‘); } break; } default: { n = printf("%s",def[col].buf); n = RAWWIDTH - n; if(n) { printf("%*c",n,‘ ‘); } break; } } } } } } int main() { sword ncols; //登陆oracle if(!connect()) { exit(-1); } //打开curse if(oopen(&cda,&lda,(OraText*)0,-1,-1,(OraText*)0,-1)) { oerhms(&lda,lda.rc,(OraText*)errorMsg,sizeof(errorMsg)); printf("%s,Please try again.\n",errorMsg); exit(-1); } while(1) { stmtLevel=0; //输入sql if(getSqlStatement()) { exitOracle(0); } //分析sql if(oparse(&cda,(OraText*)sqlStatement,-1,PARSE_NO_DELAY,PARSE_V7_LNG)) { oci_error(&cda); continue; } sqlFunction = cda.ft; //绑定变量 if((ncols = bind(&cda,sqlStatement))==-1) { continue; } if(sqlFunction==FT_SELECT) { if((ncols=describeDefine(&cda)) == -1) { continue; } } //执行sql if(oexec(&cda)) { oci_error(&cda); continue; } //若是查询,则显示查询结果;否则,提示事件 if(sqlFunction==FT_SELECT) { printHeader(ncols); printRaw(&cda,ncols); }else{ if(ocom(&lda)) { oci_error(&lda); continue; } } //显示处理行数 if(sqlFunction==FT_SELECT || sqlFunction==FT_UPDATE || sqlFunction==FT_DELETE || sqlFunction==FT_INSERT) { printf("\n\n%d row%c processed.\n",cda.rpc,cda.rpc==1 ? ‘\0‘ : ‘s‘); }else{ printf("\n\nStatement processed.\n"); } } }
运行
Copyright (c) 1982, 2014, Oracle. All rights reserved. Connected to Oracle Database: Enter user-name: [email protected] Enter password: 1qaz!QAZ SQL>select * from res.res_head_imsi where hlr=‘G04‘; HLR WRITE_TYPE MANAGE_STATUS BILL_ID STANDBYFLAG NULL_FLAG IS_CONFIRM RES_CODE RES_STATUS HEADIMSI TOTAL --- ---------- ------------- ------- ----------- --------- ---------- -------- ---------- -------- ----- G04 1 0 13673526099 0 0 K09111 1 46000 1 1 row
时间: 2024-10-10 10:19:33