• 什么是OTL:OTL 是 Oracle, Odbc and DB2-CLI TemplateLibrary 的缩写,是一个操控关系数据库的C++模板库,它目前几乎支持所有的当前各种主流数据库,如下表所示:

数据库

访问接口

支持版本

Oracle

OCI

OCI7、OCI8、OCI8i、OCI9i、OCI10g

DB2

CLI

DB2 CLI

MS SQL Server

、Sybase、Informix

、MySQL、 Interbase/Firebird、PostgreSQL、SQLite、SAP/DB、TimesTen、MS ACCESS

ODBC

ODBC2.5、ODBC3.x

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_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类封装了一系列有关数据库连接的功能:建立连接、断开连接、事务提交、事务回滚等等。换言之,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_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 the purpose of using Interbase, as an Open Source.database server.

绑定变量

•示例:

INSERT INTO my_table (employee_id, supervisor_name)VALUES(

:employee_id<int>,

:supervisor_name<char[33]>)

•placeholder(比如employee_id)可以用没有意义的f1代替,但是在一个SQL语句中不能使用相同名字的placeholder
•在执行INSERT语句的时候,如果数据库中char字段的大小是n,则这个INSERT语句的绑定变量的大小要为n+1;否则当邦定变量的大小为n时,执行INSERT会出错。
•对数据库中定义的数字字段,可以根据字段的大小使用16位、32 位的整数和double类型;当然,如果对所有OCI的数字字段使用double,也不会出错。
•OTL的一般使用步骤包括:

