OcciWrapper使用指南(高性能Oracle访问组件)

occiwrapper使用指南

  occiwrapper是一个开源的、跨平台的Oracle访问组件, 方便C++开发者们灵活地操作oracle数据库。为了方便使用,组件中的接口形式参考的POCO库的使用方式。occiwrapper采用如下的形式执行SQL语句:

1     occiwrapper::Session s = SessionInstance( connection );
2     s << "truncate table TBL_TEST ", now;

  通过session对象维护一个到oracle的会话。类似于流的操作方式,向session中传入SQL语句,并执行。

  在oracle参数绑定方面,Occiwrapper可以直接将C++变量绑定到oracle参数中,在以后的文档说明中详细介绍。

1   occiwrapper::Session s = SessionInstance( info );
2   struct tm tm_value;
3   s << "insert into TBL_TEST( date_value ) values ( :1 )", use( tm_value ), now;

  同时,对于vector等容量变量,可以灵活地直接绑定到oracle的绑定变量上,同时也可以灵活的将select语句返回的结果绑定到容器中,而且对于使用者来讲,并不用关心类型的对应关系。为了提高存取的性能,写入和读取都采入批量操作的方式,同时采用智能指针自动管理内存缓冲池,最大限度地解放了oracle开发者。

1   occiwrapper::Session s = SessionInstance( info );
2   vector< int > vec1;
3   s << "select A from tbl_test2 t", into( vec1 ), now;

  组件中使用的很多技术都是在工作中一些经验的积累与总结,由于自己认识oracle不够深刻,对C++的理解也可能不够深入,希望大家多多讨论。对于大家发现的Bug,我也会尽快修改,同时热情欢迎大家积极参与库的修改。

  源代码地址:https://github.com/CUCmehp/occiwrapper

1、下载和安装

1.1 第三方组件依赖

  本组件依赖oracle公司的occiOracle C++ Calling Interface动态库支持。连接不同的oracle版本,须要选择不同的occi版本。

  关于occi的详细介绍,请参见oracle公司官方文档

1.2 开发环境

  在Windows系统下,可以通过Visual Studio 2008 SP1或者Visual Studio 2010进行编译。

  在linux系统下,可以通过g++编译器进行编译。

1.3      运行环境

  本组件可跨平台支持WindowsLinux操作系统。

1.4 数据库环境

  test工程中所有测试用例用到的数据库表、存储过程、函数,都可以通过db文件夹中的脚本创建。

  方法:

    (1)通过具有system权限的用户执行脚本create_user.sql

    (2)使用用户occiwapper(密码为occiwrapper)执行occiwrapper.sql

  注:所有测试用例中均使用occiwrapper作为oracle的用户名。

1.5 测试

  所有的测试代码存放在源码的test目录下,在windowslinux(Suse 10, Suse 11openSuse12, redhat 6企业版, Centos 6 )下进行了相关的测试。数据库连接信息的配置文件放在db_config.ini中。

在程序在oracle 11gR212cR1oracle 12.1对应的occi版本下进行了测试。

2、 编译说明

2.1 Windows

  • 使用Visual Studio 2008 SP1工具

  使用Visual Studio 2008直接打开工程occi_wrapper_vs2008.sln,选择DebugRelease进行编译。

  注:要求vs2008 sp1以上,是由于occiwrapper中使用了tr1库,而vs2008SP1版本以上,才开始支持tr1库。

  • Visual Studio 2010

  使用Visual Studio 2010直接打开工程occi_wrapper_vs2010.sln,选择DebugRelease进行编译。

  说明:源码中include/occi_11g目录下,存放着oracle 11.2.0.2 64位数据库对应的头文件,在lib_vs2008lib_vs2010目录下,存放着11.2.0.2版数据库对应的lib库文件。在bin_vs2008bin_vs2010目录下,存放着对应的dll文件。

若需要使用其它版本的occi库版本,则将上述文件替换为需要使用的occi库文件。

