标题: 企业程序设计纲要系列---occi接口访问oracle数据
freestream
荣誉斑竹
Rank: 14Rank: 14Rank: 14Rank: 14



UID 86
精华 1
积分 77
帖子 148
活跃指数 0
LU金币 6012 个
LU金条 0 个
阅读权限 200
注册 2003-9-22
 
发表于 2004-12-19 23:54  资料  个人空间  短消息  加为好友 
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Oracle表数据 的C++存取接口</title>
<style type="text/css">
<!--
body,td,th {
color: #333399;
}
-->
</style></head>

<body>
<p align="center">Oracle表数据的C++存取接口
</p>
<p align="left">Oracle的表数据有多种存取方式,这里,着重介绍oracle 9i及其以后版本提供的C++接口,一种目前为止,最简单实用的编程接口</p>
<p align="left">
<div align="left">
<ol start="1">
<li>Oracle表数据的C/C++存取方法<br>
<ol start="0" type="a">
<li>Pro C/C++<br>
Pro C/C++是非常传统的接口,底层接口是 SQL-LIB,是一种在 C/C++代码里直接插入PLSQL语句实现oracle 数据库操作方法.虽然还是有很多公司依然采用这种接口方法,但是,一般来说,并不推荐,主要原因是,本身Pro C/C++有一套语法需要学习,另外,调试不便,多线程处理,多实例连接等情况,用起来比较复杂,而且不一定好用.</li>
<li>OCI<br>
OCI是最基础的接口,几乎是其他接口的基础。它的功能最强大,但是使用极其复杂。一般的程序员,看了极易头晕。好比是用windows sdk 编写windows程序一样,要初始化一大堆接口,一大堆句柄,处理一大堆信息。除非对速度要求极高的场合,一般最好不要用这个接口。</li>
<li>odbc<br>
odbc接口是基于OCI的高一级接口,相对来说,也很复杂,但是,vc在基于此上面封装了自己的类,用起来简单的多,但是,由于加了odbc接口层,相对来说,慢一些,对于大量数据的bulk操作,速度要慢很多,动态SQL功能也往往受一些限制.另外,odbc主要基于windows平台,unixodbc没有商业公司的支持,在unix/linux平台下基本上不会使用odbc接口.</li>
<li>ado及bde<br>
ado是ms力推的主要数据库接口,bde是borland力推的主要数据库接口
,都是基于odbc和oci, 由于经过用类接口封装,操作也很简单,但有windows平台的限制.</li>
<li>rw dbtools<br>
Rogue Wave dbtools也是直接调用oci,在几年前,是一套非常好用的商业版的数据库接口软件,可用于unix/windows,方便实用,甚至提供了数据库连接池,但是由于bug多,价格昂贵,用户并不多,尤其是进几年,更少见.但是其影响深远,对后来的C++接口的数据库存取接口起了样板作用.</li>
<li>otl<br>
otl是一套基于oci的数据库操作C++模板库接口,完全免费,提供全部源码(全部在头文件里面),操作极其简单,动态sql调用,bulk操作等,方便实用,速度极快.尤其是独具的流操作,&lt;&lt;操作符即可输入动态参数,&gt;&gt;操作符即可输出数据库记录数据,另人拍案叫绝.我本人一直都在使用.国内一些大的软件公司,例如亚信(Asiainfo),也把它作为oracle数据操作的主要接口.它的主页是http://otl.sourceforge.net/home.htm,值得研究一下.</li>
<li>occi <br>
OCCI是oracle 提供的C++调用接口,全名为 Oracle C++ Call Interface,在9i及其以后的版本中提供,
适用于unix/linux/windows,虽然底层基于oci,但是,调用非常简单,几乎就是jdbc的C++翻版.OCCI是向大家我力推的接口,并且在本文的后半部分进行作更详细的描述.它的帮助文档在http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96583/toc.htm</li>
</ol>
</li>
<li>OCCI接口<br>
本环节,将以windows环境下,详细介绍用vc6.0调用occi操作oracle数据库的方法.在unix/linux下,调用occi的方法,只是编译开关不同</li><br>
<ol start="0" type="a">
<li>安装<br>
在安装oracle的时候,请选中oci及occi.
<li>连接的参数<br>
和oci等接口一样,要求user,passwd,sid三个参数,如果是通过ipc连接或使用环境变量的SID,sid参数可以不用指定.sid的配置,可能涉及到sqlnet.ora和tnsnames.ora文件,请使用oracle自带的网络配置工具配置或直接手工编辑这两个文件.
<li>基本调用步骤<br>
调用步骤很简单,初始化环境,建立数据库连接,建立sql会话,输入动态参数,执行sql会话,取结果集,访问结果集,关闭结果集,关闭会话.程序退出时,关闭数据库连接,反初始化环境.以上是最多的步骤,例如,可能没有动态参数,也没有结果集的操作.另外,需要捕获异常.
<li>一个简单的例子<br>
<blockquote>

