OCI自学浅谈

     在数据库了解很少的情况下,公司直接让我这个实习生用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
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
oci函数的详细介绍 和应用实例 OCI 连接过程比较复杂,除了分配设置各个基本句柄外,还要明确彼此之间的联系,大致流程如下: 创建环境句柄: OCIEnvCreate(&envhp;, …); 创建一个指定环境的错误句柄: OCIHandleAlloc((dvoid *)envhp, (dvoid **)&errhp;,…); 创建一个指定环境的服务器句柄: OCIHandleAlloc((dvoid *)envhp, (dvoid **)&servhp;,…); 建立到数据源的访问路径 : OCIServerAttach(servhpp, errhpp,…); 创建一个指定环境的服务上下文句柄: (void) OCIHandleAlloc((dvoid *)envhpp,…); 为指定的句柄及描述符设置特定的属性: (void) OCIAttrSet((dvoid *)svchpp,…); 创建一个指定环境的用户连接句柄: (void) OCIHandleAlloc((dvoid *)envhpp,…); 为用户连接句柄设置登录名及密码: (void) OCIAttrSet((dvoid *)usrhpp,…); 认证用户建立一个会话连接: OCISessionBegin(svchpp, errhpp,…); 创建一个句子句柄: OCIHandleAlloc((dvoid *)envhpp,…);s 准备 SQL 语句: OCIStmtPrepare(stmthpp, errhpp,…); 绑定输入变量: OCIBindByPos(stmtp &hBind;, errhp,…); 绑定输出变量: OCIDefineByPos(stmthpp, &bhp1;, errhpp,…); 获得 SQL 语句类型: OCIAttrGet ((dvoid *)stmthpp, (ub4)OCI_HTYPE_STMT,…); 执行 SQL 语句: OCIStmtExecute(svchpp, stmthpp,…); 释放一个会话: OCISessionEnd(); 删除到数据源的访问 : OCIServerDetach(servhpp, errhpp, OCI_DEFAULT); 释放句柄: OCIHandleFree((dvoid *) stmthpp, OCI_HTYPE_STMT);

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值