2.2 Linux

  linux下使用,需要先下载oracle occi库对应的头文件和动态库文件。在oracle数据库的OCI/lib目录下,通常可以找到这些文件。若未安装oracle数据库,则可以从官网上下载:http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html

  头文件对应文件包为:instantclient-sdk-linux.x64-*.*.*.*.*.zip

  库文件对应文件包为:instantclient-basic-linux.x64-*.*.*.*.*.zip

  只需要选择需要的oracle版本,下载对就的文件就可以,然后解压,记得将so文件放在系统运行时扫描的目录,如/usr/local/lib/usr/lib等目录,也可以将so的目录添加到/etc/ld.so.conf配置文件中。

  下载occiwrapper.tar.gz包,并在linux下解压,执行以下命令:

    tar -zxvf occiwrapper.tar.gz

  genConfigure.sh生成可执行的权限,使用以下命令:

    chmod +x genConfigure.sh

  运行此命令,运行的格式如下:

    ./genConfigure.sh --occi-include=occi_include_path_value --occi-lib=occi_lib_path_value

  其中occi_include_path_value对应着occi头文件的目录,occi_lib_path_value对应着occi库文件的目录,比如头文件放在/u01/install/oracle_client/instantclient_12_1/sdk/include/,库文件存放在/u01/install/oracle_client/instantclient_12_1/,则执行的命令为:

    ./genConfigure.sh --occi-include=/u01/install/oracle_client/instantclient_12_1/sdk/include/ --occi-lib=/u01/install/oracle_client/instantclient_12_1/

  成功执行后,目录下会生成configure文件,然后执行./configure,默认安装在/usr/local目录下,也可以自己指定安装的目录,执行:

    ./configure --prefix=/usr/local/occiwrapper

  编译程序,执行make命令。

    make

  最后进行安装,执行

    make install

  执行成功后,在/usr/local/occiwrapper目录下,存放着生成的includelib文件,测试文件存放在test目录下,test目录下的db_config.ini为测试库对应的配置信息。要执行test程序,需先在oracle数据库中执行db文件夹下的脚本。

3.   使用指南

  本部分主要介绍调用occiwrapper组件的方法,包括以下部分:

  • oracle连接;
  • 创建一个会话;
  • 执行DDL语句;
  • 执行简单插入;
  • 使用绑定变量插入;
  • 执行update操作;
  • CommitRollback;
  • 执行存储过程;
  • 调用函数;
  • 执行select语句并保存结果;
  • 处理oracle中的日期类型
  • 关于NULL值的处理;

3.1 Oracle连接

  occiwrapper组件通过类occiwrapper::ConnectionInfo结构来保存oracle连接信息。

1     occiwrapper::ConnectionInfo info;
2     info.ip = "127.0.0.1";
3     info.port = 1521
4     info.username = "occiwrapper";
5     info.password = "occiwrapper";
6     info.sid = "orcl";

  要建立一个oracle连接,需要先申请一个oracleEnvironment变量,函数内部通过调用OCCIcreateEnvironment函数创建Environment

    oracle::occi::Environment::createEnvironment( oracle::occi::Environment::THREADED_MUTEXED );

  参数取值默认使用了THREADED_MUTEXED,关于OCCI创建Environment的参数有如下定义:

  DEFAULT: not thread safe, not in object mode;

  THREADED_MUTEXED: thread safe, mutexed internally by OCCI;

  THREADED_UN-MUTEXED: thread safe, client responsible for mutexing;

  OBJECT: uses object features

  occiwrapper组件通过封装Environment,将Environment的创建与销毁同发者隔离起来,开发者不需要关心何时去关闭Environment

  通过类Connection可以方便的管理oracle的数据库连接,该类屏封了默认构造函数和拷贝构造函数。只能通过静态方法GetConnection得到一个数据库连接。

以下示例完整的给出了,如何创建一个oracle连接。

