Oracle occi 绑定变量提高数据插入速度

转载自:http://fengqing888.blog.163.com/blog/static/3301141620111018017212/

occi是oracle提供的一套对oci封装好的类库,前段时间我抽空看了看相关的文档,本来是想好好的研究研究的,不过因为一直有别的事情要做,所以就没有时间看下去了。论坛上用PRO*C的人多一些。用OCI的好像很少,而且一般问都问些简单的问题,描述的也不太清楚,让人都无从回答。个人觉得OCI的使用率和它作为ORACLE下功能最强的编程接口的地位还是不太符合的。这也许因为它的函数很多而且参数定义非常乱(void ** var)到处都可以看见。不过occi在这方面做了很大的改进,个人觉得还是比较容易上手的,因为它的设计参考了JDBC标准的设计。很多写法基本都是一样的。发这个帖子只是希望有兴趣的人可以一起探讨和学习。

  我写了两个简单的小程序,从这两个程序中我们可以看见一些OCCI基本的用法。
环境:win2000pro+sp2
         oracle9.0.1
         vc6+sp5
  a.select 记录
#include "stdio.h"
#include <occi.h>
#include <string>
using namespace oracle:cci;
using namespace std;
int main()
{
  try
  {
  //初始化环境
   Environment *env = Environment::createEnvironment(Environment::THREADED_MUTEXED);
  //创建连接
   Connection  *conn = env->createConnection("ems1","ems1","emsdb1";
  //创建语句对象
   Statement *stmt = conn->createStatement("SELECT * FROM occitest";
    ResultSet *rs = stmt->executeQuery();
    //rs->setErrorOnNull(3,true);
   //逐行读出记录
    while(rs->next())
    {         
             printf("The Record is %d,%d,%s.\n",rs->getInt(1),rs->getInt(2),rs->getString(3).c_str());
    }       
   
    stmt->closeResultSet(rs);   
   conn->terminateStatement(stmt);   
   env->terminateConnection(conn);
   Environment::terminateEnvironment(env);
   
  }
  catch(SQLException &e)
  {
    printf(e.what());
  }
  return 0;
}
以我个人的意见来看,这里是OCCI比较方便的地方,以往的oracle的C/C++接口对于动态的语句的支持都是有严格定义(4种动态语句),而其中最复杂的就是列不固定的选择语句,写第4种动态语句是比较复杂的。而OCCI中对这种语句的支持是很容易就可以实现,基本上做到了不需要知道太多的细节。
2.DML操作
#include "stdio.h"
#include <occi.h>
#include <string>
using namespace oracle:cci;
using namespace std;
const int ArraySize=10000;
int main()
{
  try
  {
   printf("Init the Env&Con....\n";
   Environment *env = Environment::createEnvironment(Environment::THREADED_MUTEXED);
   Connection  *conn = env->createConnection("ems1","ems1","emsdb1";
   Statement *stmt = conn->createStatement("INSERT INTO occitest VALUES (:fld1,:fld2,:fld3)";
   printf("Init ok.\n";
   int  iFld1[ArraySize],iFld2[ArraySize];
   char sFld3[ArraySize][20];
   ub2  fld1Len[ArraySize],fld2Len[ArraySize],fld3Len[ArraySize];
   for(int i=0;i<ArraySize;i++)
   {
    iFld1=i+1;
    iFld2=i*10+1;
        if(i==0)
    strcpy(sFld3,"Sky Insert Test!";
        else
    strcpy(sFld3,"Sky Insert Test1!";
        fld1Len=4;
    fld2Len=4;
        fld3Len=sizeof(sFld3)+1;
   }
   
   printf("Begin\n";
   stmt->setDataBuffer(1,iFld1,OCCIINT,sizeof(iFld1[0]),fld1Len);
   stmt->setDataBuffer(2,iFld2,OCCIINT,sizeof(iFld2[0]),fld2Len);
   stmt->setDataBuffer(3,sFld3,OCCI_SQLT_STR,sizeof(sFld3[0]),fld3Len);
   stmt->executeArrayUpdate(ArraySize);
   printf("End\n";
   conn->commit();
   conn->terminateStatement(stmt);   
   env->terminateConnection(conn);
   Environment::terminateEnvironment(env);
   
  }
  catch(SQLException &e)
  {
    printf(e.what());
  }
  return 0;
}
具体的细节就不多说了,我想谈的是一点就是.INSERT语句的格式,很多人在用ADO或者JDBC的时候都很喜欢一个办法就是动态生成一条SQL语句然后在执行,这是个很方便的方法,不过凡事有利就有弊,这个方法的坏处硬编码,如果应用中大量使用就会在SQL语句的解析上花费很多时间,尤其在做批量操作的时候,如果采用这种模式简直就是灾难。所以INSERT 语句写成了"INSERT INTO occitest VALUES (:fld1,:fld2,:fld3)",留下3个占位符。后面是把参数数组传进去,然后一次插入。总的来说我觉得简单的代码还是做了不少事情的。
  一次插入10000条记录基本上花了1-2秒就做完了,还是很快的。不过我没有测100000花多长时间------------------------因为内存溢出了。这个帖子写的很简单,希望是抛砖引玉吧。

你可能感兴趣的:(oracle,sql,编程,jdbc,文档,insert)