OCI
2011年12月05日
OCI编程的一般过程
与OCI7.3中使用的宿主语言定义变量存储空间(很拗口,不用管它)的方式不同,OCI9以后已不再使用原有的变量结构来初始化及维护数据库的信息,而改用句柄的形式来和Oracle数据库进行交互。将常用的句柄定义在一个结构内,方便程序维护:
?
1
2
3
4
5
6
7
8
9
typedef struct _OCI_HANDLE
{
OCIEnv *phEnv; //环境句柄,要使用oracle数据库,必须首先获得环境句柄
OCISvcCtx *phService; //oracle的服务句柄,也可以说是连接句柄。
OCIError *phErr; //oracle的错误句柄,可以获取错误信息
OCIStmt *phStmt; //oracle的语句描述句柄
OCIServer *phServer; //Oracle的服务器句柄
OCISession *phSession; //Oracle会话句柄
}OCIHANDLE, *LPOCIHANDLE;
OCI9编程的一般步骤有:初始化环境句柄、生成其他各类句柄、建立数据库连接进行登录、执行SQL语句,对返回的结果进行处理、终止用户会话,断开连接,释放各种句柄。
上图给出OCI初始化的一个过程,OCI能初始化成功的前提当然是系统中已经安装或设置了Oracle的client端(在本文第四节有介绍)。其中步骤(3)到(7)都分别调用OCIHandleAlloc()函数进行分配,顺序可以不同,它们都只依赖环境句柄;步骤(1)和(2)可以使用OCIEnvCreate()函数替换掉,这两种的初始化OCI环境的方法在不同的使用条件下是不同的,一般建议使用OCIEnvCreate()代替OCIInitialize()和OCIEnvInit(),因为OCIInitialize()和OCIEnvInit()主要是为了backwards-compatible。而如果是编写DLL更是应该使用OCIEnvCreate()函数,user‘guide是这样说的:
If you are writing a DLL or a shared library using OCI library then this call should definitely be used instead of OCIInitialize() and OCIEnvInit() call.
OCI各句柄初始化完毕后,接下来就是连接数据库,如下图:
数据库连接好后可以执行SQL语句:一条SQL语句在OCI应用程序中的执行步骤一般如下:(1)准备SQL语句。(2)在SQL语句中绑定需要输入到SQL语句中的变量。(3)执行SQL语句。(4)获取SQL中的输出描述。(5)定义输出变量。(6)获取数据。具体过程及过程中调用的函数如下图所示。对于SQL中的定义语句(如CREATE,DROP)和控制语句(如GRANT,REVOKE),由于没有数据的输入输出,只需要图2中第一步和第三步即可。操作语句(如INSERT,DELETE,UPDATE)则需要执行前三步。而查询语句(如SELECT)不仅可能有数据输入,而且也有数据的输出,因此需要执行六个步骤。
OCI编程的一般过程还是很清晰的,流程图都是一条线………
三、单次查询返回多行结果的实现
设计的时候老大要求要像原有接口库那样一次查询返回多行,然后再在本地进行处理,以减少对数据库的访问。这本来是一个很正常的要求,但后面看了好些开源的OCI封装,发现它们的demo里都没有给出如何fetch多行……… 比如写的比较好的ocilib,demo中就没有给出(至少是以前的版本没给出,现在就不知道了),在写完这个OCI接口库大概半年后,再看ocilib的代码OCIDefineByPos()函数时,发现倒数第三第四个参数都是指针,说明可以fetch多行。进而发现ocilib可以通过OCI_SetFetchSize()函数来设置查询返回的行数。但为什么不在demo里给一个示例呢?就连该版本的文档里也没有这个函数的说明。很奇怪!没办法还是自己动手丰衣足食,使劲啃user’guide。
需要fetch多行,首先要考虑执行select语句后,接收到数据放在什么地方?当然是放在缓冲区里了,在OCI里通过不同的变量函数绑定来告诉oracle client把从数据库取到的数据存放在什么地方。这里使用OCIDefineByPos()函数。下面以每次取100行为例给出具体步骤:
1. 分配足够大的缓冲区m_pData = new unsigned char[m_DataLen * 100]。m_DataLen表示数据库表中每一行的长度(各个列长度之和),这样需要使用unsigned作Buffer,因为如果使用有符号char则取带时间的表会有问题。
2. 根据各列的长度来定义各列在缓冲区中的位置:
?
1
2
3
4
5
6
7
8
9
10
OCIDefineByPos(m_hOCI.phStmt, //语句句柄
&(m_vecColInfo.phdefine),//定义句柄
m_hOCI.phErr,
i+1, //列序号
(ub1 *)(&(m_pData[pos])), //各列的位置pos等于当前列之前各列长度和乘以100
m_vecColInfo.collen, //对应列的长度 SQLT_STR,
(m_vecColInfo.indp), //指示器,因为每次最多要取100行,所以indp应设为维数为100的数组。
(m_vecColInfo.rlenp), //返回数据的真实长度,这里也应把rlenp设为维数100的数组
0,
OCI_DEFAULT));
m_vecColInfo为保存各列信息的vector。值得注意的是OCIDefineByPos()的第八和第九个参数:第八个参数是指示器参数,在OCIStmtFectch后只是所取的对应数据是否完整(0表示完整),由于要取100行,则在m_vecColInfo中每一个列元素对应的结构中都应定义indp[100]的数组。第九个参数用于返回所取数据的实际长度,因此也需要在一个列元素的结构体中定义rlenp[100]的数组。还有一个需要注意的是第四个参数里的pos,pos用于指定该列保存在Buffer中的起始位置。如下表是数据库中某表,执行select查询该表前100行后,数据在缓冲区m_pData中保存数据的形式如图4:
CarKey
MakeKey
ModelKey
ColorKey
Year
1
1
1
2
2003
2
2
1
3
2005
3
2
1
2
2005
…….
…….
……..
……..
………
100
2
1
1
2006
上图可以看到OCI在fetch多行时,先将第一列的100行数据放入m_pData中,然后以列为单位每次取100行放入m_pData。因此pos变量的赋值应写为:pos += 100 * (m_vecColInfo[i-1].collen); 其中collen代表该列的长度。
3. 获取数据:
?
1
2
3
4
5
OCIStmtFetch(m_hOCI.phStmt,
m_hOCI.phErr,
100,//每次取100行的数据
OCI_FETCH_NEXT,
OCI_DEFAULT);
第三个参数设置为100后,执行OCIStmtFetch完毕后数据就填充到缓冲区中。这里需要注意的是最后一个fetch,因为最后一次fetch时数据库表中往往已经不足100行,所以每次执行OCIStmtFetch()函数完毕要需要检查其返回值,当返回值为OCI_NO_DATA时使用:
?
1
2
3
4
5
6
OCIAttrGet(m_hOCI.phStmt,
OCI_HTYPE_STMT,
(dvoid *) &row_fetched,
(ub4 *) NULL,
(ub4) OCI_ATTR_ROWS_FETCHED,
m_hOCI.phErr);
row_fetched将返回剩下的行数,倒数第二个参数为OCI_ATTR_ROWS_FETCHED,在oci.h中是这样定义的:
#define OCI_ATTR_ROWS_FETCHED 197 /* rows fetched in last call */
在oci10中这里没有任何问题,但在一些较早的oci9版本中找不到OCI_ATTR_ROWS_FETCHED的定义……… 也就是说无法fetch多行?!迫不得已只能用oci10。可能ocilib在demo中没有fetch多行的示例也是出于这个考虑吧。
四、Oracle即时客户端(instantclient)的配置
过去使用OCI需要安装oracle的客户端,Oracle的普通客户端一般都很庞大,Windows平台下的客户端就有700M。Oracle公司在10g版本后推出了大小只有30M的InstantClient(即时客户端)作为oracle的访问客户端。不需要安装就可以访问Oracle的服务器。
Windows平台下instantclient的配置和使用:
下面以C:\Oracle为例介绍具体的配置过程。
1.将instantclient的basic包及sqlplus包中所有文件解压至C:\Oracle。
2.配置系统的环境变量:
• 将 C:\Oracle 添加到 PATH 中(位于其他 Oracle 目录之前)。例如,在 Windows 2000 上,依次单击“开始”->“设置”->“控制面板”->“系统”->“高级”->“环境变量”,编辑系统变量列表中的 PATH。WindowXP上,右击“我的电脑”->“高级”->“环境变量”。
• 添加用户环境变量 TNS_ADMIN 设置为C:\Oracle。
• 设置必要的 Oracle 全球化语言环境变量, 添加用户环境变量NLS_LANG 中文对应的字符集是 SIMPLIFIED CHINESE_CHINA.ZHS16GBK
3. 一共设置以下三个环境变量(以解压缩目录C:\Oracle为例)环境变量名 变量值
path C:\Oracle
TNS_ADMIN C:\Oracle
ORACLE_HOME C:\Oracle (可选)
NLS_LANG SIMPLIFIED CHINESE_CHINA.ZHS16GBK
4. tnsnames.ora和sqlnet.ora文件,这两个文件可以在所要访问的Oracle数据库服务器的$ORACLE_HOME/network/admin目录下找到,把tnsnames.ora中的服务器主机名改为ip地址即可。需更改时注意备份原来的文件。
5. 配置完毕后进入C:\Oracle运行sqlplus.exe登陆对应的数据库测试是否设置正确。在windows下使用instantclient时,需要将instantclient的sdk包中的include和lib加到工程中。
Unix平台下instantclient的配置和使用:
本例中使用solaris_x86_10.2.0.2为客户端
1. 将instantclient_solaris_x86_10.2.0.2中的basic、sqlplus和sdk解压至同一目录,用chmod将该目录下的所有文件设为可读写,比如:chmod
发表评论
-
WIN下用exp备份保存最近N天方案
2012-01-20 01:34 582WIN下用exp备份保存最近N天方案 2010年06月03日 ... -
[转]命令行创建快捷方式的批处理脚本
2012-01-20 01:34 1305[转]命令行创建快捷方式的批处理脚本 2010年10月27日 ... -
自动化测试规范小结
2012-01-20 01:34 745自动化测试规范小结 20 ... -
自动获取CPU使用率的脚本
2012-01-20 01:34 948自动获取CPU使用率的脚本 2011年04月28日 一个 ... -
业务组件学习资料
2012-01-20 01:34 581业务组件学习资料 2011 ... -
2012-1-12
2012-01-19 09:24 6052012-1-12 2012年01月12日 瀹剁┓浜轰 -
怎么使用quicktime
2012-01-17 01:58 753怎么使用quicktime 2011年1 ... -
ROM修改制作工具软件集合
2012-01-17 01:58 1129ROM修改制作工具软件集合 2012年01月11日 1. ... -
游戏编程101
2012-01-17 01:58 628游戏编程101 2011年11月21 ... -
MonoTouch:用.net开发iPhone应用
2012-01-17 01:58 578MonoTouch:用.net开发iPhone ... -
[转]GCC笔记
2012-01-15 21:15 652[转]GCC笔记 2010年03月23日 The His ... -
系统调用
2012-01-15 21:14 579系统调用 2009年08月26日 系统调用在用户空间 ... -
关于cgi库
2012-01-15 21:14 624关于cgi库 2009年07月02日 目前Web技术中生 ... -
嵌入式WEB服务器BOA的移植方法(三)
2012-01-15 21:14 534嵌入式WEB服务器BOA的移 ... -
SAMSUNG S3C2440的简易BootLoader ㈢
2012-01-15 21:14 570SAMSUNG S3C2440的简易BootLoa ...
相关推荐
oracle最新OCI文件,兼容一切版本! 本地安装的是64位的Oracle,但由于Navicat仅支持32位的,因此我们还需下载一个32位的客户端。 解决方案 下载32位客户端,配置进navicat中。 第1步:下载 最新OCI文件最新...
Oracle 调用接口 (OCI) 是最全面、性能最高、基于原生“C”语言的 Oracle 数据库接口,它可以提供 Oracle 数据库的全部功能。OCI 为构建各种语言专用接口(如 Oracle JDBC-OCI、ODP.Net、Oracle 预编译器、Oracle ...
然后运行Navicat for Oracle,在菜单栏依次展开“工具”——“选项”——其他——OCI——OCI.DLL指定到刚复制过去的OCI.DLL位置。然后确定,退出Navicat再次运行并配置好连接,这样即可连接数据库。
然后运行Navicat for Oracle,在菜单栏依次展开“工具”——“选项”——其他——OCI——OCI.DLL指定到刚复制过去的OCI.DLL位置。然后确定,退出Navicat for Oracle再次运行并配置好连接,这样即可连接数据库。
OCI
各windows版本下的oci.dll oci_10.2.0.5.dll oci_11.1.0.7.0.dll oci_11.2.0.4.0.dll oci_12.2.0.1.0.dll oci_21.3.0.0.0.dll
连接数据库时提示oci错误,使用这个oci.dll可以解决连接问题 11.2版
oci函数的详细介绍 和应用实例 OCI 连接过程比较复杂,除了分配设置各个基本句柄外,还要明确彼此之间的联系,大致流程如下: 创建环境句柄: OCIEnvCreate(&envhp;, …); 创建一个指定环境的错误句柄: ...
oracle oci11g 下载 用于navicat for oracle
这个包包含在LINUX安装OCI8和PDO_OCI扩展所需要的安装包.
C++实现的OCI操作Oracle数据库类,基于ocilib-4.3.3-windows.zip实现,OCI的资源可以直接到官网下载。 C++实现的OCI操作Oracle数据库类,基于ocilib-4.3.3-windows.zip实现,OCI的资源可以直接到官网下载。
oci头文件及库文件
对数据库的访问是通过调用OCI库函数实现的,若将C语言作为宿主语言,那么ORACLE数据库调用其实就是C程序中的函数调用,一个含OCI调用的C程序其实就是用C语言编写的应用程序。这样的程序既具有SQL语言非过程性的优点...
oracle oci 数据库开发 库和头文件, lib , .h , 下载
php7.1 oci8扩展 内含php_oci8.dll php_oci8_11g.dll php_oci8_12c.dll 实测可用
64位OCI.DLL 64位 系统 使用 PL/SQL必用、 PYTHON CX_ORACLE 必备
OCI例子OCI使用例子,本断代码为OCI使用实例
oracle10G和11G的OCI.dll,主要用于navicat工具;oracle10G和11G的OCI.dll,主要用于navicat工具
oracle 10g 的oci dll
OCI(Oracle Call Interface) Oracle调用接口(OCI)是最全面的,高性能的,本土的非托管访问ORACLE的官方接口。