1     shared_ptr< occiwrapper::Environment > pEnv = occiwrapper::Environment::CreateEnvironment();
2     assert( pEnv->CreateEnvironment() != NULL );
3     occiwrapper::ConnectionInfo info;
4     info.ip = "127.0.0.1";
5     info.username = "occiwrapper";
6     info.password = "occiwrapper";
7     info.sid = "orcl";
8     assert( occiwrapper::Connection::GetConnection( shared_ptr< occiwrapper::Environment >( pEnv ), info ) != NULL );

  上述代码中,shared_ptrC++ 0x标准中提出的tr1库定义的智能指针,关于C++ 0xtr1库,在此不做介绍,大家可以参见维基百科。

  occiwrapper使用连接池对oracle数据库连接进行管理,对于相同的数据库连接进行复用;同时,通过连接池,对oracle连接进行管理,以下代码给出了如何使用occiwrapper的连接池,取得oracle连接。

 1      occiwrapper::ConnectionInfo info;
 2      occiwrapper::ConnectionPool connPool;
 3      info.ip = "127.0.0.1";
 4      info.username = "occiwrapper";
 5      info.password = "occiwrapper";
 6      info.sid = "orcl";
 7      shared_ptr< occiwrapper::Connection > p =  connPool.GetConnection( info );
 8      assert( p != NULL);
 9      assert( p->GetValidity() == occiwrapper::VALID );
10      shared_ptr< occiwrapper::Connection > other = connPool.GetConnection( info );
11      assert( connPool.GetConnMapSize() == 1 );

3.2 创建一个会话

  Session类用来管理客户端与oracle服务器之间的会话连接。通过会话连接,客户端可以灵活的创建出若干Statement来执行SQL命令。

  occiwrapper通过类SessionFactory来创建session会话,SessionFactory是一个以单件形式存在的工厂类,可以动态的创建出Session对象。同时,SessionFactory中内置了一个连接池对象管理oracle连接。关于连接池对象,可以参考3.2节创建一个会话中的介绍。

  以下代码给出了如何使用SessionFactory创建一个Session对象。

1     occiwrapper::ConnectionInfo info;
2     occiwrapper::Session s = occiwrapper::SessionFactory::Instance().Create( info, false );

  为了方使创建Session,也可以使用宏定义。

1     occiwrapper::Session s = SessionInstance( info );

3.3      执行DDL语句

  利用Session对象可以方便地执行DDL命令,如下示例演示如何创建一张表,再将它清空,最后删除该表。

1     occiwrapper::ConnectionInfo info( "127.0.0.1", 1521, "occiwrapper", "occiwrapper", "orcl" );
2     occiwrapper::Session s = SessionInstance( info );
3     bool bRet = false;
4     string strErrMsg = "";
5     s << "create table tbl_test( x int )", now, bRet, strErrMsg;
6     s << "truncate table tbl_test", now, bRet, strErrMsg;
7     s << "drop table tbl_test", now, bRet, strErrMsg;

3.4 执行简单插入

  对于简单的insert操作,指不使用绑定变量的insert操作。如何利用occiwrapper进行绑定变量插入,将在下两节中进行介绍。本节只介绍执行最简单的SQL语句。

  例如,对于一张已知的表TBL_TEST1,该表只含有一个整数字段X。以下的代码数字10004插入到该表中。

1   occiwrapper::ConnectionInfo info( "127.0.0.1", 1521, "occiwrapper", "occiwrapper", "orcl" );
2   occiwrapper::Session s = SessionInstance( info );
3   bool bRet = false;
4   string strErrMsg = "";
5   s << "insert into tbl_test1( x ) values ( 10004 )", now, bRet, strErrMsg;

  Session执行的结果会被保存bRet中,若执行出错,在strErrMsg中输出出错原因。

3.5      使用绑定变量进行插入

  绑定变量是oracle编程中一个重要的使用技巧。通过绑定变量的使用,能够显著的提高多次执行同一条SQL语句的性能。在此不在赘述。

  下面分两类进行介绍,包括绑定简单变量和绑定容器。

  • 绑定简单变量

  绑定简单变量,将简单数据类型变量,如int, float, double, string, struct tm等绑定到oracle的绑定变量上。

  下表给出了occiwrapper支持的绑定类型

1 Windowsocciwrapper支持的绑定类型定义


occiwrapper 类型定义


操作系统类型


Int8


signed char


UInt8


unsigned char


Int16


signed short


UInt16


