OcciWrapper使用指南(高性能Oracle访问组件)
occiwrapper使用指南
occiwrapper是一个开源的、跨平台的Oracle访问组件, 方便C++开发者们灵活地操作oracle数据库。为了方便使用,组件中的接口形式参考的POCO库的使用方式。occiwrapper采用如下的形式执行SQL语句:
occiwrapper::Session s = SessionInstance( connection );
s << "truncate table TBL_TEST ", now;
通过session对象维护一个到oracle的会话。类似于流的操作方式,向session中传入SQL语句,并执行。
在oracle参数绑定方面,Occiwrapper可以直接将C++变量绑定到oracle参数中,在以后的文档说明中详细介绍。
occiwrapper::Session s = SessionInstance( info );
struct tm tm_value;
s << "insert into TBL_TEST( date_value ) values ( :1 )", use( tm_value ), now;
同时,对于vector等容量变量,可以灵活地直接绑定到oracle的绑定变量上,同时也可以灵活的将select语句返回的结果绑定到容器中,而且对于使用者来讲,并不用关心类型的对应关系。为了提高存取的性能,写入和读取都采入批量操作的方式,同时采用智能指针自动管理内存缓冲池,最大限度地解放了oracle开发者。
occiwrapper::Session s = SessionInstance( info );
vector< int > vec1;
s << "select A from tbl_test2 t", into( vec1 ), now;
组件中使用的很多技术都是在工作中一些经验的积累与总结,由于自己认识oracle不够深刻,对C++的理解也可能不够深入,希望大家多多讨论。对于大家发现的Bug,我也会尽快修改,同时热情欢迎大家积极参与库的修改。
源代码地址:https://github.com/CUCmehp/occiwrapper
1、下载和安装
1.1 第三方组件依赖
本组件依赖oracle公司的occi(Oracle C++ Calling Interface)动态库支持。连接不同的oracle版本,须要选择不同的occi版本。
关于occi的详细介绍,请参见oracle公司官方文档。
1.2 开发环境
在Windows系统下,可以通过Visual Studio 2008 SP1或者Visual Studio 2010进行编译。
在linux系统下,可以通过g++编译器进行编译。
1.3 运行环境
本组件可跨平台支持Windows和Linux操作系统。
1.4 数据库环境
test工程中所有测试用例用到的数据库表、存储过程、函数,都可以通过db文件夹中的脚本创建。
方法:
(1)通过具有system权限的用户执行脚本create_user.sql。
(2)使用用户occiwapper(密码为occiwrapper)执行occiwrapper.sql。
注:所有测试用例中均使用occiwrapper作为oracle的用户名。
1.5 测试
所有的测试代码存放在源码的test目录下,在windows、linux(Suse 10, Suse 11,openSuse12, redhat 6企业版, Centos 6 )下进行了相关的测试。数据库连接信息的配置文件放在db_config.ini中。
在程序在oracle 11gR2和12cR1(oracle 12.1)对应的occi版本下进行了测试。
2、 编译说明
2.1 Windows
- 使用Visual Studio 2008 SP1工具
使用Visual Studio 2008直接打开工程occi_wrapper_vs2008.sln,选择Debug和Release进行编译。
注:要求vs2008 sp1以上,是由于occiwrapper中使用了tr1库,而vs2008从SP1版本以上,才开始支持tr1库。
- Visual Studio 2010
使用Visual Studio 2010直接打开工程occi_wrapper_vs2010.sln,选择Debug和Release进行编译。
说明:源码中include/occi_11g目录下,存放着oracle 11.2.0.2 64位数据库对应的头文件,在lib_vs2008和lib_vs2010目录下,存放着11.2.0.2版数据库对应的lib库文件。在bin_vs2008和bin_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目录下,存放着生成的include和lib文件,测试文件存放在test目录下,test目录下的db_config.ini为测试库对应的配置信息。要执行test程序,需先在oracle数据库中执行db文件夹下的脚本。
3. 使用指南
本部分主要介绍调用occiwrapper组件的方法,包括以下部分:
- oracle连接;
- 创建一个会话;
- 执行DDL语句;
- 执行简单插入;
- 使用绑定变量插入;
- 执行update操作;
- Commit与Rollback;
- 执行存储过程;
- 调用函数;
- 执行select语句并保存结果;
- 处理oracle中的日期类型
- 关于NULL值的处理;
3.1 Oracle连接
occiwrapper组件通过类occiwrapper::ConnectionInfo结构来保存oracle连接信息。
occiwrapper::ConnectionInfo info;
info.ip = "127.0.0.1";
info.port =
info.username = "occiwrapper";
info.password = "occiwrapper";
info.sid = "orcl";
要建立一个oracle连接,需要先申请一个oracle的Environment变量,函数内部通过调用OCCI的createEnvironment函数创建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连接。
shared_ptr< occiwrapper::Environment > pEnv = occiwrapper::Environment::CreateEnvironment();
assert( pEnv->CreateEnvironment() != NULL );
occiwrapper::ConnectionInfo info;
info.ip = "127.0.0.1";
info.username = "occiwrapper";
info.password = "occiwrapper";
info.sid = "orcl";
assert( occiwrapper::Connection::GetConnection( shared_ptr< occiwrapper::Environment >( pEnv ), info ) != NULL );
上述代码中,shared_ptr为C++ 0x标准中提出的tr1库定义的智能指针,关于C++ 0x和tr1库,在此不做介绍,大家可以参见维基百科。
occiwrapper使用连接池对oracle数据库连接进行管理,对于相同的数据库连接进行复用;同时,通过连接池,对oracle连接进行管理,以下代码给出了如何使用occiwrapper的连接池,取得oracle连接。
occiwrapper::ConnectionInfo info;
occiwrapper::ConnectionPool connPool;
info.ip = "127.0.0.1";
info.username = "occiwrapper";
info.password = "occiwrapper";
info.sid = "orcl";
shared_ptr< occiwrapper::Connection > p = connPool.GetConnection( info );
assert( p != NULL);
assert( p->GetValidity() == occiwrapper::VALID );
shared_ptr< occiwrapper::Connection > other = connPool.GetConnection( info );
assert( connPool.GetConnMapSize() == );
3.2 创建一个会话
Session类用来管理客户端与oracle服务器之间的会话连接。通过会话连接,客户端可以灵活的创建出若干Statement来执行SQL命令。
occiwrapper通过类SessionFactory来创建session会话,SessionFactory是一个以单件形式存在的工厂类,可以动态的创建出Session对象。同时,SessionFactory中内置了一个连接池对象管理oracle连接。关于连接池对象,可以参考3.2节创建一个会话中的介绍。
以下代码给出了如何使用SessionFactory创建一个Session对象。
occiwrapper::ConnectionInfo info;
occiwrapper::Session s = occiwrapper::SessionFactory::Instance().Create( info, false );
为了方使创建Session,也可以使用宏定义。
occiwrapper::Session s = SessionInstance( info );
3.3 执行DDL语句
利用Session对象可以方便地执行DDL命令,如下示例演示如何创建一张表,再将它清空,最后删除该表。
occiwrapper::ConnectionInfo info( "127.0.0.1", , "occiwrapper", "occiwrapper", "orcl" );
occiwrapper::Session s = SessionInstance( info );
bool bRet = false;
string strErrMsg = "";
s << "create table tbl_test( x int )", now, bRet, strErrMsg;
s << "truncate table tbl_test", now, bRet, strErrMsg;
s << "drop table tbl_test", now, bRet, strErrMsg;
3.4 执行简单插入
对于简单的insert操作,指不使用绑定变量的insert操作。如何利用occiwrapper进行绑定变量插入,将在下两节中进行介绍。本节只介绍执行最简单的SQL语句。
例如,对于一张已知的表TBL_TEST1,该表只含有一个整数字段X。以下的代码数字10004插入到该表中。
occiwrapper::ConnectionInfo info( "127.0.0.1", , "occiwrapper", "occiwrapper", "orcl" );
occiwrapper::Session s = SessionInstance( info );
bool bRet = false;
string strErrMsg = "";
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 Windows下occiwrapper支持的绑定类型定义
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绑定到对应的绑定变量上。
occiwrapper::ConnectionInfo info( "127.0.0.1", , "occiwrapper", "occiwrapper", "orcl" );
occiwrapper::Session s = SessionInstance( info );
bool bRet = false;
string strErrMsg = "";
s << "insert into tbl_test1( x ) values ( :1 )", use( ), now, result, err_msg;
cout << "result: " << result << endl << "error message: " << err_msg << endl;
assert( result );
s << "insert into test_string( id, string_val ) values( :1, :2 )", use( ), use( "CUCmehp" ), now, result, err_msg;
cout << "result: " << result << endl << "error message: " << err_msg << endl;
assert( result );
s << "insert into test_number( id, number_value ) values( :1, :2 )", use( ), use( 3.5 ), now, result, err_msg;
cout << "result: " << result << endl << "error message: " << err_msg << endl;
assert( result );
对于同一个Session也可以多次进行绑定,进行复用,以下代码向表TBL_TEST1中插入0到9。
occiwrapper::ConnectionInfo info( "127.0.0.1", , "occiwrapper", "occiwrapper", "orcl" );
occiwrapper::Session s = SessionInstance( info );
bool bRet;
string strErrMsg;
s << "truncate table tbl_test1", now;
occiwrapper::Statement stmt = s << "insert into tbl_test1( x ) values( :1 )";
for( int i = ; i < ; ++ i )
{
stmt, use( i ), now, bRet, strErrMsg;
assert( bRet );
}
- 绑定容器
绑定容器是指把表中的若干列与一个或多个容器(1.0.0版本仅支持vector容器)相绑定。
如下图所示,一个表有A、B、C三列,可以将列A的数据与变量vector<A>进行绑定,将列B、列C的数据绑定到vector< tuple< B, C> >变量中,tuple为元组类型,其定义可以参见C++ 0x标准,定义在库tr1中。
利用occiwrapper的batched_use关键字可以灵活的实现上述绑定,以下示例给出了将数组{20,21,22,23,24}所生成的vector,批量插入到表TBL_TEST1中。
occiwrapper::ConnectionInfo info( "127.0.0.1", , "occiwrapper", "occiwrapper", "orcl" );
occiwrapper::Session s = SessionInstance( info );
bool bRet;
string strErrMsg;
int a[] = { , , , , };
vector< int > vec( a, a + );
s << "insert into tbl_test1( x ) values ( :1 )", batched_use( vec ), now, bRet, strErrMsg;
assert(bRet);
以下示例给出了如何绑定到两个vector或者一个vector<tuple>结构中。表TEST_STRING中含有两个字段ID、STRING_VAL,分别为integer和varchar2类型。示例中,首先将一个vector<int>变量和vector<string>变量绑定到这两列上,进行插入操作。然后,将一个vector< tuple<int,string> >变量绑定到这两列上。
occiwrapper::ConnectionInfo info( "127.0.0.1", , "occiwrapper", "occiwrapper", "orcl" );
occiwrapper::Session s = SessionInstance( info );
bool bRet;
string strErrMsg;
int a[] = { , , , , };
vector< int > vec( a, a + );
string strArray[] = { "message1", "message2", "message3", "message4", "message5" };
vector< string > vecStr( strArray, strArray + );
s << "insert into test_string( id, string_val ) values ( :1, :2 )", batched_use( vec ), batched_use( vecStr ), now, bRet, strErrMsg;
assert( bRet );
s << "truncate table test_string", now, bRet;
assert( bRet );
vector< tuple< int, string > > vecTuple;
for( size_t i = ; i < ; ++ i )
{
vecTuple.push_back( make_tuple( vec[ i ], vecStr[ i ] ) );
}
s << "insert into test_string( id, string_val ) values ( :1, :2 )", batched_use( vecTuple ), now, bRet, strErrMsg;
assert( bRet );
3.6 执行update操作
执行update操作的方式,跟执行DDL和select语句的方式基本相同,同样可以使用绑定变量。以下给出了简单的例子。
occiwrapper::ConnectionInfo info( "127.0.0.1", , "occiwrapper", "occiwrapper", "orcl" );
occiwrapper::Session s = SessionInstance( info );
bool bRet = false;
string strErrMsg = "";
s << "truncate table tbl_test1", now, bRet, strErrMsg;
s << "insert into tbl_test1( x ) values ( 10004 )", now, bRet, strErrMsg;
s << "update tbl_test1 set x = :1 where x = 10004", use( ), now, bRet, strErrMsg;
示例代码先向表TBL_TEST1中的X字段插入数值10004,然后将数值修改为10005。
3.7 Commit与Rollback
Occiwrapper支持两种形式的commit操作。在创建Session时,可以指定Commit的类型,isAutoCommit参数为true,则表示每次操作后,自动进行commit,否则需要手工commit或者rollback,操作才能生效。以下代码给出了示例。
occiwrapper::Session s = occiwrapper::SessionFactory::Instance().Create( info, false );
s << "truncate table tbl_test1", now;
s.Commit();
bool bRet = false;
string strErrMsg = "";
s << "insert into tbl_test1( x ) values ( 10005 )", now, bRet, strErrMsg;
s.Rollback();
occiwrapper::Statement stmt2 = ( s << "insert into tbl_test1( x ) values ( 10005 )" );
for ( int i = ; i < ; ++i)
{
stmt2.execute();
}
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输出。
下面的代码块给出了上述过程。
occiwrapper::ConnectionInfo info( "127.0.0.1", , "occiwrapper", "occiwrapper", "orcl" );
occiwrapper::Session s = SessionInstance( info );
bool bRet;
string strErrMsg;
int nParIn = ;
string strParOut = "";
s << "begin p_test_procedure( :1,:2 ); end;", use( nParIn, occiwrapper::PAR_IN ), use( strParOut, occiwrapper::PAR_OUT ), now, bRet, strErrMsg;
assert( bRet );
assert( strParOut == "" );
3.9 调用函数
调用函数的方法与调用存储过程类似,只不过函数有返回值,类型为输出类型。
occiwrapper::ConnectionInfo info( "127.0.0.1", , "occiwrapper", "occiwrapper", "orcl" );
occiwrapper::Session s = SessionInstance( info );
bool bRet;
string strErrMsg = “”;
int a = ;
s << "begin :1 := f_ins_tbl_test1( :2 ); end;", use( a, occiwrapper::PAR_OUT ), use( , occiwrapper::PAR_IN ) , now, bRet, strErrMsg;
assert( bRet );
int b;
s << "begin :1 := f_test2( :2, :3 ); end;", use( a, occiwrapper::PAR_OUT ), use( ), use( b, occiwrapper::PAR_OUT ), now, bRet, strErrMsg;
assert( bRet );
3.10 执行select语句并保存结果
select操作是SQL操作中最常见的操作之一,将oracle中的数据取到内存中。occiwrapper通过关键字into实现将数据库中的一个字段绑定到一个容器中。
vector< string > vStr;
vector< struct tm > vDate;
vector< occiwrapper::Int32 > vInt;
vector< float > vFloat;
vector< double > vDouble;
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;
assert( bRet );
上述代码段将表tbl_batched_table中的数据读取,并存到5组vector变量中。
occiwrapper内部采用了批量读取的方式,提高了读取的性能,同时内部自动管理批量绑定时所需要内存空间。
当表中数据量比较大,只取若干条数据时,可以使用Limit关键字。
下列代码段给出了示例:
vector< int > vec1;
vector< int > vec2;
// test limit select
s << "select * from tbl_test2 t", into( vec1 ), into( vec2 ), occiwrapper::Limit( ), now;
occiwrapper在读取时,并没有提供游标的操作(考虑到游标会影响对于底层的封装性),直接将内存中的容器对象(vector)与oracle的数据表进行了绑定。因此,当数据表中的数据量很大时,vector的插入受限于内存,故本组件更适应单表数据量在百万条以下的应用场景。当然,开发者为了防止插入时vector出错内存用尽,如将一个1亿条记录的数据,分100次插入到100W的vector容量中,每次调用批量入库,这样做也是能够成功的。然而,由于没有提供游标相关的操作,该表无法将1亿条记录一次绑定到一组vector中(会std bad allocate异常),从而形成了无法处理的窘境。因此,本组件更适合单表数据量在百万条以下规模的应用。
3.11 处理oracle中的日期类型
为了处理oracle中的Date类型,occiwrapper对外处理的类型为struct tm类型,即occiwrapper插入和读取的类型都采用struct tm类型。
示例代码中,给出了如何向表中插入当前时间,并如何将当向时间从oracle数据库中读到一个vector数组中。
occiwrapper::ConnectionInfo info( "127.0.0.1", , "occiwrapper", "occiwrapper", "orcl" );
occiwrapper::Session s = SessionInstance( info );
bool bRet;
string strErrMsg;
struct tm tmValue;
time_t nowTime = time( NULL );
localtime_r( &nowTime, &tmValue);
s << "truncate table test_date", now, bRet, strErrMsg;
s << "insert into test_date( date_val ) values ( :1 )", use( tmValue ), now, bRet;
vector< struct tm > vTmDb;
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绑定容器一节中,利用绑定容器变量的方式,已经实现了各种数据的批量入库。
本节再给出一个含有多种类型数据批量插入的示例:
occiwrapper::ConnectionInfo info( "127.0.0.1", , "occiwrapper", "occiwrapper", "orcl" );
occiwrapper::Session s = SessionInstance( info );
struct tm tm_value;
time_t now_time = time( NULL );
localtime_s( &tm_value, &now_time );
vector< string > vec0;
vec0.push_back( "" );
vec0.push_back( "" );
vector< struct tm > vec1;
vec1.push_back( tm_value );
vec1.push_back( tm_value );
vector< occiwrapper::Int8 > vec2;
vec2.push_back( );
vec2.push_back( );
vector< float > vec3;
vec3.push_back( 0.1 );
vec3.push_back( 0.2 );
vector< double > vec4;
vec4.push_back( );
vec4.push_back( );
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;
assert( bRet );
3.14 批量读取
当一个表含有大量记录时,需要进行批量读取。Occiwrapper提供了非常便捷的批量读取方式,可以直接把表内的结果读取到容器中,屏闭了复杂的类型绑定和内存操作过程。
在3.10执行select语句并保存结果一节中,给出了通过一条SQL语句,一次把表内所有的数据读取出来。
但实际上,常遇到一张表内的数据量达到百万、千万级别,一次根本读不到内存中(out of memory)。此时,就需要多次分批读取。以下给出一段示例代码。
occiwrapper::ConnectionInfo info( "127.0.0.1", , "occiwrapper", "occiwrapper", "orcl" );
occiwrapper::Session s = SessionInstance( info );
struct tm tm_value;
time_t now_time = time( NULL );
vector< int > vec1;
vector< int > vec2;
// test limit select, getting all of data to the vectors
occiwrapper::Statement stmt = ( s << "select * from tbl_test2 t", into( vec1 ), into( vec2 ), limit( ) );
do
{
vec1.clear();
vec2.clear();
stmt.Execute();
}
while( stmt.HasNext() );
通过执行上述代码,每次通过调用Execute操作,从表中取10000条记录到vec1和vec2两个容器中。如果不执行vec1.clear()操作,下次调用Execute操作,会再往vec1中追加10000条记录。示例中,并没有对数据进行处理,因此,直接进行了清除。
OcciWrapper使用指南(高性能Oracle访问组件)的更多相关文章
- 超轻量级高性能ORM数据访问组件Deft,比dapper快20%以上
超轻量级高性能ORM数据访问组件Deft,比dapper快20%以上 阅读目录 Deft简介 Deft 核心类介绍 Deft 3分钟即可上手使用 其他可选的配置参数 性能测试 Demo代码下载 回到顶 ...
- Oracle数据访问组件ODAC的安装方法
Oracle数据访问组件ODAC(Oracle Data Access Components)顾名思义就是用来访问Oracle数据库的小程序.我们可以编程调用这些组件来实现在没有安装Oracle数据库 ...
- Oracle数据访问组件ODAC的安装方法:
Oracle数据访问组件ODAC(Oracle Data Access Components)顾名思义就是用来访问Oracle数据库的小程序.我们可以编程调用这些组件来实现在没有安装Oracle数据库 ...
- 微信自用高性能通用key-value组件MMKV已开源!
1.MMKV简介 腾讯微信团队于2018年9月底宣布开源 MMKV ,这是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,主打高性能和稳定性.近 ...
- 高性能 Windows Socket 组件 HP-Socket v3.0.2 正式发布
HP-Socket 是一套通用的高性能 Windows Socket 组件包,包含服务端组件(IOCP 模型)和客户端组件(Event Select 模型),广泛适用于 Windows 平台的 TCP ...
- 高性能 Windows Socket 组件 HP-Socket v3.0.1 正式发布
HP-Socket 是一套通用的高性能 Windows Socket 组件包,包含服务端组件(IOCP 模型)和客户端组件(Event Select 模型),广泛适用于 Windows 平台的 TCP ...
- 尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。
从10G开始,Oracle提供了一个较为轻量级的客户包,叫做Instant Client. 将它安装好后,就不用再安装庞大的Oracle Client了. 这样一来,只要客户端下载Instant Cl ...
- “尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。”
远程连接服务器的数据库调试WCF程序时,可以正常访问数据库,但将程序发布成站点部署在数据库所在的服务器之后,一直报错,通过try/catch捕获得到以下报错信息: System.Exception: ...
- Oracle XDB组件重建说明
Oracle XDB 组件重建 说明一. XDB 组件说明1.1 官网说明:XDB 全称XML DB,官网的说明如下:http://docs.oracle.com/cd/E11882_01/appde ...
随机推荐
- int([x[, base]]) : 将一个字符转换为int类型,base表示进制
int([x[, base]]) : 将一个字符转换为int类型,base表示进制 >>> int(-12) -12 >>> int(-12.00) -12 > ...
- ASP.NET 使用mode=”InProc”方式保存Session老是丢失,无奈改成StateServer 模式。
http://blog.csdn.net/fox123871/article/details/8165431 session是工作在你的应用程序进程中的.asp.net进程.iis往往会在20分钟之后 ...
- SQL SERVER查看当前连接情况
使用超级管理员账户登录,并执行以下命令: SELECT * FROM [Master].[dbo].[SYSPROCESSES] WHERE [DBID] IN ( SELECT [DBID] FRO ...
- [杂题]URAL1822. Hugo II's War
看懂题意的请直接跳过下一坨! 本人有表达障碍! ========================================== 题意: (题意真的很难很难懂啊!!! 去他娘的**) 有一个王国 ...
- hdu 4878 ZCC loves words AC自动机+中国剩余定理+快速幂
题意就不说了. 分析:折腾好几天自己写的代码还是看了别人代码后发现几乎没什么复杂度的差别,可是就是一直超时,后来干脆照着别人写啊,一直WA,就在准备放弃干脆先写这篇博客的时候,又看了一眼WA的代码,发 ...
- HTML5文件拖拽
HTML5新增的File API, 可以获取名称.文件大小.类型等信息,需先对DOM中的Element进行拖拽事件绑定 相关API 首先获取节点,绑定拖动到该节点的事件,可以改变鼠标形状 var dr ...
- 如何在Oracle11中配置st_shapelib
- app与server联系
--- /frameworks/base/services/java/com/android/server目录下SystemServer.java 在ServerThread的run函数中增加加载Rf ...
- 手势识别官方教程(4)在挑划或拖动手势后view的滚动用ScrollView和 HorizontalScrollView,自定义用Scroller或OverScroller
简单滚动用ScrollView和 HorizontalScrollView就够.自定义view时可能要自定义滚动效果,可以使用 Scroller或 OverScroller Animating a S ...
- bzoj3626
百度空间马上要下架的说,赶快把最后一点题解补完,然后搬家这是一道不错的题,首先注意询问是满足区间减法的,我们把他变成前缀和表示设我们询问[1,r]中的点和z的LCA深度和,假设我们确定一个根,不难发现 ...