<blockquote>
<pre> 给出一个的例子,以便后面讲解
#include &quot;windows.h&quot;
#include &quot;occi.h&quot;<br> using namespace oracle::occi; <br> using namespace std;
int main(int argc,char *argv[])
{
Environment *m_Env=NULL ;<br> Connection * m_Conn=NULL;
char szUser[]=&quot;abc&quot;;
char szUser[]=&quot;ora123&quot;;
char szSid[]=&quot;sid000&quot;;
m_Env = Environment::createEnvironment();<br> m_Conn=m_Env-&gt;createConnection(szUser,szPasswd,szSid);<br> if(m_Conn==NULL)
{
Environment::terminateEnvironment(m_Env); <br> return -1;<br> }
Statement * localStatement=m_Conn-&gt;createStatement(<br> &quot;select f2 from test_tab where f1&gt;=:f1&quot;);<br> if(localStatement==NULL)<br> return -1;<br> localStatement-&gt;setInt(1,100);<br> ResultSet * rs = NULL;<br> try<br> {<br> rs=localStatement-&gt;executeQuery();<br> }<br> catch(SQLException &amp;e)<br> {<br> OutputDebugString(e.getMessage().data());<br> m_Conn-&gt;terminateStatement(localStatement);<br> return -2;
}<br>
if(rs==NULL)<br>
{<br>
m_Conn-&gt;terminateStatement(localStatement);<br>
return -3;<br>
}<br>
ResultSet::Status localStatus=rs-&gt;next();<br>
string localStr2;<br>
if(localStatus==ResultSet::END_OF_FETCH)<br>
{
return -3;<br>
}<br>

else<br>
{<br>
localStr2=rs-&gt;getString(1);<br>
}<br>
localStatement-&gt;closeResultSet(rs);<br>
m_Conn-&gt;terminateStatement(localStatement);<br> <br> m_Env-&gt;terminateConnection(m_Conn);
Environment::terminateEnvironment(m_Env);<br>
return 0;
} </pre>
</blockquote>
<li>occi调用分析<br>
使用的class: Environment,Connection,Statement,ResultSet.数据库异常类SQLException.非oracle定义类,直接使用编译器提供stl,例如string.<br>
获得环境的句柄 Environment::createEnvironment();<br>
建立数据库连接 m_Conn=m_Env-&amp;gt;createConnection(szUser,szPasswd,szSid);<br>
建立SQL会话 localStatement=m_Conn-&gt;createStatement(&quot;select f2 from test_tab where f1&gt;=:f1&quot;); 可以是任何plsql语句,包括动态sql.<br>
输入动态参数 localStatement-&gt;setInt(1,100);<br>
执行SQL会话并取结果集 rs=localStatement-&gt;executeQuery();<br>
访问结果集并判断结果集状态 ResultSet::Status localStatus=rs-&gt;next();<br>
获得结果集的数据 : localStr2=rs-&gt;getString(1);主意,字符类型字段取得的值是string的实例<br>
关闭结果集: localStatement-&gt;closeResultSet(rs);<br>
结束本条SQL会话 : m_Conn-&gt;terminateStatement(localStatement);<br>
关闭数据库连接 : m_Env-&gt;terminateConnection(m_Conn); <br>
反初始化环境 : Environment::terminateEnvironment(m_Env);<br>
注意,每一步操作时,都可能产生SQLException异常,最好能捕获并处理它.<br>
occi还提供Blob和Clob等class,以便blob及clob等类型的输入和输出.<br>
<br>
</li>
<li>编译开关设置<br>
由于使用了stl,vc要求使用特定的编译开关,才能保证编译通过,运行时,内存管理不出错.<br>
编译时,要定义WIN32COMMON,_DLL,_MT这三个宏.include路径应包含 %ORACLE_HOME%/oci/include<br>
连接时,要添加oraocci9.lib,msvcrt.lib,msvcprt.lib,lib路径应包含%ORACLE_HOME%/oci/lib/msvc<br>
<br>
<br>
</li>
</ol>
</ol>
不难看出,OCCI完完全全就是jdbc的c++版本
</div>
</body>
</html>