unsigned short


Int32


int


UInt32


unsigned int


Int64


signed __int64


UInt64


unsigned __int64


float


float


double


double


struct tm


struct tm


std::string


std::string

2 Linux下occiwrapper支持的绑定类型定义


occiwrapper 类型定义


操作系统类型


Int8


signed char


UInt8


unsigned char


Int16


signed short


UInt16


unsigned short


Int32


int


UInt32


unsigned int


Int64


signed long


UInt64


signed long long


float


float


double


double


struct tm


struct tm


std::string


std::string

  occiwrapper通过use关键字进行简单变量绑定。如执行use(1),将数字1绑定到对应的绑定变量上; 执行use(“hello world”)将字符串hello world绑定到对应的绑定变量上。

 1     occiwrapper::ConnectionInfo info( "127.0.0.1", 1521, "occiwrapper", "occiwrapper", "orcl" );
 2     occiwrapper::Session s = SessionInstance( info );
 3     bool bRet = false;
 4     string strErrMsg = "";
 5     s << "insert into tbl_test1( x ) values ( :1 )", use( 2 ), now, result, err_msg;
 6     cout << "result: " << result << endl << "error message: " << err_msg << endl;
 7     assert( result );
 8     s << "insert into test_string( id, string_val ) values( :1, :2 )", use( 2 ), use( "CUCmehp" ), now, result, err_msg;
 9     cout << "result: " << result << endl << "error message: " << err_msg << endl;
10     assert( result );
11     s << "insert into test_number( id, number_value ) values( :1, :2 )", use( 1 ), use( 3.5 ), now, result, err_msg;
12     cout << "result: " << result << endl << "error message: " << err_msg << endl;
13     assert( result );

对于同一个Session也可以多次进行绑定,进行复用,以下代码向表TBL_TEST1中插入09

 1     occiwrapper::ConnectionInfo info( "127.0.0.1", 1521, "occiwrapper", "occiwrapper", "orcl" );
 2     occiwrapper::Session s = SessionInstance( info );
 3     bool bRet;
 4     string strErrMsg;
 5     s << "truncate table tbl_test1", now;
 6     occiwrapper::Statement stmt = s << "insert into tbl_test1( x ) values( :1 )";
 7     for( int i = 0; i < 10; ++ i )
 8     {
 9               stmt, use( i ), now, bRet, strErrMsg;
10               assert( bRet );
11     }
  • 绑定容器

  绑定容器是指把表中的若干列与一个或多个容器(1.0.0版本仅支持vector容器)相绑定。

  如下图所示,一个表有ABC三列,可以将列A的数据与变量vector<A>进行绑定,将列B、列C的数据绑定到vector< tuple< B, C> >变量中,tuple为元组类型,其定义可以参见C++ 0x标准,定义在库tr1中。

  利用occiwrapperbatched_use关键字可以灵活的实现上述绑定,以下示例给出了将数组{20,21,22,23,24}所生成的vector,批量插入到表TBL_TEST1中。

1     occiwrapper::ConnectionInfo info( "127.0.0.1", 1521, "occiwrapper", "occiwrapper", "orcl" );
2     occiwrapper::Session s = SessionInstance( info );
3     bool bRet;
4     string strErrMsg;
5     int a[5] = { 20, 21, 22, 23, 24 };
6     vector< int > vec( a, a + 5 );
7     s << "insert into tbl_test1( x ) values ( :1 )", batched_use( vec ), now, bRet, strErrMsg;
8     assert(bRet);

  以下示例给出了如何绑定到两个vector或者一个vector<tuple>结构中。表TEST_STRING中含有两个字段IDSTRING_VAL,分别为integervarchar2类型。示例中,首先将一个vector<int>变量和vector<string>变量绑定到这两列上,进行插入操作。然后,将一个vector< tuple<int,string> >变量绑定到这两列上。

 1     occiwrapper::ConnectionInfo info( "127.0.0.1", 1521, "occiwrapper", "occiwrapper", "orcl" );
 2     occiwrapper::Session s = SessionInstance( info );
 3     bool bRet;
 4     string strErrMsg;
 5     int a[5] = { 20, 21, 22, 23, 24 };
 6     vector< int > vec( a, a + 5 );
 7     string strArray[5] = { "message1", "message2", "message3", "message4", "message5" };
 8     vector< string > vecStr( strArray, strArray + 5 );
 9     s << "insert into test_string( id, string_val ) values ( :1, :2 )", batched_use( vec ), batched_use( vecStr ), now, bRet, strErrMsg;
