OCI自学浅谈

来源:互联网 发布:ug creo 编程 编辑:程序博客网 时间:2024/05/17 23:47

     在数据库了解很少的情况下,公司直接让我这个实习生用OCI连接数据库,做一个可以访问服务器数据库的程序,并且可以进行修改,删除等操作。然后开始进入紧张忙碌的状态,但是在网上找了很多信息发现这方面的文章不算太少但是很多都一样,所以资料就不多了,努力搜寻认真研读下终于把这个小程序搞定了。

    我先说一下我学习OCI的路程,先找个例子看,发现OCI只是一些API的应用,流程都是一样的,上网查那些没见过的函数,好的查找源一个是OCI常用函数——百度百科,一个是http://download.oracle.com/docs/cd/A91202_01/901_doc/appdev.901/a89857/toc.htm,这两个结合可以解决大部分问题。

   下边是OCI的基本结构,按照这个结构做就可以了,这个结构为连接数据库做准备:

          image

  首先必须初始化环境,只有在OCI的环境下那些函数才能使用,初始化环境的函数OCIEnvCreate(&env,OCI_DEFAULT,NULL,NULL,NULL,NULL,0,NULL);我用的是这个。也可以用OCIInitialize()或OICEnvInit();

  下边就开始分配句柄,在这之前首先得声明各句柄:

  OCIEnv * env;  //环境句柄
  OCIServer * ser;  //服务句柄
  OCIError * err;  //错误句柄
  OCISession * user;  //用户句柄
  OCISvcCtx * svc;  //服务上下文句柄
  OCIStmt *stmt;//句子句柄

 分配各句柄:

 OCIHandleAlloc((dvoid *)env,(dvoid **)&ser,OCI_HTYPE_SERVER,0,NULL);//分配服务器句柄(我个人理解)
 OCIHandleAlloc((dvoid *)env,(dvoid **)&err,OCI_HTYPE_ERROR,0,NULL);//分配错误句柄
 OCIHandleAlloc((dvoid *)env,(dvoid **)&svc,OCI_HTYPE_SVCCTX,0,NULL);//分配服务句柄

OCIHandleAlloc((dvoid *)env,(dvoid **)&user,OCI_HTYPE_SESSION,0,NULL);//分配用户句柄

 OCIHandleAlloc((dvoid *)env, (dvoid **)&stmt, OCI_HTYPE_STMT,0, NULL) ;//分配句子句柄(这里的句子就是要执行的PL/SQL语句)

 开始建立连接:

  if(OCIServerAttach(ser,err,(text *)"test",strlen("test"),OCI_DEFAULT)==OCI_SUCCESS)
 printf("连接成功\n");

   test是服务器主机的名字,如果OCIServerAttach执行成功也就是等于OCI_SUCCESS,就输出连接成功。

下边就是一些设置:

服务器句柄和回话句柄都要设到服务句柄中,用户名和密码都设到回话里

OCIAttrSet((dvoid *)svc,OCI_HTYPE_SVCCTX,(dvoid *)user,0,OCI_ATTR_SESSION,err);

 OCIAttrSet((dvoid *)svc,OCI_HTYPE_SVCCTX,(dvoid *)ser,0,OCI_ATTR_SERVER,err);
  OCIAttrSet((dvoid *)user,OCI_HTYPE_SESSION,(dvoid *)"epgate",strlen("epgate"),OCI_ATTR_USERNAME,err);
  OCIAttrSet((dvoid *)user,OCI_HTYPE_SESSION,(dvoid *)"zxcvbn",strlen("zxcvbn"),OCI_ATTR_PASSWORD,err);
建立会话
OCISessionBegin(svc,err,user,OCI_CRED_RDBMS,OCI_DEFAULT);
以上就是连接服务器以及建立回话,也就是和数据库接线成功,可以进行操作了,接下来就要执行SQL语句了。SQL语句可以分为好几类,具体的我也记不清,有DDL、DML、DQL等等,这些语句操作的时候可以分为三大类:1、输入型的,像CREAT、UPDATE、INSERT等   2、输出型的, 像SELECT等  3、直接操作的

  1、输入型:需要绑定变量,这些变量用于临时存储传入进来的值,也就是用户更新的数据

        定义绑定输入的句柄:OCIBind * bpara[5],有几个变量就写几,我的变量有五个

        定义要存放这些数据的变量  

      struct students
     {
      char StudentName[20];
      int En_score;
      int Ma_score;
      int Ph_score;
      int Ch_score;
     }st1;

开始将需要输入的值得位置与这些位置对应起来,用到OCIBindByPos,还可以按名字对应OCIBindByName

OCIBindByPos(stmt,&bpa1,err,1, (dvoid *)&st2.StudentName, sizeof(st2.StudentName),SQLT_CHR, (dvoid *) 0, (ub2 *)0,(ub2 *)0,(ub4) 0, (ub4 *) 0,OCI_DEFAULT);这是将   错误句柄err后边的参数1就表示第一个位置,第一个位置的变量对应好了,其他的依次对应就好

       准备SQL语句:

char * sql[255];

sprintf(sql,"%s","insert into studentscore values('关某',81,85,84,82)");

OCIStmtPrepare(stmt, err,(text *)sentence, strlen(sentence), OCI_NTV_SYNTAX, OCI_DEFAULT);

获取SQL语句(这句必须要写的,要不然找不到语句)

OCIAttrGet((dvoid *)stmt, (ub4)OCI_HTYPE_STMT, (dvoid *)&stmt_type, (ub4 *)0, (ub4)OCI_ATTR_STMT_TYPE, err);//这一句可以获取SQL语句的类型,是选择型或者非选择型,也可以设置为获取数据库的数据条数等

执行SQL语句:

OCIStmtExecute(svc,stmt,err,(ub4)1,0,NULL,NULL,OCI_DEFAULT);//执行的次数就是1-0=1

2、输出型的与输入型的类似,只是所用函数不同,见下边代码

3、直接操作的简单,将SQL语句准备好直接执行就可以了

所有需要操作的都解决了以后还需要将会话断开,释放句柄,要不然会造成内存的泄露

OCISessionEnd(svc,err,user,OCI_DEFAULT);//断开会话

OCIServerDetach(ser,err,OCI_DEFAULT);//断开数据库

OCIHandleFree((void *)env,OCI_HTYPE_ENV);//释放句柄,有这一句所有的句柄均释放了