顶部
无双
荣誉斑竹
Rank: 14Rank: 14Rank: 14Rank: 14
天才猪



UID 4
精华 84
积分 5863
帖子 11390
活跃指数 0
LU金币 4248 个
LU金条 0 个
阅读权限 200
注册 2003-9-16
来自 杭州
 
发表于 2004-12-23 20:04  资料  个人空间  主页 短消息  加为好友 
强 期待freestream的后续版本






不要问我结果 我只研究过程与思路
无双客栈
顶部
javantsky
LU幼天使
Rank: 2



UID 32120
精华 0
积分 34
帖子 67
活跃指数 0
LU金币 2006 个
LU金条 0 个
阅读权限 20
注册 2005-5-25
 
发表于 2005-6-10 10:35  资料  个人空间  短消息  加为好友 
QUOTE(freestream @ 2004-12-19 23:54:30)
Pro C/C++是非常传统的接口,底层接口是 SQL-LIB,是一种在 C/C++代码里直接插入PLSQL语句实现oracle 数据库操作方法.虽然还是有很多公司依然采用这种接口方法,但是,一般来说,并不推荐,主要原因是,本身Pro C/C++有一套语法需要学习,另外,调试不便,多线程处理,多实例连接等情况,用起来比较复杂,而且不一定好用.</li>
 


难者不会,会者不难。

顶部
yifanernei
LU新生
Rank: 1



UID 52322
精华 0
积分 2
帖子 3
活跃指数 1
LU金币 4 个
LU金条 0 个
阅读权限 10
注册 2006-8-14
 
发表于 2006-8-18 10:43  资料  个人空间  短消息  加为好友  QQ
我用OCCI时发生ora-32108错误,就是在读一个字段很多的表时发生,是rs->next()抛出的

stmt->setXXX()函数无效啊
stmt->setSQL("select * from :1");
stmt->setString(1, "users");
cout <<stmt->getSQL() <<endl;    //取得串还是select * from :1

NUBER类型,要是想取成一个字串该怎么做?直接getString的话,只有第一条记录成功

顶部
freestream
荣誉斑竹
Rank: 14Rank: 14Rank: 14Rank: 14



UID 86
精华 1
积分 77
帖子 148
活跃指数 0
LU金币 6012 个
LU金条 0 个
阅读权限 200
注册 2003-9-22
 
发表于 2007-1-17 19:27  资料  个人空间  短消息  加为好友 
oerr ora 32108
32108, 00000, "max column or parameter size not specified"
// *Cause: The max column or parameter size is not specified.
// *Action: Specify the max size by setMaxColumnSize or setMaxParamSize.

不要使用select * 这种模式,而要列出要选择的字段。

顶部
 



当前时区 GMT+8, 现在时间是 2008-7-9 16:29
乐悠LoveUnix论坛-京ICP备05005823号

Thanks to Discuz!  © 2001-2007    Power by LoveUnix.net
Processed in 0.052765 second(s), 6 queries , Gzip enabled

清除 Cookies - 联系我们 - 乐悠LoveUnix - Archiver - WAP