LoveUnix » 行业应用 项目实施 » 企业程序设计纲要系列---occi接口访问oracle数据
让LU留住您的每

一天 让LU博客留住您的每一天
2004-12-19 23:54 freestream
&lt;html&gt;<br />&lt;head&gt;<br />&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=gb2312&quot;&gt;<br />&lt;title&gt;Oracle表数据 的C++存取接口&lt;/title&gt;<br />&lt;style type=&quot;text/css&quot;&gt;<br />&#60;&#33;--<br />body,td,th {<br />        color: #333399;<br />}<br />--&#62;<br />&lt;/style&gt;&lt;/head&gt;<br /><br />&lt;body&gt;<br />&lt;p align=&quot;center&quot;&gt;Oracle表数据的C++存取接口<br />&lt;/p&gt;<br />&lt;p align=&quot;left&quot;&gt;Oracle的表数据有多种存取方式,这里,着重介绍oracle 9i及其以后版本提供的C++接口,一种目前为止,最简单实用的编程接口&lt;/p&gt;<br />&lt;p align=&quot;left&quot;&gt;  <br />&lt;div align=&quot;left&quot;&gt;<br />      &lt;ol start=&quot;1&quot;&gt;<br />        &lt;li&gt;Oracle表数据的C/C++存取方法&lt;br&gt;<br />                &lt;ol start=&quot;0&quot; type=&quot;a&quot;&gt;<br />                        &lt;li&gt;Pro C/C++&lt;br&gt;<br />                          Pro C/C++是非常传统的接口,底层接口是 SQL-LIB,是一种在 C/C++代码里直接插入PLSQL语句实现oracle 数据库操作方法.虽然还是有很多公司依然采用这种接口方法,但是,一般来说,并不推荐,主要原因是,本身Pro C/C++有一套语法需要学习,另外,调试不便,多线程处理,多实例连接等情况,用起来比较复杂,而且不一定好用.&lt;/li&gt;<br />                        &lt;li&gt;OCI&lt;br&gt;<br />                    OCI是最基础的接口,几乎是其他接口的基础。它的功能最强大,但是使用极其复杂。一般的程序员,看了极易头晕。好比是用windows sdk 编写windows程序一样,要初始化一大堆接口,一大堆句柄,处理一大堆信息。除非对速度要求极高的场合,一般最好不要用这个接口。&lt;/li&gt;<br />                    &lt;li&gt;odbc&lt;br&gt;<br />                      odbc接口是基于OCI的高一级接口,相对来说,也很复杂,但是,vc在基于此上面封装了自己的类,用起来简单的多,但是,由于加了odbc接口层,相对来说,慢一些,对于大量数据的bulk操作,速度要慢很多,动态SQL功能也往往受一些限制.另外,odbc主要基于windows平台,unixodbc没有商业公司的支持,在unix/linux平台下基本上不会使用odbc接口.&lt;/li&gt;<br />                    &lt;li&gt;ado及bde&lt;br&gt;<br />                      ado是ms力推的主要数据库接口,bde是borland力推的主要数据库接口<br />,都是基于odbc和oci,        由于经过用类接口封装,操作也很简单,但有windows平台的限制.&lt;/li&gt;<br />                    &lt;li&gt;rw dbtools&lt;br&gt;<br />                      Rogue Wave dbtools也是直接调用oci,在几年前,是一套非常好用的商业版的数据库接口软件,可用于unix/windows,方便实用,甚至提供了数据库连接池,但是由于bug多,价格昂贵,用户并不多,尤其是进几年,更少见.但是其影响深远,对后来的C++接口的数据库存取接口起了样板作用.&lt;/li&gt;<br />                    &lt;li&gt;otl&lt;br&gt;<br />                      otl是一套基于oci的数据库操作C++模板库接口,完全免费,提供全部源码(全部在头文件里面),操作极其简单,动态sql调用,bulk操作等,方便实用,速度极快.尤其是独具的流操作,&amp;lt;&amp;lt;操作符即可输入动态参数,&amp;gt;&amp;gt;操作符即可输出数据库记录数据,另人拍案叫绝.我本人一直都在使用.国内一些大的软件公司,例如亚信(Asiainfo),也把它作为oracle数据操作的主要接口.它的主页是http://otl.sourceforge.net/home.htm,值得研究一下.&lt;/li&gt;<br />                    &lt;li&gt;occi &lt;br&gt;<br />                      OCCI是oracle 提供的C++调用接口,全名为 Oracle C++ Call Interface,在9i及其以后的版本中提供,<br />适用于unix/linux/windows,虽然底层基于oci,但是,调用非常简单,几乎就是jdbc的C++翻版.OCCI是向大家我力推的接口,并且在本文的后半部分进行作更详细的描述.它的帮助文档在http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96583/toc.htm&lt;/li&gt;<br />                &lt;/ol&gt;<br />        &lt;/li&gt;<br />        &lt;li&gt;OCCI接口&lt;br&gt;<br />          本环节,将以windows环境下,详细介绍用vc6.0调用occi操作oracle数据库的方法.在unix/linux下,调用occi的方法,只是编译开关不同&lt;/li&gt;&lt;br&gt;<br />                &lt;ol start=&quot;0&quot; type=&quot;a&quot;&gt;<br />                        &lt;li&gt;安装&lt;br&gt;<br />                  在安装oracle的时候,请选中oci及occi.            <br />                        &lt;li&gt;连接的参数&lt;br&gt;<br />                  和oci等接口一样,要求user,passwd,sid三个参数,如果是通过ipc连接或使用环境变量的SID,sid参数可以不用指定.sid的配置,可能涉及到sqlnet.ora和tnsnames.ora文件,请使用oracle自带的网络配置工具配置或直接手工编辑这两个文件.            <br />                        &lt;li&gt;基本调用步骤&lt;br&gt;<br />                  调用步骤很简单,初始化环境,建立数据库连接,建立sql会话,输入动态参数,执行sql会话,取结果集,访问结果集,关闭结果集,关闭会话.程序退出时,关闭数据库连接,反初始化环境.以上是最多的步骤,例如,可能没有动态参数,也没有结果集的操作.另外,需要捕获异常.            <br />                        &lt;li&gt;一个简单的例子&lt;br&gt;<br />      &lt;blockquote&gt;<br />        <br />                    &lt;blockquote&gt;<br />                      &lt;pre&gt;        给出一个的例子,以便后面讲解<br />        #include &amp;quot;windows.h&amp;quot;<br />        #include &amp;quot;occi.h&amp;quot;&lt;br&gt;  using namespace oracle::occi; &lt;br&gt;  using namespace std;<br />        int main(int argc,char *argv[])<br />        {<br />                Environment *m_Env=NULL ;&lt;br&gt;                Connection        * m_Conn=NULL;<br />                char szUser[]=&amp;quot;abc&amp;quot;;<br />                char szUser[]=&amp;quot;ora123&amp;quot;;<br />                char szSid[]=&amp;quot;sid000&amp;quot;;<br />                m_Env = Environment::createEnvironment();&lt;br&gt;                m_Conn=m_Env-&amp;gt;createConnection(szUser,szPasswd,szSid);&lt;br&gt;                if(m_Conn==NULL)<br />                {<br />                        Environment::terminateEnvironment(m_Env);        &lt;br&gt;                        return -1;&lt;br&gt;                }<br />                Statement * localStatement=m_Conn-&amp;gt;createStatement(&lt;br&gt;                &amp;quot;select f2 from test_tab where f1&amp;gt;=:f1&amp;quot;);&lt;br&gt;                if(localStatement==NULL)&lt;br&gt;                        return -1;&lt;br&gt;                localStatement-&amp;gt;setInt(1,100);&lt;br&gt;                ResultSet * rs = NULL;&lt;br&gt;                try&lt;br&gt;                {&lt;br&gt;                        rs=localStatement-&amp;gt;executeQuery();&lt;br&gt;                }&lt;br&gt;                catch(SQLException &amp;amp;e)&lt;br&gt;                {&lt;br&gt;                        OutputDebugString(e.getMessage().data());&lt;br&gt;                        m_Conn-&amp;gt;terminateStatement(localStatement);&lt;br&gt;                        return -2;<br />                }&lt;br&gt;        <br />                  if(rs==NULL)&lt;br&gt;<br />                  {&lt;br&gt;<br />                          m_Conn-&amp;gt;terminateStatement(localStatement);&lt;br&gt;<br />                          return -3;&lt;br&gt;<br />                  }&lt;br&gt;<br />                  ResultSet::Status localStatus=rs-&amp;gt;next();&lt;br&gt;<br />                  string localStr2;&lt;br&gt;<br />                  if(localStatus==ResultSet::END_OF_FETCH)&lt;br&gt;<br />                  {<br />                        return -3;&lt;br&gt;<br />                  }&lt;br&gt;<br />  <br />                  else&lt;br&gt;<br />                  {&lt;br&gt;<br />                          localStr2=rs-&amp;gt;getString(1);&lt;br&gt;<br />                  }&lt;br&gt;<br />                  localStatement-&amp;gt;closeResultSet(rs);&lt;br&gt;<br />                  m_Conn-&amp;gt;terminateStatement(localStatement);&lt;br&gt;                &lt;br&gt;                m_Env-&amp;gt;terminateConnection(m_Conn);<br />                Environment::terminateEnvironment(m_Env);&lt;br&gt;<br />                   return 0;<br />        }     &lt;/pre&gt;<br />              &lt;/blockquote&gt;<br />                    &lt;li&gt;occi调用分析&lt;br&gt;<br />                  使用的class: Environment,Connection,Statement,ResultSet.数据库异常类SQLException.非oracle定义类,直接使用编译器提供stl,例如string.&lt;br&gt;<br />                  获得环境的句柄 Environment::createEnvironment();&lt;br&gt;<br />                  建立数据库连接 m_Conn=m_Env-&amp;amp;gt;createConnection(szUser,szPasswd,szSid);&lt;br&gt;<br />                  建立SQL会话 localStatement=m_Conn-&amp;gt;createStatement(&amp;quot;select f2 from test_tab where f1&amp;gt;=:f1&amp;quot;); 可以是任何plsql语句,包括动态sql.&lt;br&gt;<br />                  输入动态参数 localStatement-&amp;gt;setInt(1,100);&lt;br&gt;<br />                  执行SQL会话并取结果集 rs=localStatement-&amp;gt;executeQuery();&lt;br&gt;<br />                  访问结果集并判断结果集状态 ResultSet::Status localStatus=rs-&amp;gt;next();&lt;br&gt;<br />                  获得结果集的数据 : localStr2=rs-&amp;gt;getString(1);主意,字符类型字段取得的值是string的实例&lt;br&gt;<br />                  关闭结果集: localStatement-&amp;gt;closeResultSet(rs);&lt;br&gt;<br />结束本条SQL会话 : m_Conn-&amp;gt;terminateStatement(localStatement);&lt;br&gt;<br />关闭数据库连接 : m_Env-&amp;gt;terminateConnection(m_Conn); &lt;br&gt; <br />反初始化环境 : Environment::terminateEnvironment(m_Env);&lt;br&gt;<br />注意,每一步操作时,都可能产生SQLException异常,最好能捕获并处理它.&lt;br&gt;<br />occi还提供Blob和Clob等class,以便blob及clob等类型的输入和输出.&lt;br&gt;<br />&lt;br&gt;<br />              &lt;/li&gt;<br />                    &lt;li&gt;编译开关设置&lt;br&gt;<br />                由于使用了stl,vc要求使用特定的编译开关,才能保证编译通过,运行时,内存管理不出错.&lt;br&gt;<br />                编译时,要定义WIN32COMMON,_DLL,_MT这三个宏.include路径应包含 %ORACLE_HOME%/oci/include&lt;br&gt;<br />                连接时,要添加oraocci9.lib,msvcrt.lib,msvcprt.lib,lib路径应包含%ORACLE_HOME%/oci/lib/msvc&lt;br&gt;<br />                &lt;br&gt;<br />                &lt;br&gt;<br />                    &lt;/li&gt;<br />                &lt;/ol&gt;<br />      &lt;/ol&gt;<br />      不难看出,OCCI完完全全就是jdbc的c++版本  <br />&lt;/div&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;

2004-12-23 20:04 无双
强 期待freestream的后续版本<br /><br />

2005-6-10 10:35 javantsky
<!--QuoteBegin-freestream+2004-12-19 23:54:30--><div class='quotetop'>QUOTE(freestream @ 2004-12-19 23:54:30)</div><div class='quotemain'><!--QuoteEBegin-->Pro C/C++是非常传统的接口,底层接口是 SQL-LIB,是一种在 C/C++代码里直接插入PLSQL语句实现oracle 数据库操作方法.虽然还是有很多公司依然采用这种接口方法,但是,一般来说,并不推荐,主要原因是,本身Pro C/C++有一套语法需要学习,另外,调试不便,多线程处理,多实例连接等情况,用起来比较复杂,而且不一定好用.&lt;/li&gt;<br />&nbsp;         <br /><!--QuoteEnd--></div><!--QuoteEEnd--><br /><br />难者不会,会者不难。

2006-8-18 10:43 yifanernei
我用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的话,只有第一条记录成功

2007-1-17 19:27 freestream
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 * 这种模式,而要列出要选择的字段。

页: [1]


Powered by Discuz! Archiver 5.5.0  © 2001-2006 Comsenz Inc.