10     assert( bRet );
11     s << "truncate table test_string", now, bRet;
12     assert( bRet );
13     vector< tuple< int, string > > vecTuple;
14     for( size_t i = 0; i < 5; ++ i )
15     {
16               vecTuple.push_back( make_tuple( vec[ i ], vecStr[ i ] ) );
17     }
18     s << "insert into test_string( id, string_val ) values ( :1, :2 )", batched_use( vecTuple ), now, bRet, strErrMsg;
19     assert( bRet );

3.6 执行update操作

  执行update操作的方式,跟执行DDLselect语句的方式基本相同,同样可以使用绑定变量。以下给出了简单的例子。

1     occiwrapper::ConnectionInfo info( "127.0.0.1", 1521, "occiwrapper", "occiwrapper", "orcl" );
2     occiwrapper::Session s = SessionInstance( info );
3     bool bRet = false;
4     string strErrMsg = "";
5     s << "truncate table tbl_test1", now, bRet, strErrMsg;
6     s << "insert into tbl_test1( x ) values ( 10004 )", now, bRet, strErrMsg;
7     s << "update tbl_test1 set x = :1 where x = 10004", use( 10005 ), now, bRet, strErrMsg;

  示例代码先向表TBL_TEST1中的X字段插入数值10004,然后将数值修改为10005

3.7  CommitRollback

  Occiwrapper支持两种形式的commit操作。在创建Session时,可以指定Commit的类型,isAutoCommit参数为true,则表示每次操作后,自动进行commit,否则需要手工commit或者rollback,操作才能生效。以下代码给出了示例。

 1     occiwrapper::Session s = occiwrapper::SessionFactory::Instance().Create( info, false );
 2     s << "truncate table tbl_test1", now;
 3     s.Commit();
 4     bool bRet = false;
 5     string strErrMsg = "";
 6     s << "insert into tbl_test1( x ) values ( 10005 )", now, bRet, strErrMsg;
 7     s.Rollback();
 8     occiwrapper::Statement stmt2 = ( s << "insert into tbl_test1( x ) values ( 10005 )" );
 9     for ( int i = 0; i < 2; ++i)
10     {
11             stmt2.execute();
12     }
13     s.Commit();

  首先创建一个不会自动提交的Session对象,然后向表中插入数值10005,但并不提交,反而撤销。此时,用PL/SQL工具查看该表,发现表为空。连续执行两次insert操作后,提交。此时,表中有两条记录。

3.8 执行存储过程

  对于oracle存储过程,有输入参数与输出参数之分,输入参数是向oracle中传入的参数,而输出参数是从oracle中传出的参数。在使用use关键字是,附加PAR_IN指定参数为输入参数,附加PAR_OUT指定参数为输出参数。

  在下面的例子中,存储过程p_test_procedure含有两个参数,第一个参数为int类型,第二个参数为varchar2,函数实现了将int参数转化为string后,由参数2输出。

  下面的代码块给出了上述过程。

1     occiwrapper::ConnectionInfo info( "127.0.0.1", 1521, "occiwrapper", "occiwrapper", "orcl" );
2     occiwrapper::Session s = SessionInstance( info );
3     bool bRet;
4     string strErrMsg;
5     int nParIn = 1000;
6     string strParOut = "";
7     s << "begin p_test_procedure( :1,:2 ); end;", use( nParIn, occiwrapper::PAR_IN ), use( strParOut, occiwrapper::PAR_OUT ), now, bRet, strErrMsg;
8     assert( bRet );
9     assert( strParOut == "1000" );

