前几天,偶然知道了一个新名词:OCCI,这是虾米东东呢?找了时间看了一下,原来是一套oracle提供的访问oracle数据库的C++接口,用过微软数据库的朋友马上会联想到一个东西,那就是DAO,不错,这东西的原理和DAO是一样的,下面就让我们来看一下OCCI把。(DAO就是Data Access Object的缩写,也是一套访问数据库的库,IT界缩写词很多,有可能你在用着都不自知,这没有关系)
因为我是直接从oracle网站上查看的,在下面这个地址,有两个压缩包,里面包含了OCCI的演示代码,我们就从这里开始分析吧:
http://www.oracle.com/technology/global/cn/sample_code/tech/occi/index.html
我们可以先从第二个压缩包的内容开始看起,就是这个包:
occiplsql.tar.tar
我们下载之后,解压缩,包含三个文件,其中一个是
storedproc.cpp
我们就从她开始看吧。(其实这个文件是一个PL/SQL的演示程序,里面使用了三种执行存储过程的办法,下面就会讲到;另外,这个程序需要用到一些存储过程,在解压得到的occiplsql_readme.txt文件中有详细的描述,使用schema.sql在自己的数据库中创建存储过程,这里省略)
让我们一行一行代码来分析
首先,它调用了文件所需头文件:
#include <iostream>
#include <string>
#include <vector>
#include <occi.h>
这里最重要的就是occi.h了,这一看就是occi库文件的头文件,一般我们后面基本上都要导入这个头文件,无需赘言。
然后代码紧跟着的就是一个main()函数,让我们看一看下面的代码:
//initialize in object mode since we are accessing VARRAY types
Environment *env = Environment::createEnvironment(Environment::OBJECT);
Connection *conn = env->createConnection("scott","tiger");
Statement *stmt = conn->createStatement();
这三段代码是调用OCCI的基础,初始环境,建立连接,并且创造一个Statement来对数据库进行操作。
下面看看他如何执行sql语句吧:
//create anonymous block for executing stored proc/function
stmt->setSQL("begin OCCIDEMO1.GetBookDetails(:1, :2, :3, :4, :5); end;");
int id = 1;//book to retrieve
//pass IN parameters by setXXX(), indicate OUT parameters
//by registerOutParam
stmt->setNumber(1, id);//1 - IN - Id
stmt->registerOutParam(2, OCCISTRING, 100); //2 - OUT - title,max=100
stmt->registerOutParam(3, OCCIDOUBLE); //3 - OUT - price
stmt->registerOutParam(4, OCCIDATE); //4 - OUT - pubdate
stmt->registerOutParam(5, OCCIVECTOR, 0,
"SCOTT.KEYWORDSLIST"); //5 - OUT - keywords(varray)
stmt->execute(); //execute procedure
很简单,不是吗?这里调用了存储过程,注册了几个输出函数。这些和.NET平台的存储过程调用很像,尤其跟JSP中的数据库调用很像(简直一摸一样)。注意,里面的输出函数调用了OCCI的变量,就是OCCISTRING,OCCIDOUBLE等等,以OCCI*形式的变量。
然后我们往下看:
//get the OUT parameters
string title = stmt->getString(2);
double price = stmt->getDouble(3);
Date pubdate = stmt->getDate(4); //OCCI Date class
vector<string> keywords;
//there are overloaded getVector methods for each vector<T>
getVector(stmt, 5, keywords);
这里注释的很清楚,得到刚才我们定义的存储过程输出变量的输出值,我们只需从Statement中取出结果就行了,无需赘言。
然后下面执行了一些输出函数,打印我们的结果:
cout << "Book Details : " << title << " " << price << " " <<
pubdate.toText() << endl;
cout << "Keywords : ";
for (int i = 0 ; i < keywords.size(); i++)
cout << keywords[i] << ",";
cout << endl;
cout << "******Calling GetBookList******" << endl;
然后我们来看下面的第二个存储过程,这个和第一个是不同(废话),哪里不同呢?我们可以看一下他的注释:
//Stored Function 2 - shows PL/SQL tables and function returning value
使用函数返回值得到表
/* To pass/retrieve PL/SQL tables use setDataBufferArray method :-
void setDataBufferArray(unsigned int paramIndex,
void *array, Type type, ub4 arraySize, ub4 *arrayElements,
sb4 elementSize, ub2 *elementLengths, sb2 *ind = NULL, ub2 *rc = NULL)
After the execute, the buffer will contain OUT values
*/
第一句,使用setDataBufferArray函数来传递和恢复 PL/SQL表
看看我们第一个存储过程,是直接传递的变量和得到结果,姑且称之为“直接法”,而第二个演示的方法就是使用Statement自带的函数setDataBufferArray来进行操作了。
注意,这里的注释同时也告诉了我们将要用到的setDataBufferArray函数的原型,大家可以稍微看一下,下面会用到。
下面我们来看看第二个存储过程的代码
首先,进行了各种变量的定义:
stmt->setSQL("begin :1 := OCCIDEMO1.GetBookList(:2, :3); end;");
int idlist[10];
char booklist[10][200];
ub4 inelems=3,outelems=0;
ub2 outelemlens[10], inelemlens[10];
idlist[0] = 1;idlist[1] = 2;idlist[2] = 3;//book Ids 1,2,3
inelemlens[0] = inelemlens[1] = inelemlens[2] = sizeof(int);
这里,就定义了setDataBufferArray需要用到的让人困惑的ub4,ub2等类型的变量,这些其实就是用来buffer我们的结果的。
然后下面正式开始使用setDataBufferArray来进行操作:
stmt->setDataBufferArray(2, idlist, OCCIINT, 10, &inelems,
sizeof(int), inelemlens);//2 - IN - TABLE OF NUMBER
stmt->setDataBufferArray(3, booklist, OCCI_SQLT_STR, 10, &outelems,
200, outelemlens);//3 - OUT - TABLE OF VARCHAR2
stmt->registerOutParam(1, OCCIINT); //1 - Function return value
stmt->execute(); //execute the function
这里我们可以看到,用到了两次setDataBufferArray,我前面已经说过setDataBufferArray就是用来buffer我们的变量(还有值),最后的结果被contain在了outelemlens中。(这些在程序的注释中都提到了)
之后我们就可以取得返回的值,向下面这样:
int ret = stmt->getInt(1);//Function return value
cout << "Function return : " << ret << endl;
cout << "Elements returned : " << outelems << endl;
for (int j = 0; j < outelems; j++)
cout << booklist[j] << "[" << outelemlens[j] << "]" << endl;
cout << "******Calling SearchBooks******" << endl;
好了,这就是使用了setDataBufferArray的用法。
下面我们来看例子中的最后一个用法:
//Stored Proc 3 - returns a REF cursor for a query
说得很清楚,就是返回一个可以被我们用来操作的REF cursor (引用游标),这样我们就可以操作集合数据了,这个也很简单,做过数据库的都知道,简单看一下吧:
stmt->setSQL("begin OCCIDEMO1.SearchBooks(:1, :2); end;");
//for IN/OUT, input with setXXX, do not call registerOutParam
stmt->setString(1, "Databases"); //1 - IN/OUT - varchar
stmt->setMaxParamSize(1, 100);//max param size for string parameter
stmt->registerOutParam(2, OCCICURSOR);//2 - OUT - Ref Cursor
stmt->execute();//execute stored procedure
首先,这些都是相同的,同样是规定了输入和输出变量,然后执行。
cout << "Searched using keyword: " << stmt->getString(1) << endl;
ResultSet *rs = stmt->getCursor(2);//use ResultSet to fetch rows
//we know cursor has 1 varchar column in Select, use getString()
while (rs->next())
cout << "Book : " << rs->getString(1) << endl;
stmt->closeResultSet(rs);
然后,这里用到了Statement的getCursor将结果赋值给一个ResultSet(结果集),之后我们就可以遍历返回的数据了。
到此为止,就完成了对OCCI操作PL/SQL语言示例的解释(好像没有讲什么东西,别怪我,因为确实很简单^_^,就是我们每天使用到的,而且示例也很简单,不过这很好,simple is beautiful)。
好了,到这里就结束了,我们要进行收尾工作,像下面这样:
conn->terminateStatement(stmt);
env->terminateConnection(conn);
Environment::terminateEnvironment(env);
将我们用到的这三个变量倒序释放掉,这应该是个好习惯。
其实整个这部分都是用到了异常处理,我们在这里没有提及,大家可以自行研究。
到这里,对OCCI的简单数据库操作就结束了。
如果有时间,我们将在教程2中讲一下另一个压缩包的内容。并且将所有涉及到的代码都调试一下,看看实际中是怎样的。
分享到:
相关推荐
受够了ADO 的折磨,试试 OCCI的。包括OCCI 编程入门。
OCCI 用户指南和OCCI源码 OCCI 用户指南和OCCI源码
occi使用手册(11g Release 1 (11.1))
occi测试代码 是occi的一个实例代码 更加鲜明的显示出occi的用法
OCCI封装包 线程池 对occi进行了封装 利用线程池方案
自己精心收集的oracle occi资料。 包括官网occi例子, 自己编写的occi示例(增删改,存储过程等), 还有整理的occi使用指南, 官网的occi书籍
Oracle ODBC与OCCI对照表,方便大家利用ODBC和OCCI接口开发数据库程序
VC使用occi 连接 orcale 数据库。包括代码中包括一个写好的使用事例。
vc6.0下occi配置
oracle培训ppt, occi的详细介绍以及常用方式的示例代码
包含了OCCI简介、编程指南、使用手册,以及关于批处理实例
OCCI快速入门!1.OCCI编程模式2.流程图具体说明......
在做Oracle项目开发时候,经常会用到的文档,方便查阅OCCI API,程序猿的好帮手。大家支持下我吧!THX A Lot
Oracle10g occi 连接池创建方法Oracle10g occi 连接池创建方法
文件列表 occi10gr2samples.tar.gz occi10gsamples.tar.gz occi920.tar.gz occiplsql.tar.gz occispatial.tar.gz occivc9win32_111060.zip
The Oracle C++ Call Interface (OCCI) is an application programming interface (API) that allows applications written in C++ to interact with one or more Oracle database servers. OCCI gives your ...
封装了OCCI的底层接口,是的操作变得容易,而且方便。 只需要配置连接池的参数,调用一下初始化函数,然后,你就可以方便的执行查询和增删改的SQL。详细信息,请参考Readme.txt.
Oracle OCCI 连接示例程序 准备工作: http://www.oracle.com/technetwork/database/occidownloads-083553.html 1. 修改 项目属性-> C++ -> 常规 ->附加包含目录 , 指向你自己的 occi.h所在目录, 我的是 D:\...
occi详细说明文档PDF
occi使用demo 及 所需动态链接库/。。。。。。。。。。。