UNIX(Linux适用)环境下使用occi远程连接Oracle数据库

来源:互联网 发布:vue.js 跨域请求api 编辑:程序博客网 时间:2024/05/17 08:46

 本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2011-05/35930.htm

有点空,和新上手occi的筒子们一起总结下。这篇内容其实挺有用的,对于新人来说不管哪一方面都是一个难点,如oracle、unix、c++与occi、shell、makefile、随便挑出一个名词就能够让人学上一阵子了。这篇文章呢,咱就来个彻底的大剖析,目的是连通oracle并进行C++的应用编程,并在这个基础上,对我们以后每个名词点的深入学习,提供入门的作用。
首先说一下我的环境,(注:大家的工作环境千差万别,但万变不离其宗,今天着重讲这个宗,所以不必拘泥于环境如何,看了我的操作,希望能使你举一反三,各种环境都能应对自如。)由于公司结构不得不形成如下的工作环境: 
本人主机:windows+secureCRT,所以我都是在使用远程
工作主机:unix+oracle(本人是oracle服务器端,其实客户端的问题不大后详细解释。)
数据库服务器:我只知道主机ip、数据库用户名及密码,其他都不知道。应该是大型主机。
这种环境貌似是三方,而实际工作是两方,因为我是用windows+secureCRT远程连接到unix工作机上,在unix上编写c++程序调用occi连接远程数据库服务器。所以描述重心是后两者的工作。至于secureCRT(可以是其他ssh工具)连接到unix则需要unix主机的ip地址、用户名及密码即可。
好了,下面的所有工作都是从登陆unix工作机这一刻开始,目标是在unix上编写一段连接远程oracle数据库的c++代码编译、连接、运行成功。各个击破吧!
第一步:编译、连接、运行C++程序,保证C++环境正确。
判断C++环境正确很简单,写个helloworld.cpp程序。代码如:

#include <iostream>    using namespace std;    main()    {    cout<<"hello world!"<<endl;    }  
这段代码要包含区别于c的元素,如using语句、cout等;
在shell里(sh、bash均可,个人更喜欢bash。)运行编译命令:
CC -c helloworld.cpp 
注意此处为大写的CC,小写的cc是编译c语言的)。结果会生成helloworld.o文件,继续运行连接命令:
CC -o helloworld.o

结果会默认生成a.out文件,此时当前目录下执行 ./a.out 出现打印的hello world!则为成功了(不要漏掉点和斜杠./),C++的编译环境就这样完成了。

unix默认都会支持CC的,至于gcc那是linux上的gnu项目开发的unix不一定支持

第二步:环境变量配置及撰写Makefile文件

1、Unix环境变量的配置
这里所说的环境变量是指oracle安装的dll等资源路径。因为若cpp文件经过编译链接,执行的时候需要occi资源的支持的,没有支持就会报错说.dll文件找不到之类。所以在makefile之前可以先把环境变量搞定了,内容很简单,看setenv.sh脚本代码: 
ORACLE_HOME = /opt/app/ora10g/product/10.2.0;                        export ORACLE_HOME    PATH = /usr/ccs/bin:$ORACLE_HOME/bin:$PATH;                export PATH    LD_LIBRARY_PATH = $ORACLE_HOME/lib32:$LD_LIBRARY_PATH;export LD_LIBRARY_PATH 

注释:

ORACLE_HOME变量是产品根目录,就是有很多文件的上一级;

PATH中第一个/usr/ccs/bin是我用的make路径,这样每次就不用绝对地址了,直接make就行了。

$ORACLE_HOME/bin:$PATH路径下包含oracle提供的可执行文件。

LD_LIBRARY_PATH=$ORACLE_HOME/lib32为后面的cpp对应执行文件提供dll。

这里多提一下lib和lib32的区别吧,在oracle9i还是10g或更新的oracle,lib32表示的是32位的环境,而lib表示的是64位的环境。所以根据个人情况改写吧,对于makefile也是这样的。

setenv.sh的使用:

setenv.sh是一个shell脚本,可以手动执行./setenv.sh,这样你就能享受这些环境变量了,也可以自动执行,关于怎样自动执行建议看看.profile等文件相关内容,(本人喜欢bash环境,每次运行bash时会自动依次执行.bash_profile、.bashrc,所以在.bashrc中加入/setenv.sh即可。

bashrc内容是:

注意看最后一行指明了要运行setenv.sh,这样就不用手动执行了

# .bashrc     # Source global definitions    if [ -f /etc/bashrc ]; then    . /etc/bashrc    fi     #open core file    ulimit -S -c unlimited > /dev/null 2>&1     #time zone   # User specific aliases and functions    . ./zxliu/setenv.sh  
2、Makefile的编写

在开始调用occi之前,首先需要在helloworld工作目录写一份Makefile文件,起名为makefile均可,make命令首先寻找Makefile,若不存在则会寻找makefile。

这时也要确认能否执行make命令,如果显示找不到,需要使用绝对地址执行make,如/usr/ccs/bin/make,默认unix均有make执行文件。

该Makefile内容如下:

###########################################   #Makefile for the OCCI demo programs   ###########################################   #ORACLE_HOME变量指明unix上的oracle产品路径    ORACLE_HOME=/opt/app/ora10g/product/10.2.0     #ORACLE_INCLUDES变量指明产品路径下的各种include文件$()表示取值,注明这些文件对于后面cpp编译中include occi头文件很重要    ORACLE_INCLUDES=-I$(ORACLE_HOME)/rdbms/demo \                    -I$(ORACLE_HOME)/rdbms/public \                    -I$(ORACLE_HOME)/plsql/public \                    -I$(ORACLE_HOME)/network/public \                    -I$(ORACLE_HOME)/precomp/public  #ORACLE_LIBS变量指明,链接库,编译程序的时候很重要,而INC和LIB是连接程序时候需要的。-I表示引入的是头文件,-L表示引入的是动态链接库,-l表示在-L中连接的文件如clntsh.dll文件和occi.dll文件。所以-l必须和-L配合使用。    ORACLE_LIBS=-L$(ORACLE_HOME)/lib32 -L$(ORACLE_HOME)/rdbms/lib32    INC=$(ORACLE_INCLUDES)    LIB=$(ORACLE_LIBS) -lclntsh -locci   #为方便取下面三个变量,目标为helloworld,源文件是helloworld.cpp,编译后文件helloworld.o    PRG=helloworld    SRC=../../helloworld.cpp    OBJ=helloworld.o   #下面是常规的makefile内容,$@表示依次取目标执行,这里只有helloworld一个目标。实际等价于   #CC -o helloworld helloworld.o 不过加入了include和lib文件。而helloworld.o需要后续完成    $(PRG):$(OBJ)            @echo "begin link......"           CC $(INC) $(LIB) -o $@ $(OBJ)    #helloworld目标依赖helloworld.o生成,所以该句就是编译.c生成.o文件。只不过加入了include和lib文件    $(OBJ):$(SRC)            @echo "begin compile......"           CC $(INC) $(ORACLE_LIBS) -c $(SRC)    #后面的内容不是make的内容了,而是make clean内容。比如想重新make之前,清除.o等文件,执行make clean语句   #.PRNOY语句表明 clean关键词是个伪目标。make不自动执行。    .PRONY:clean    clean:            @echo "Removing linked and compiled files......"           rm -f $(OBJ) $(PRG)  

写到这里,Makefile写完了,至于是否正确需要实际验证,因为每个人的oracle安装的不一样,所以里面的变量内容需要酌情更改,按照我说的更改即可。

验证方法很简单,执行make命令(或绝对路径用make),看是否能够编译.cpp并生成.o及最后的目标文件。一步一步检查看哪里存在问题。问题常常是oracle路径的问题要设置好。其实路径无非是编译需要的和链接需要的include及dll文件而已。所以根据这个思想去你的oracle目录下去找他们吧。 Makefile很关键,没写好的留言讨论。

验证代码如下:
//代码的目的就是验证makefile中oracle的头文件和lib文件路径是否正确了    
#include <iostream>    #include <occi.h>    using namespace std;    using namespace oracle::occi;    main()    {    Environment *env=Environment::createEnvironment();    cout<<"success"<<endl;   }  
注:编译好了,执行一下看是否输出success
第三步另起一篇,第三篇是在c++及makefile环境没问题的情况下如何访问远程oracle数据库了。
哈哈,说是交互编程,只负责登陆成功而已。

第三步,程序中登陆远程数据库。

1、验证unix有无配置远程数据库的信息(unix本地服务名设置)
unix cd到oracle的目录去,找/opt/app/ora10g/product/10.2.0/network/admin/tnsnames.ora文件。嗯是的,就是这个文件,tns名称服务文件,这个文件里指明了远程服务器的ip等信息。www.linuxidc.com无论装的是oracle服务端还是客户端还是instant client都必须找到这个文件,哪怕自己建(instant client可能要自己建)。vi tnsnames.ora 看是否有如下信息段: 
DBDEMO =
     (DESCRIPTION =
           (ADDRESS = (PROTOCOL = TCP)(HOST = 10.6.6.15)(PORT = 1521))
           (LOAD_BALANCE = no)
           (CONNECT_DATA =
                 (SERVER = DEDICATED)
                 (SERVICE_NAME = testDB)
                 (FAILOVER_MODE =
                       (TYPE = SELECT)
                       (METHOD = BASIC)
                       (RETRIES = 180)
                       (DELAY = 5)
                 )
            )
       )
这个信息段可以自定义多种信息,可以搜索看看,但核心是指明DBDEMO是unix端起得服务名,可以任意起名但cpp文件里要用到的,而HOST = 10.6.6.15是远程数据库所在地址。SERVICE_NAME = testDB看是远程数据库的名(全局数据库名,顺便提一下远程数据库要设置监听程序,你懂的,我有篇文章介绍了客户端和服务端的链接原理),这个名字必须要正确。保证这几个要点可以看2.
2、cpp文件的编写。
先看代码吧
#include <iostream>    #include <occi.h>    using namespace std;    using namespace oracle::occi;    main()    {    Environment *env=Environment::createEnvironment();//create succ       string name = "name";    string pwd = "pwd";    string dbname = "DBDEMO";       try   {    Connection *conn=env->createConnection(name,pwd,dbname);  cout<<"conn succ!"<<endl;    env->terminateConnection(conn);   }    catch(SQLException e)    {    cout<<e.what()<<endl;   }                Environment::terminateEnvironment(env);  cout<<"end!"<<endl;    }  
语句都能理解吧,就是建立链接,值得注意的是用户名和密码,以及DBDEMO名字,是unix配置的服务名,而不是远程oracle服务器的全局数据库名。本cpp是通过unix的network文件夹连接远程数据库服务器的。修改数据库内容就自己去学吧。还很多路要走。

ok,make、./helloworld 看看结果吧。

最后一步了,和远程数据库交互编程。

至此全部完成了,每一个细节点都要仔细推敲,这样就不会乱了。有问题留言。