3.9 调用函数

  调用函数的方法与调用存储过程类似,只不过函数有返回值,类型为输出类型。

 1     occiwrapper::ConnectionInfo info( "127.0.0.1", 1521, "occiwrapper", "occiwrapper", "orcl" );
 2     occiwrapper::Session s = SessionInstance( info );
 3     bool bRet;
 4     string strErrMsg = “”;
 5     int a = 0;
 6     s << "begin :1 := f_ins_tbl_test1( :2 ); end;", use( a, occiwrapper::PAR_OUT ), use( 2, occiwrapper::PAR_IN ) , now, bRet, strErrMsg;
 7     assert( bRet );
 8     int b;
 9     s << "begin :1 := f_test2( :2, :3 ); end;", use( a, occiwrapper::PAR_OUT ), use( 2 ), use( b, occiwrapper::PAR_OUT ), now, bRet, strErrMsg;
10     assert( bRet );

3.10 执行select语句并保存结果

  select操作是SQL操作中最常见的操作之一,将oracle中的数据取到内存中。occiwrapper通过关键字into实现将数据库中的一个字段绑定到一个容器中。

1     vector< string > vStr;
2     vector< struct tm > vDate;
3     vector< occiwrapper::Int32 > vInt;
4     vector< float > vFloat;
5     vector< double > vDouble;
6     s << "select string_value, date_value, int_value, float_value, number_value from test_batched_table", into( vStr ), into( vDate ), into( vInt ), into( vFloat ), into( vDouble ), now, bRet, strErrMsg;
7     assert( bRet );

  上述代码段将表tbl_batched_table中的数据读取,并存到5组vector变量中。

  occiwrapper内部采用了批量读取的方式,提高了读取的性能,同时内部自动管理批量绑定时所需要内存空间。

  当表中数据量比较大,只取若干条数据时,可以使用Limit关键字。

  下列代码段给出了示例:

1     vector< int > vec1;
2     vector< int > vec2;
3     // test limit select
4     s << "select * from tbl_test2 t", into( vec1 ), into( vec2 ), occiwrapper::Limit( 3 ), now;

  occiwrapper在读取时,并没有提供游标的操作(考虑到游标会影响对于底层的封装性),直接将内存中的容器对象(vector)与oracle的数据表进行了绑定。因此,当数据表中的数据量很大时,vector的插入受限于内存,故本组件更适应单表数据量在百万条以下的应用场景。当然,开发者为了防止插入时vector出错内存用尽,如将一个1亿条记录的数据,分100次插入到100Wvector容量中,每次调用批量入库,这样做也是能够成功的。然而,由于没有提供游标相关的操作,该表无法将1亿条记录一次绑定到一组vector中(会std bad allocate异常),从而形成了无法处理的窘境。因此,本组件更适合单表数据量在百万条以下规模的应用。

3.11 处理oracle中的日期类型

  为了处理oracle中的Date类型,occiwrapper对外处理的类型为struct tm类型,即occiwrapper插入和读取的类型都采用struct tm类型。

  示例代码中,给出了如何向表中插入当前时间,并如何将当向时间从oracle数据库中读到一个vector数组中。

 1     occiwrapper::ConnectionInfo info( "127.0.0.1", 1521, "occiwrapper", "occiwrapper", "orcl" );
 2     occiwrapper::Session s = SessionInstance( info );
 3     bool bRet;
 4     string strErrMsg;
 5     struct tm tmValue;
 6     time_t nowTime = time( NULL );
 7     localtime_r( &nowTime, &tmValue);
 8     s << "truncate table test_date", now, bRet, strErrMsg;
 9     s << "insert into test_date( date_val ) values ( :1 )", use( tmValue ), now, bRet;
10     vector< struct tm > vTmDb;
11     s << "select date_val from test_date", into( vTmDb ), now, bRet, strErrMsg;

3.12 关于NULL值的处理

  当数据库表中取出空值时,occiwrapper在向容器中插入时,用默认值进行处理。下表给出了各种类型的默认值。


occiwrapper 类型定义


默认值


Int8


0


UInt8


0


Int16


0


UInt16


0


Int32


0


UInt32


0


Int64


0


UInt64


0


float


0