(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()方法从数据库断开。

  1. #include <iostream>
  2. using namespace std;
  3. #include <stdio.h>
  4.  
  5. #define OTL_ORA9I // Compile OTL 4.0/OCI9i,
  6. //#define OTL_UNICODE //Enable Unicode OTL for OCI9i
  7. #include <otlv4.h> // include the OTL 4.0 header file
  8. otl_connect db; // connect object
  9.  
  10. void insert();void insertConstant();void insertBatch();
  11. void insertNoAutoCommit();
  12. void select();
  13. void update();void updateNoAutoCommit();void del();
  14.  
  15. int main()
  16. {
  17. otl_connect::otl_initialize(); // initialize OCI environment
  18. try{
  19. db.rlogon("dbuser/dbpwd"); // connect to Oracle
  20. otl_cursor::direct_exec
  21. (
  22. db,
  23. "drop table person_tab",
  24. otl_exception::disabled // disable OTL exceptions
  25. ); // drop table
  26.  
  27. otl_cursor::direct_exec
  28. (
  29. db,
  30. "create table person_tab(age number, name varchar2(30))"
  31. ); // create table
  32.  
  33. insert(); // insert one records into table
  34. insertConstant();//constand insert sql
  35. insertBatch(); // insert batch records into table
  36. insertNoAutoCommit();//insert no auto commit;
  37. select(); // select records from table
  38. update(); // update records in table
  39. updateNoAutoCommit(); // update no auto commit
  40. del(); // delete records from table
  41. }
  42.  
  43. catch(otl_exception& p){ // intercept OTL exceptions
  44. cerr<<p.msg<<endl; // print out error message
  45. cerr<<p.stm_text<<endl; // print out SQL that caused the error
  46. cerr<<p.var_info<<endl; // print out the variable that caused
  47. // the error
  48. }
  49. db.logoff(); // disconnect from Oracle
  50. return ;
  51. }
  52. void insert()//插入单条数据数据
  53. { // create insert stream
  54. otl_stream o(, // buffer size
  55. "insert into person_tab values(:v_age<int>,:v_name<char[31]>)",
  56. // INSERT statement
  57. db // connect object
  58. );
  59. o<<;//assigning :v_age=30
  60. o<<“dengkf”;//assigning :v_name=“dengkf”
  61. //char tmp[32];sprintf(tmp,”邓科峰”);
  62. //o<<(unsigned char*)tmp;
  63. //INSERT automatically executes when all input variables are assigned.
  64. }
  65.  
  66. void insertBatch()//批量插入数据
  67. {
  68. // create insert stream
  69. otl_stream o(, // buffer size
  70. "insert into person_tab values(:v_age<int>,:v_name<char[31]>)",
  71. db // connect object
  72. );
  73. char tmp[];
  74.  
  75. for(int i=;i<=;i++){
  76. sprintf(tmp,“NAME%d”,i);
  77. o<<i;
  78. o<<tmp;
  79. }
  80. //INSERT automatically executes when all input variables are assigned.
  81. } void insertNoAutoCommit()//插入数据(事务手动提交)
  82. {
  83. // create insert stream
  84. otl_stream o(, // buffer size
  85. "insert into person_tab values(:v_age<int>,:v_name<char[31]>)",
  86. db // connect object
  87. );
  88. o.set_flush(false);//turning off the stream’s autoflush flag
  89. o.set_commit();//turning off the stream's autocommit flag
  90. char tmp[];
  91.  
  92. for(int i=;i<=;i++){
  93. sprintf(tmp,“NAME%d”,i);
  94. o<<i;
  95. o<<tmp;
  96. }
  97. o.flush();//flushing the stream's buffer
  98. db.commit();//committing the changes to the database
  99. }
  100. void select()//检索数据
  101. {
  102. // create select stream
  103. otl_stream i(, // buffer size
  104. "select * from person_tab where name=:v_name<char[31]>",
  105. // SELECT statement
  106. db // connect object
  107. );
  108. i<<"dengkf"; // assigning :v_name = 8
  109. // SELECT automatically executes when all input variables are
  110. // assigned. First portion of output rows is fetched to the buffer
  111.  
  112. int r_age;
  113. char r_name[];
  114.  
  115. while(!i.eof()){ // while not end-of-data
  116. i>>r_age;
  117. i>>r_name;
  118. cout<<"age="<<r_age<<endl;
  119. cout<<"name="<<r_name<<endl;
  120. }
  121. }
  122. //修改数据(事务自动提交)
  123. void update()
  124. {
  125. // create update stream
  126. otl_stream s(, // buffer size
  127. "update person_tab set age=:v_age<int> where
  128. name=:v_name<char[]>",
  129. // UPDATE statement
  130. db // connect object
  131. );
  132. s<<;//assgining :v_age =31
  133. s<<"dengkf"; //assigning :v_name = 8
  134. //UPDATE automatically executes when all input variables are assigned.
  135. }
  136. //修改数据(事务手动提交)
  137. void updateNoAutoCommit()
  138. {
  139. // create update stream
  140. otl_stream s(, // buffer size
  141. "update person_tab set age=:v_age<int> where age<:v_age2<int>",// UPDATE statement
  142. db // connect object
  143. );
  144. s.set_flush(false);
  145. s.set_commit();
  146.  
  147. s<<;//assgining :v_age =31
  148. s<<; //assigning :v_age2 = 2000
  149.  
  150. s.flush();
  151. db.commit();
  152.  
  153. }
  154. //删除数据
  155. void del()
  156. {
  157. // create delete stream
  158. otl_stream l(, // buffer size
  159. delete from person_tab where name=:v_name<char[]>",
  160. // DELETE statement
  161. db // connect object
  162. );
  163. l<<"dengkf"; //assigning :v_name = 8
  164. //DELETE automatically executes when all input variables are assigned.
  165. }
  166.  
  167. •SQL使用举例(常量SQL使用):
  168. 常量SQL就是不带任何绑定变量的SQL,OTL通过一个静态方法来操作:
  169.  
  170. long otl_cursor::direct_exec(otl_connect&db,//OTL数据库对象
  171.  
  172. const char* sqltm,//SQL语句
  173.  
  174. otl_exception_disable=,//OTL异常忽略标志
  175.  
  176. );
  177.  
  178. 返回值:
  179.  
  180. ●-,如果otl_exception_disable被设置成1,并且OTL的底层API发生错误
  181.  
  182. ●>=,SQL执行成功,返回实际处理成功的记录数.
  183.  
  184. o Examples(Oracle)
  185.  
  186. otl_cursor::direct_exec
  187. (db, // connect object
  188. "create table person_tab(age number, name varchar2(30))"
  189. ); // create table
  190.  
  191. otl_cursor::direct_exec
  192. (db, // connect object
  193. "drop table persion_tab", // SQL statement
  194. otl_exception::disabled // disable OTL exceptions,
  195. // in other words, ignore any
  196. // database error
  197. ); // drop table
  198.  
  199. long rpc=otl_cursor::direct_exec
  200. (db,//connect object
  201. “delete from persion_tab”);
  202.  
  203. o Examples(ODBC,DB2-CLI)
  204. otl_cursor::direct_exec
  205. (db, // connect object
  206. "create table person_tab(age numeric, name varchar(30))"
  207. ); // create table
  208.  
  209. otl_cursor::direct_exec
  210. (db, // connect object
  211. "drop table persion_tab", // SQL statement
  212. otl_exception::disabled // disable OTL exceptions,
  213. // in other words, ignore any
  214. // database error
  215. ); // drop table
  216.  
  217. long rpc=otl_cursor::direct_exec
  218. (db,//connect object
  219. “delete from persion_tab”);
  220.  
  221. //“OtlPlsqlExample.cpp”
  222. #include <iostream>
  223. using namespace std;
  224.  
  225. #include <stdio.h>
  226. #define OTL_ORA9I // Compile OTL 4.0/OCI9i
  227. #include <otlv4.h> // include the OTL 4.0 header file
  228.  
  229. otl_connect db; // connect object
  230.  
  231. void plsql(void)
  232. // invoking PL/SQL block
  233. {
  234. otl_stream o(, // buffer size
  235. "begin "
  236. " :A<int,inout> := :A+1; "
  237. " :B<char[31],out> := :C<char[31],in>; "
  238. "end;",
  239. // PL/SQL block
  240. db // connect object
  241. );
  242. o.set_commit(); // set stream auto-commit off since
  243. // the block does not have any transactions
  244. // to commit
  245. o<<<<"Test String1"; // assigning :A = 1, :C = "Test String1"
  246. o<<<<"Test String2"; // assigning :A = 2, :C = "Test String2"
  247. o<<<<"Test String3"; // assigning :A = 3, :C = "Test String3"
  248.  
  249. o.flush(); // executing PL/SQL block 3 times
  250.  
  251. int a;
  252. char b[];
  253.  
  254. while(!o.eof()){ // not end-of-data
  255. o>>a>>b;
  256. cout<<"A="<<a<<", B="<<b<<endl;
  257. }
  258.  
  259. }
  260.  
  261. int main()
  262. {
  263. otl_connect::otl_initialize(); // initialize OCI environment
  264. try{
  265.  
  266. db.rlogon(“dbuser/dbpwd"); // connect to Oracle
  267.  
  268. plsql();//invoking PL/SQL block
  269.  
  270. }
  271.  
  272. catch(otl_exception& p){ // intercept OTL exceptions
  273. cerr<<p.msg<<endl; // print out error message
  274. cerr<<p.stm_text<<endl; // print out SQL that caused the error
  275. cerr<<p.var_info<<endl; // print out the variable that caused the
  276. // error
  277. }
  278.  
  279. db.logoff(); // disconnect from Oracle
  280.  
  281. return ;
  282. }
  283. 输出:
  284.  
  285. A=,B=Test Stri ng1
  286.  
  287. A=,B=Test String2
  288.  
  289. A=,B=Test String3
  290.  
  291. 常量PL/SQL块的使用与常量SQL的使用类似,在此不再赘述。

下一篇:OTL使用指南

OTL技术应用的更多相关文章

  1. otl中遇到的一些字符数组长度问题

    最近做的项目中对于数据库的操作为了有一个统一的操作,所以采用了otl技术作为中间媒介,当然,由于是用了别人的库,所以还是出现了很多问题.通过对问题进行分析,也形成了一些常用问题的处理方法. 在用otl ...

  2. OTL翻译(10) -- OTL的流缓冲池

    OTL的流缓冲池 一般来讲,流一般作为一个局部的变量被使用,当使用完毕后就立刻关闭,如果需要再次使用就需要再次的声明变量,如此循环.OTL流的缓冲池(内存池)是一个解决以往的流性能低下的一个机制.当流 ...

  3. OTL翻译(5) -- otl_stream流相关绑定变量

    声明绑定变量 本章节将详细的说明如何在otl_stream流里面声明绑定变量. SQL语句.SQL语句块或存储过程在程序里面使用的时候总是带有占位符.OTL里面带有一个小的解析器用来解析这些占位符,并 ...

  4. OTL使用指南

    1 OTL简介 OTL 是 Oracle, Odbcand DB2-CLI Template Library 的缩写,是一个C++编译中操控关系数据库的模板库,它目前几乎支持当前所有的各种主流数据库, ...

  5. 关于解决python线上问题的几种有效技术

    工作后好久没上博客园了,虽然不是很忙,但也没学生时代闲了.今天上博客园,发现好多的文章都是年终总结,想想是不是自己也应该总结下,不过现在还没想好,等想好了再写吧.今天写写自己在工作后用到的技术干货,争 ...

  6. SQL Server技术内幕笔记合集

    SQL Server技术内幕笔记合集 发这一篇文章主要是方便大家找到我的笔记入口,方便大家o(∩_∩)o Microsoft SQL Server 6.5 技术内幕 笔记http://www.cnbl ...

  7. 本人提供微软系.NET技术顾问服务,欢迎企业咨询!

    背景: 1:目前微软系.NET技术高端人才缺少. 2:企业很难直接招到高端技术人才. 3:本人提供.NET技术顾问,保障你的产品或项目在正确的技术方向. 技术顾问服务 硬服务项: 1:提供技术.决策. ...

  8. 分布式锁1 Java常用技术方案

    前言:       由于在平时的工作中,线上服务器是分布式多台部署的,经常会面临解决分布式场景下数据一致性的问题,那么就要利用分布式锁来解决这些问题.所以自己结合实际工作中的一些经验和网上看到的一些资 ...

  9. 【大型网站技术实践】初级篇:借助LVS+Keepalived实现负载均衡

    一.负载均衡:必不可少的基础手段 1.1 找更多的牛来拉车吧 当前大多数的互联网系统都使用了服务器集群技术,集群即将相同服务部署在多台服务器上构成一个集群整体对外提供服务,这些集群可以是Web应用服务 ...

随机推荐

  1. 【转】WinForm基础

    winform基础 先修基础:C#语法基础和面向对象编程 1.Winform创建解决方案 2.Winform窗体 3.MessageBOx 4.Winform登录.控制软件只运行一次.回车登录 5.W ...

  2. 用于主题检测的临时日志(0ece3f5c-d74f-449c-85a7-ed53fffb0e94 - 3bfe001a-32de-4114-a6b4-4005b770f6d7)

    这是一个未删除的临时日志.请手动删除它.(abf5973f-502f-47e6-8825-4dd1c2cdd799 - 3bfe001a-32de-4114-a6b4-4005b770f6d7)

  3. Texas Instruments matrix-gui-2.0 hacking -- app_description.php

    <?php /* * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistrib ...

  4. 51Nod 1002:数塔取数问题(DP)

    1002 数塔取数问题  基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题  收藏  关注 一个高度为N的由正整数组成的三角形,从上走到下,求经过的数字和的最大值. 每 ...

  5. C# 使用GZip对字符串压缩和解压

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...

  6. java泛型学习(1)

    java泛型(Generices Type) --->概念:泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和 ...

  7. [题解] CodeM美团点评编程竞赛资格赛题

    最近看到牛课网美团一个编程竞赛,想着做做看,结果一写就是两天..真是写不动了啊.话不多说,下面开始我的题解. 题目大致还是比较考察思维和代码能力(因为自己代码能力较弱,才会觉得比较考察代码能力吧= = ...

  8. 下载各个版本java (Java Development Kit)

    本文介绍怎么样下载各个版本java开发工具包. 方法/步骤   打开官方下载网址:http://www.oracle.com/technetwork/java/javase/downloads/ind ...

  9. hdu - 1823 - Luck and Love(线段树)

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/SCNU_Jiechao/article/details/24406391 题意:Wiskey招女友, ...

  10. JS 网页键盘钩子

    使用write技术把脚本和代码写入文件,即使查看原文及也无法看到原代码,下面是具体的代码,直接保存就可以运行============================================== ...