------------------------------------------------附录:完整代码-----------------------------------------------------

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<oci.h>  char errormsg[1024];  int erroecode = 0;  OCIEnv * env;  //环境句柄  OCIServer * ser;  //服务句柄  OCIError * err;  //错误句柄  OCISession * user;  //用户句柄  OCISvcCtx * svc;  //服务上下文句柄  OCIStmt *stmt;//句子句柄  ub4 ub4recoedno=1;  struct students  {  char StudentName[20];  int En_score;  int Ma_score;  int Ph_score;  int Ch_score;  }; void execution(char * sentence);  void link_database();int main(){  link_database();//-----------------------------执行SQL语句-------------------------------------------------  //准备SQL语句  char sql[255];   //申请绑定字段的句柄   OCIBind * bpa1=NULL;   OCIBind * bpa2=NULL;   OCIBind * bpa3=NULL;   OCIBind * bpa4=NULL;   OCIBind * bpa5=NULL;   OCIDefine * para[5];   struct students st1,st2;   //将名字结尾赋以结束符   memset(st1.StudentName,'\0',sizeof(st1.StudentName));//给字符串结尾加结束符   sprintf((char *)sql,"%s","SELECT * FROM stu_score");   OCIDefineByPos(stmt, ¶[0], err, 1, (dvoid *)&st1.StudentName, sizeof(st1.StudentName), SQLT_STR,NULL,NULL, NULL, OCI_DEFAULT);   OCIDefineByPos(stmt, ¶[1], err, 2, (dvoid *)&st1.En_score, sizeof(int), SQLT_INT,NULL, NULL, NULL, OCI_DEFAULT);   OCIDefineByPos(stmt, ¶[2], err, 3, (dvoid *)&st1.Ma_score, sizeof(int), SQLT_INT,NULL,NULL,NULL, OCI_DEFAULT);   OCIDefineByPos(stmt, ¶[3], err, 4, (dvoid *)&st1.Ph_score, sizeof(int), SQLT_INT,NULL,NULL, NULL, OCI_DEFAULT);   OCIDefineByPos(stmt, ¶[4], err, 5, (dvoid *)&st1.Ch_score, sizeof(int), SQLT_INT,NULL,NULL, NULL, OCI_DEFAULT);    execution(sql);   do   {      printf("%s   %d   %d   %d   %d\n",st1.StudentName,st1.En_score,st1.Ma_score,st1.Ph_score,st1.Ch_score);   }  while(OCIStmtFetch(stmt, err, 1, OCI_FETCH_NEXT, OCI_DEFAULT) != OCI_NO_DATA);//提取数据库中的数据直到完成为止  sprintf(sql,"%s","delete from stu_score where 姓名='段仁光'");  execution(sql);  sprintf(sql,"%s","insert into stu_score values('蒋天国',98,87,84,51)");  OCIBindByPos(stmt,&bpa1,err,1, (dvoid *)&st2.StudentName, sizeof(st2.StudentName),SQLT_CHR, (dvoid *) 0, (ub2 *)0,(ub2 *)0,(ub4) 0, (ub4 *) 0,OCI_DEFAULT);  OCIBindByPos(stmt,&bpa2,err,2, (dvoid *)&st2.En_score, sizeof(int),SQLT_INT, (dvoid *) 0, (ub2 *)0,(ub2 *)0,(ub4) 0, (ub4 *) 0,OCI_DEFAULT);  OCIBindByPos(stmt,&bpa3,err,3, (dvoid *)&st2.Ma_score, sizeof(int),SQLT_INT, (dvoid *) 0, (ub2 *)0,(ub2 *)0,(ub4) 0, (ub4 *) 0,OCI_DEFAULT);  OCIBindByPos(stmt,&bpa4,err,4, (dvoid *)&st2.Ph_score, sizeof(int),SQLT_INT, (dvoid *) 0, (ub2 *)0,(ub2 *)0,(ub4) 0, (ub4 *) 0,OCI_DEFAULT);  OCIBindByPos(stmt,&bpa5,err,5, (dvoid *)&st2.Ch_score, sizeof(int),SQLT_INT, (dvoid *) 0, (ub2 *)0,(ub2 *)0,(ub4) 0, (ub4 *) 0,OCI_DEFAULT);  execution(sql);  sprintf(sql,"%s","update stu_score set 化学=99 where 姓名='何源'");  OCIBindByPos(stmt,&bpa5,err,5, (dvoid *)&st2.Ch_score, sizeof(int),SQLT_INT, (dvoid *) 0, (ub2 *)0,(ub2 *)0,(ub4) 0, (ub4 *) 0,OCI_DEFAULT);  execution(sql);  OCISessionEnd(svc,err,user,OCI_DEFAULT);  //断开数据库  OCIServerDetach(ser,err,OCI_DEFAULT);  //释放所有句柄,当释放环境父句柄,它所有子句柄会自动释放  OCIHandleFree((void *)env,OCI_HTYPE_ENV);  return 0;}//-------------------------------------------定义函数-------------------------------------------//连接数据库,建立回话void link_database(){  OCIEnvCreate(&env,OCI_DEFAULT,NULL,NULL,NULL,NULL,0,NULL);  OCIHandleAlloc((dvoid *)env,(dvoid **)&ser,OCI_HTYPE_SERVER,0,NULL);  OCIHandleAlloc((dvoid *)env,(dvoid **)&err,OCI_HTYPE_ERROR,0,NULL);  if(OCIServerAttach(ser,err,(text *)"test",strlen("test"),OCI_DEFAULT)==OCI_SUCCESS)      printf("连接成功\n");  else  {     if (OCIErrorGet(err,ub4recoedno++,NULL,&erroecode,(oratext*)errormsg,sizeof(errormsg),OCI_HTYPE_ERROR)==OCI_SUCCESS)       {            printf("errorcode:%d/nerrormsg:%s",erroecode,errormsg);        }        printf("连接失败\n");        exit(0);  }  OCIHandleAlloc((dvoid *)env,(dvoid **)&svc,OCI_HTYPE_SVCCTX,0,NULL);  OCIAttrSet((dvoid *)svc,OCI_HTYPE_SVCCTX,(dvoid *)ser,0,OCI_ATTR_SERVER,err);  OCIHandleAlloc((dvoid *)env,(dvoid **)&user,OCI_HTYPE_SESSION,0,NULL);  OCIAttrSet((dvoid *)user,OCI_HTYPE_SESSION,(dvoid *)"epgate",strlen("epgate"),OCI_ATTR_USERNAME,err);  OCIAttrSet((dvoid *)user,OCI_HTYPE_SESSION,(dvoid *)"zxcvbn",strlen("zxcvbn"),OCI_ATTR_PASSWORD,err);  if(OCISessionBegin(svc,err,user,OCI_CRED_RDBMS,OCI_DEFAULT)==OCI_SUCCESS)      printf("成功!\n");  else  {    printf("失败!\n");    exit(0);  }  OCIAttrSet((dvoid *)svc,OCI_HTYPE_SVCCTX,(dvoid *)user,0,OCI_ATTR_SESSION,err);  //分配句子句柄  if (OCIHandleAlloc((dvoid *)env, (dvoid **)&stmt, OCI_HTYPE_STMT,0, NULL) != OCI_SUCCESS)  {    printf("分配句子句柄失败!\n");           exit(0);  }}//执行SQL语句的函数void execution(char * sentence){  ub2 stmt_type; if (OCIStmtPrepare(stmt, err,(text *)sentence, strlen(sentence), OCI_NTV_SYNTAX, OCI_DEFAULT) != OCI_SUCCESS)   { if (OCIErrorGet(err,ub4recoedno++,NULL,&erroecode,(oratext*)errormsg,sizeof(errormsg),OCI_HTYPE_ERROR)==OCI_SUCCESS)       {            printf("errorcode:%d/nerrormsg:%s",erroecode,errormsg);        }   }  OCIAttrGet((dvoid *)stmt, (ub4)OCI_HTYPE_STMT, (dvoid *)&stmt_type, (ub4 *)0, (ub4)OCI_ATTR_STMT_TYPE, err);  if ( OCIStmtExecute(svc,stmt,err,(ub4)1,0,NULL,NULL,OCI_DEFAULT) != OCI_SUCCESS)   {      if (OCIErrorGet(err,ub4recoedno++,NULL,&erroecode,(oratext*)errormsg,sizeof(errormsg),OCI_HTYPE_ERROR)==OCI_SUCCESS)       {            printf("errorcode:%d/nerrormsg:%s",erroecode,errormsg);        }   }}




0 0
原创粉丝点击