double


0


struct tm


1900-1-1 0:0:0


std::string


“”

  如果不想用上表中的默认值,则推荐在select语句中使用nvl函数进行显示指定。

3.13        批量插入

  在3.5绑定容器一节中,利用绑定容器变量的方式,已经实现了各种数据的批量入库。

  本节再给出一个含有多种类型数据批量插入的示例:

 1     occiwrapper::ConnectionInfo info( "127.0.0.1", 1521, "occiwrapper", "occiwrapper", "orcl" );
 2     occiwrapper::Session s = SessionInstance( info );
 3     struct tm tm_value;
 4     time_t now_time = time( NULL );
 5     localtime_s( &tm_value, &now_time );
 6     vector< string > vec0;
 7     vec0.push_back( "123456" );
 8     vec0.push_back( "222222" );
 9     vector< struct tm >  vec1;
10     vec1.push_back( tm_value );
11     vec1.push_back( tm_value );
12     vector< occiwrapper::Int8 > vec2;
13     vec2.push_back( 1 );
14     vec2.push_back( 2 );
15     vector< float > vec3;
16     vec3.push_back( 0.1 );
17     vec3.push_back( 0.2 );
18     vector< double > vec4;
19     vec4.push_back( 10000 );
20     vec4.push_back( 100 );
21     s << "insert into test_batched_table( string_value, date_value, int_value, float_value, number_value ) values ( :1, :2, :3, :4, :5 )", batched_use( vec0 ), batched_use( vec1 ), batched_use( vec2 ), batched_use( vec3 ), batched_use( vec4 ), now, bRet, strErrMsg;
22     assert( bRet );

3.14 批量读取

  当一个表含有大量记录时,需要进行批量读取。Occiwrapper提供了非常便捷的批量读取方式,可以直接把表内的结果读取到容器中,屏闭了复杂的类型绑定和内存操作过程。

  在3.10执行select语句并保存结果一节中,给出了通过一条SQL语句,一次把表内所有的数据读取出来。

  但实际上,常遇到一张表内的数据量达到百万、千万级别,一次根本读不到内存中(out of memory)。此时,就需要多次分批读取。以下给出一段示例代码。

 1     occiwrapper::ConnectionInfo info( "127.0.0.1", 1521, "occiwrapper", "occiwrapper", "orcl" );
 2     occiwrapper::Session s = SessionInstance( info );
 3     struct tm tm_value;
 4     time_t now_time = time( NULL );
 5     vector< int > vec1;
 6     vector< int > vec2;
 7     // test limit select, getting all of data to the vectors
 8     occiwrapper::Statement stmt = ( s << "select * from tbl_test2 t", into( vec1 ), into( vec2 ), limit( 10000 ) );
 9     do
10     {
11               vec1.clear();
12               vec2.clear();
13               stmt.Execute();
14     }
15     while( stmt.HasNext() );

  通过执行上述代码,每次通过调用Execute操作,从表中取10000条记录到vec1和vec2两个容器中。如果不执行vec1.clear()操作,下次调用Execute操作,会再往vec1中追加10000条记录。示例中,并没有对数据进行处理,因此,直接进行了清除。

时间: 2024-08-01 11:36:20

OcciWrapper使用指南(高性能Oracle访问组件)的相关文章

Oracle数据访问组件ODAC的安装方法

Oracle数据访问组件ODAC(Oracle Data Access Components)顾名思义就是用来访问Oracle数据库的小程序.我们可以编程调用这些组件来实现在没有安装Oracle数据库软件的电脑上完成对Oracle数据库的访问. 工具/原料 ODAC安装包 步骤1. 下载ODAC安装包 到Oracle官方网站下载ODAC安装包.在网页上找到你要的版本.我下载的是: 64-bit ODAC 11.2 Release 6 (11.2.0.4.0) Xcopy for Windows

微信自用高性能通用key-value组件MMKV已开源!

1.MMKV简介 腾讯微信团队于2018年9月底宣布开源 MMKV ,这是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,主打高性能和稳定性.近期也已移植到 Android 平台,一并对外开源. MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强.从 2015 年中至今,在 iOS 微信上使用已有近 3 年,其性能和稳定性经过了时间的验证.近期也已移植到 An

尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。

从10G开始,Oracle提供了一个较为轻量级的客户包,叫做Instant Client. 将它安装好后,就不用再安装庞大的Oracle Client了. 这样一来,只要客户端下载Instant Client,直接解压,设置Path就ok了.具体设置如下:1.下载32位Oracle InstantClient 2.将Oracle InstantClient解压到某目录 3.打开PL/SQL,在perference里面设置OCI Library和Oracle_home,例子如下:        

设计模式在实际业务应用中的介绍之1——抽象工厂模式实现对数据库访问组件的封装

设计模式在实际业务应用中的介绍之1--抽象工厂模式实现对数据库访问组件的封装 基于C#打造的通用数据库访问组件 基于C#打造的通用数据库访问组件,完全支持开闭原则,设计上支持可扩展支持任意主流数据库,目前组件只实现了Oracle.MS SQL.MySQL三种库. 该组件实现简单.架构清晰,目前组件只包括5个类文件,兼容了三种数据库,组件实现采用了单例模式.工厂模式. 获取组件源码请入QQ群706224870,在群文件中下载.入群验证信息:codefc 下面简单描述下实现思路: 5个类文件如下:D

Asp.net_解决vs运行报在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题的bug方法

环境:操作系统win10 64位,开发工具vs2015 社区版,服务器数据库oracle 11g 64位,本机客户端oracle client 11g 64位,PLSQL Developer 也是64位版 以上开发环境,PLSQL Developer可以正常连接服务器数据库,然而运行项目代码后报以下错误: “System.InvalidOperationException”类型的异常在 System.Data.OracleClient.dll 中发生,但未在用户代码中进行处理 其他信息: 尝试加

.net程序错误:BadImageFormatException....如果在安装32位Oracle客户端组件的情况下以64位模式运行

OracleClient 程序要连oracle数据库,提示如下错误: 数据连接不成功,请检查该数据库是否已启动尝试加载oracle客户端时引发BadImageFormatException.如果在安装32位Oracle客户端组件的情况下以64位模式运行,将出现此问题. 1.IIS部署时 网上搜索了一下,有各种办法,试过多安装了一个64位的oracle11g客户端,还是不行.后来想到是否是iis的问题,之前配置iis的时候好像碰到过32位64位的一个设置,看了以前的博客之后把应用程序池做了如下设置

Oracle内存组件理论篇一

目标 1.SGA结构 2.PGA结构 1.SGA Shared pool 1).共享池是对SQL.PL/SQL程序进行语法分析.编译.执行的内存区域. 在执行SELECT * FROM emp语句时,会对sql语句进行语法分析->编译->生成执行计划->运行执行计划等,这些操作都在共享池中完成: 如果再次执行SELECT * FROM emp语句时,会在共享池中查找是否有相同的sql,如果存在则省去编译.生成执行计划操作步骤而是直接运行执行计划. 因此养成良好的编码习惯对于提高oracl

webservice 尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下运行,将出现此问题

最近做的项目中,应用服务器迁移到另外一台服务器,操作系统升级为win10,配置好IIS里的应用程序发布网站和Webservice网站后, 客户端程序调用Webservice出错: “尝试加载 Oracle 客户端库时引发 BadImageFormatException.如果在安装 32 位 Oracle 客户端组件的情况下运行,将出现此问题”. 写了个控制台程序,在本机上运行测试,还是出现这个问题: 最开始以为是oracle客户端的问题,重新安装另外一个版本的客户端,运行程序还是出现这个错误.

通用简易数据访问组件 Gem.Data

通用简易数据访问组件 Gem.Data,非ORM,无需配置,直接编写SQL语句操作数据.支持多种数据库 Access.MySql.SqlServer 等. 1.初始化数据访问组件 IXDatabase dbAccess = XDatabaseBuilder.CreateAccessDb("demo.mdb"); IXDatabase dbMySql = XDatabaseBuilder.CreateMySqlDb("127.0.0.1", 3306, "D