什么是OTL:OTL 是 Oracle, Odbc and DB2-CLI TemplateLibrary 的缩写,是一个操控关系数据库的C++模板库,它目前几乎支持所有的当前各种主流数据库。Oracle和DB2也可以由OTL间接使用ODBC的方式来进行操纵。
OTL中直接操作Oracle主要是通过Oracle提供的OCI接口进行,依赖于Oracle客户端。
OTL使用简单, 只要头文件中包含有: #include “otlv4.h” 就可,实际上整个OTL就一个“.H”的文件,使用起来极为的方便。
优点 |
(1).跨平台 (2).运行效率高,与C语言直接调用数据库API相当 (3).开发效率高,使用方便,繁在其内,简在其外,比 ADO.net使用起来更简单,更简洁 (4).部署容易,不需要ADO组件,不需要.net framework 等 |
缺点 |
(1).只能在C++中使用 |
- OTL的主要类
主要类包括:otl_stream、otl_connect、otl_exception
otl_stream类是OTL“流”的概念的具体表现形式,任何通过输入/输出参数使用SQL语句、PL/SQL 块或者是存储过程调用,在C++的编程中都能通过otl_stream类来实现。
其构造函数为:
(1)for Oracle 7/8/9/10:
otl_stream(const int arr_size, // 流的缓存大小
const char* sqlstm, // SQL语句或PL/SQL块或存储过程
otl_connect& db, // OTL数据库连接对象
const char* ref_cur_placeholder=0, // 游标引用占位符名称
const char* sqlstm_label=0 // SQL 语句标签);
(2)forODBC/DB2-CLI:
otl_stream(const int arr_size,// 流的缓存大小
constchar* sqlstm,// SQL语句或PL/SQL块或存储过程
otl_connect& db,// OTL数据库连接对象
const int implicit_select=otl_explicit_select ,
const char* sqlstm_label=0//SQL 语句标签);
OTL流构造函数,负责创建otl_stream对象并调用open()(解析sql语句)方法。
otl_stream的性能主要被缓冲区大小arr_size一个参数控制。缓冲区大小定义了插入表的逻辑行以及与数据库一次往反交互(one round-trip to the database)过程中从表或视图中查询的逻辑行。
(3)void set_commit(int auto_commit=0);
设置流的auto_commit标志。默认情况下,该标志被置1,即当输出缓冲区刷新时,当前的事务被自动提交。
注意流的auto_commit标志和数据库的自动提交模型没有任何关系。
(4)void set_flush(const bool auto_flush=true);
设置auto_flush标志。默认情况下auto_flush的值为true, 即如果缓冲区出现脏数据则在流的析构函数中刷新缓冲区。如果自动刷新标志被关闭,则需要使用close()方法或者flush()方法对流进行刷新。
注意该函数仅仅能够设置流的析构函数中是否自动刷新,并不是通常意义上的缓冲区刷新。
(5)voidflush(void);
刷新流的输出缓冲区。当输出缓冲区被填满时,缓冲区将被自动刷新。如果流的auto_commit标志被置上,则在刷新完毕后当前事务被提交。
otl_connect类封装了一系列有关数据库连接的功能:建立连接、断开连接、事务提交、事务回滚等等。换言之,otl_connect是在C++编程中创建和使用数据库连接以及进行数据库事务管理的类,主要方法有:
(1)static int otl_initialize(const int threaded_mode=0);
该静态方法的主要功能是初始化OTL数据库环境,程序中第一次建立与数据库的连接之前,必须调用该方法一次,其后再建立与数据库的连接,就不需要调用该方法了。如果程序是在多线程环境下访问数据库,参数threaded_mode需置为1。另外在多线程环境下访问数据库,不要多个线程操作同一个otl_connect对象,除非该ot_connect对象有互斥锁机制。
(2) otl_connect(const char* connect_str,const int auto_commit=0);
连接数据库。参数同rlogon(),见(3)rlogon()
(3) void rlogon(const char* connect_str,const int auto_commit=0);
该方法的主要功能是建立与数据库的连接。
参数connect_str是数据库连接配置字符串,有两种表达形式
o OTL4.0/OCIx
■”USER/PASSWORD”(本地数据库)
■”USER/PASSWORD@TNS_ALIAS”(远程数据库)
o OTL4.0/ODBC和OTL4.0/DB2_CLI
■”USER/PASSWORD@DSN”
■”DSN=value;UID=value;PWD=value”
参数auto_commit设置数据库事务的提交模式,auto_commit设置为1,表示数
据库事务自动提交;auto_commit设置为0,表示数据库事务非自动提交,auto_commit
缺省为0。
(4) void logoff(void);
该方法的主要功能是断开与数据库的连接。
(5) void commit(void);
该方法的主要功能是提交数据库事务。
(6) void rollback(void);
该方法的主要功能是回滚数据库事务。
(7) void auto_commit_off(void); void auto_commit_on(void);
设置otl_connect对象的auto_commit标志
(8) long direct_exec(constchar *sqlstm,
int ignore_error =
otl_exception::enabled );
直接执行静态(无绑定变量)的SQL语句 ,该函数返回处理的行数。-1:处理异常;>=0:在执行INSERT、DELETE或UPDATE语句时,实际返回的是已处理行数
otl_exception类用于描述OTL操作数据时抛出的异常,有3个主要的成员变量:
(1)unsignedchar msg[1000];
该成员变量用于保存存异常的具体错误信息。
(2)char stm_text[2048];
该成员变量用于保存导致发生异常错误的SQL语句。
(3)char var_info[256];
该成员变量用于保存导致发生异常错误的输入/输出变量。
OTL使用起来也很简单,使用不同的数据库连接,主要是根据需要在程
序开始的宏定义来指定的。OTL是首先根据这个宏定义来初始化数据库
连接环境。OTL中用来区分连接方式的宏定义主要有下面这些:
OTL_ORA7,OTL_ORA8, OTL_ODBC, OTL_DB2_CLI, OTL_ODBC_MYSQL...
不同的宏对应的数据库API,具体说明如下:
宏定义名 |
说明 |
OTL_ORA7 |
for OCI7 |
OTL_ORA8 |
for OCI8 |
OTL_ORA8I |
for OCI8i |
OTL_ORA9I |
for OCI9i. All code that compiles and works under #define OTL_ORA7, OTL_ORA8, and OTL_ORA8I, should work when OTL_ORA9I is used |
OTL_ORA10G |
for OCI10g. All code that compiles and works under #define OTL_ORA7, OTL_ORA8, OTL_ORA8I, OTL_ORA9I, should work with OTL_ORA10G. |
OTL_ORA10G_R2 |
for OCI10g, Release 2 (Oracle 10.2). All code that compiles and works under #define OTL_ORA7, OTL_ORA8, OTL_ORA8I, OTL_ORA9I, and OTL_ORA10G should work with OTL_ORA10G_R2 |
OTL_DB2_CLI |
for DB2 Call Level Interface (CLI) |
OTL_INFORMIX_CLI |
for Informix Call Level Interface for Unix (when OTL_ODBC_UNIX is enabled). |
OTL_IODBC_BSD |
for ODBC on BSD Unix, when iODBC package is used |
OTL_ODBC |
for ODBC |
OTL_ODBC_MYSQL |
for MyODBC/MySQL. The difference between OTL_ODBC_MYSQL and OTL_ODBC is that transactional ODBC function calls are turned off for OTL_ODBC_MYSQL, since MySQL does not have transactions |
OTL_ODBC_ POSTGRESQL |
for the PostgreSQL ODBC driver 3.5 (and higher) that are connected to PostgerSQL 7.4 / 8.0 (and higher) servers. |
OTL_ODBC_UNIX |
for ODBC bridges in Unix |
OTL_ODBC_zOS |
for ODBC on IBM zOS. |
OTL_ODBC_XTG_IBASE6 |
for Interbase 6.x via XTG Systems' ODBC driver. The reason for introducing this #define is that the ODBC driver is the only Open Source ODBC driver for Interbase. Other drivers, like Easysoft's ODBC for Interbase, are commercial products, and it beats |
绑定变量
INSERT INTO my_table (employee_id, supervisor_name)VALUES(
:employee_id<int>,
:supervisor_name<char[33]>)
(1) 使用宏指明底层数据库API类型和控制编译器对OTL的编译。例如:#define OTL_ORA9I // Compile OTL 4.0/OCI9i
(2) 创建otl_connect对象,该对象一般为全局共享的。
(3) 调用otl_connect的静态方法otl_initialize()初始化OTL环境。
(4) 调用otl_connect的rlogon()方法连接数据库。
(5) 创建otl_stream()对象,该对象一般为局部的。
(6) 使用otl_stream的<<操作符绑定SQL中的变量。
(7) 使用otl_stream的>>操作符读取返回结果。
(8) 调用otl_connect的logoff()方法从数据库断开。
代码
代码 #include <iostream> using namespace std; #include <stdio.h> #define OTL_ORA9I // Compile OTL 4.0/OCI9i, //#define OTL_UNICODE //Enable Unicode OTL for OCI9i #include <otlv4.h> // include the OTL 4.0 header file otl_connect db; // connect object void insert();void insertConstant();void insertBatch(); void insertNoAutoCommit(); void select(); void update();void updateNoAutoCommit();void del(); int main() { otl_connect::otl_initialize(); // initialize OCI environment try{ db.rlogon("dbuser/dbpwd"); // connect to Oracle otl_cursor::direct_exec ( db, "drop table person_tab", otl_exception::disabled // disable OTL exceptions ); // drop table otl_cursor::direct_exec ( db, "create table person_tab(age number, name varchar2(30))" ); // create table insert(); // insert one records into table insertConstant();//constand insert sql insertBatch(); // insert batch records into table insertNoAutoCommit();//insert no auto commit; select(); // select records from table update(); // update records in table updateNoAutoCommit(); // update no auto commit del(); // delete records from table } catch(otl_exception& p){ // intercept OTL exceptions cerr<<p.msg<<endl; // print out error message cerr<<p.stm_text<<endl; // print out SQL that caused the error cerr<<p.var_info<<endl; // print out the variable that caused // the error } db.logoff(); // disconnect from Oracle return 0; } void insert()//插入单条数据数据 { // create insert stream otl_stream o(1, // buffer size "insert into person_tab values(:v_age<int>,:v_name<char[31]>)", // INSERT statement db // connect object ); o<<30;//assigning :v_age=30 o<<“dengkf”;//assigning :v_name=“dengkf” //char tmp[32];sprintf(tmp,”邓科峰”); //o<<(unsigned char*)tmp; //INSERT automatically executes when all input variables are assigned. } void insertBatch()//批量插入数据 { // create insert stream otl_stream o(10000, // buffer size "insert into person_tab values(:v_age<int>,:v_name<char[31]>)", db // connect object ); char tmp[32]; for(int i=1;i<=10000;i++){ sprintf(tmp,“NAME%d”,i); o<<i; o<<tmp; } //INSERT automatically executes when all input variables are assigned. } void insertNoAutoCommit()//插入数据(事务手动提交) { // create insert stream otl_stream o(10001, // buffer size "insert into person_tab values(:v_age<int>,:v_name<char[31]>)", db // connect object ); o.set_flush(false);//turning off the stream’s autoflush flag o.set_commit(0);//turning off the stream's autocommit flag char tmp[32]; for(int i=1;i<=10000;i++){ sprintf(tmp,“NAME%d”,i); o<<i; o<<tmp; } o.flush();//flushing the stream's buffer db.commit();//committing the changes to the database } void select()//检索数据 { // create select stream otl_stream i(50, // buffer size "select * from person_tab where name=:v_name<char[31]>", // SELECT statement db // connect object ); i<<"dengkf"; // assigning :v_name = 8 // SELECT automatically executes when all input variables are // assigned. First portion of output rows is fetched to the buffer int r_age; char r_name[31]; while(!i.eof()){ // while not end-of-data i>>r_age; i>>r_name; cout<<"age="<<r_age<<endl; cout<<"name="<<r_name<<endl; } } //修改数据(事务自动提交) void update() { // create update stream otl_stream s(1, // buffer size "update person_tab set age=:v_age<int> where name=:v_name<char[31]>", // UPDATE statement db // connect object ); s<<31;//assgining :v_age =31 s<<"dengkf"; //assigning :v_name = 8 //UPDATE automatically executes when all input variables are assigned. } //修改数据(事务手动提交) void updateNoAutoCommit() { // create update stream otl_stream s(2, // buffer size "update person_tab set age=:v_age<int> where age<:v_age2<int>",// UPDATE statement db // connect object ); s.set_flush(false); s.set_commit(0); s<<31;//assgining :v_age =31 s<<2000; //assigning :v_age2 = 2000 s.flush(); db.commit(); } //删除数据 void del() { // create delete stream otl_stream l(1, // buffer size “delete from person_tab where name=:v_name<char[31]>", // DELETE statement db // connect object ); l<<"dengkf"; //assigning :v_name = 8 //DELETE automatically executes when all input variables are assigned. }