摘 要: OCI(Oracle Call Interface)是Oracle公司提供的开发基于Oracle数据库应用程序的底层接口,它具有速度快、支持第三代编程语言、对Oracle数据库的控制功能强等优点。本文首先介绍了OCI接口的优点、应用范围、OCI程序结构,接着详细介绍了在MiroSoft VC++6.0中应用OCI来访问Oracle数据库,以实例的方式演示了SQL语句的执行过程,并且结合实例对OCI的一些函数与处理SQL语句的方法做了说明。
关键词: OCI,VC++6.0, SQL,Oracle数据库引言
开发基于Oracle数据库的应用程序,我们可以选择多种工具,不仅可以用一般的数据库开发技术,诸如ADO(ActiveX Data Objects)、ODBC(Open DataBase Connectivity)等等,同时,也可以用Oracle公司提供的专门的开发工具,诸如Pro C_C++,OCI(Oracle Call Intedace)等等。比较这几种方式,前者因为是通用技术,开发起来比较容易,但是有一个致命的弱点就是诸如ADO之类的通用技术的速度太慢,如果我们要开发管理海量数据的数据库,比如影像数据库,那么,这种速度我们是不能忍受的。而OCI虽然开发起来难度大一些,但是它的速度极快,而且是一种底层接口,几乎可以操纵Oracle数据库的任何对象。
一、OCI简介
1.OCI概述
OCI(Oracle Call Intedace,即0racle调用层接口)是Oracle公司提供的由头文件和库函数等组成的一个访问Oracle数据库的应用程序编程接口(application programming interface API),它允许开发人员在第三代编程语言(包括C, C++, COBOL 与 FORTRAN)中通过SQL(Structure Query Language)来操纵Oracle数据库,而且OCI在一定程度上支持第三代编程语言(诸如C, C++, COBOL 与 FORTRAN)的数据类型、语法等等。OCI的显著特点是全面支持Oracle的面向对象技术,同时OCI还具有如下的一些特点:
1)非常有利于应用程序的设计;
2)高度控制应用程序的执行;
3)允许开发人员应用已熟悉的第三代程序设计语言来应用OCI;
4)支持动态SQL;
5)几乎所有的Oracle的开发工具都支持OCI;
6)通过回调技术(callbacks)来实现动态绑 定与定义;
7)通过OCI的描述函数可以获取Oracle数据库的各种参数;
8)增强了数组在DML(data manipulation language)语言中的应用;
OCI接口支持Windows NT和Windows 95/98/2000/XP操作系统,它所支持的C语言编译器包括Borland C++和MiroSoft VisualC++等。在使用0CI开发Oralce数据库应用程序之前,应首先安装这些操作系统和C语言编译工具。在选择安装OCI开发工具包后,Oracle安装程序将0CI文件拷贝到oracle主目录内的以下子目录中:
..BIN\:执行文件和帮助文件:
..\OCIINCLUDE头文件;
..OCI\LIB\其中包含仍bc和\msvc两个子目录,分别用于存储支持Borland C++和MiroSoftVisualC++的OCI库文件,这些库文件与OCI源程序编译后所产生的目标文件进行链接生成可执行程序。一个应用OCI程序的生成可执行应用程序的过程如图1:
图1
由此,我们可以看出:一个应用OCI的应用程序与其它不连接数据库的应用程序生成可执行程序的过程没有区别,在程序的链接阶段OCI库与源程序的目标代码文件链接而生成可执行程序。
2.OCI程序的基本结构
在一个应用程序中,我们是通过调用OCI提供的库函数来实现对Oracle数据库的操纵。OCI提供了上百个函数,都是以OCI开头的函数,比如创建OCI环境的OCI函数:OCIEnvCreate()。OCI函数的一个特点或者说是难点就是它的参数特别多,函数往往都有十几个参数。
一般情况下,一个OCI应用程序都是在多用户环境下的。在一个n层网络结构的配置中,客户端的应用程序需要完成一些数据操纵,包括交换数据与处理数据。一个OCI应用程序的基本结构包括:
1)初始化OCI环境和线程;
2)分配必要的句柄与数据结构;
3)建立与数据库的连接以及创建用户会话;
4)通过SQL与Oracle服务器交换数据,而后再做数据处理;
5)结束用户会话与断开与数据库的连接;
6)释放在程序中所分配的句柄。
示意如图2:
图2 OCI程序的基本结构 3.在OCI应用程序中执行SQL的步骤
结构化查询语言(SQL Structure Query Language)是操纵关系数据库的主流语言,目前,几乎所有的商业数据库软件都支持SQL语言。标准的SQL语言按照它的功能不同,可以分为查询、操纵、定义以及控制四种类型。每一种都有若干关键字,具体如表1所示。
SQL功能 |
关键字 |
查询DQL
(Data Query Language) |
SELECT |
操纵DML
(Data Manipulation Language) |
INSERT,DELETE,UPDATE |
定义DDL
(Data Define Language,) |
CREATE,DROP |
控制DCL
(Data Control Language) |
GRANT,REVOKE |
表1
一个SQL语句在OCI应用程序中的执行步骤一般如下:
1)准备SQL语句。调用函数OCIStmtPrepare();
2)在SQL语句中绑定需要输入到SQL语句中的变量。对于DML语句来说,由于它带有输入变量,我们可以通过调用一个或者多个函数OCIBindByPos()、OCIBindByName()等把输入变量的地址绑定在DML语句中的占位符中;
3)执行SQL语句。调用OCIStmtExecute()函数。对于DDL语句到这一步就完成了一个语句的执行;
4)描述SQL中的输出的数据。如果有必要的话,我们可以调用函数OCIParamGet()与 OCIAttrGet()来获取我们所读取的记录的字段个数、字段的数据类型以及字段数据定义的最大长度。
5)定义输出变量。对于DQL(Data Query Language)语句,即SELECT的查询语句,需要定义一定数量的变量用来接受所选择列的数据。我们可以调用OCIDefineByPos()、OCIDefineObject()函数等来完成这个任务。也就建立SQL语句所返回的数据与应用程序中变量的关系。
6)获取数据。我们可以调用函数OCIStmtFetch()来把用SELECT选中的记录的数据赋予应用程序中的变量。
过程以及过程中调用到的函数如图3所示:
OCIBindByPos()
OCIBindByName()
OCIBindObject()
OCIBindDynamic()
OCIBindArrayOfStruct() |
OCIParamGet()
OCIAttrGet() |
OCIDefineByPos(), OCIDefineObject()
OCIDefineDynamic()
OCIDefineArrayOfStruct() |
图3
虽然Oracle对标准的SQL语言有所扩展,但它也是建立在标准的SQL语言的基础之上。上图是一个一般SQL执行的流程图,对于不同的SQL语句,所需要的步骤也有所不同。对于DCL与DDL语句,由于没有数据的输入与输出,仅仅涉及到一些权限与定义或者删除数据库中的对象的问题,因此只需要上图的第一步与第三步便可以了。而对于DQL与DML语句,由于有数据的输入与输出,因此需要的步骤就多一些。其实,DML也可以只用两步来完成。这是因为DML语句中仅仅涉及数据的输入(即,数据从应用程序到数据库端),因此我们可以把所要输入的数据以字符串的形式放在SQL语句中。而DQL不仅可能有数据输入,而且也有数据输出(从数据库端到应用程序),因此,一个DQL语句需要如上图的六个步骤。
三、OCI在VC++6.0中的应用
第二部分是对OCI接口的简单介绍。下面我们就谈谈OCI在VC++中的应用。为了方便我们对应用OCI的理解,就以一个简单的MS VC++6.0的工程为例,把对OCI的解释放在这个工程之中。
1. 数据准备
首先,我们启动SQL *PLUS,然后我们可以以用户名SYSTEM,口令manager,主机字符串MYORACLE(其中MYORACLE是一个数据库实例的名称)登录到SQL Plus,用SQL语句来建立表:
1)创建表
CREATE TABLE t1
(ID NUMBER(5),
StudentID NUMBER(10),
Name VARCHAR2(12),
Old NUMBER(3),
Stature NUMBER(3,2));
表已创建。(执行CREATE后,有“表已创建。”,的提示,则说明我们创建表t1成功)。
2)添加数据
我们用INSERT语句来添加数据,如下:
INSERT INTO t1 VALUES
(1,20020101,'李华',23,1.77);
已创建 1 行。
用如此的格式加入几条记录,最后我们用“SELECT * FROM t1”来看一下表t1里的数据,如下:
ID STUDENTID NAME OLD STATURE
-- -------- ----- --- ------
1 20020101 李华 23 1.77
2 20020102 张万里 25 1.75
3 20020103 赵鹏成 27 1.84
4 20020104 高明就 28 1.85
5 20020105 王小明 55 1.99
执行COMMIT命令,以便保存数据到数据库端。
这样我们就在Oracle的数据库中建立了一个名称为t1的表;我们可以同样的方式建立另外一些表。
如果你不想自己建立表与输入数据,那么我们可以用Oracle数据库中自带的数据。首先,启动SQL *PLUS,然后我们可以以用户名SCOTT,口令tiger,主机字符串MYORACLE(你所建立的数据库实例的名称)登录SQL *PLUS;若登录成功,我们可以用“SELECT TABLE_NAME FROM USER_TABLES”命令来查看SCOTT用户的所有的表,一般情况下,我们可以看到SCOTT用户有诸如DEPT、EMP等等表。那么我们就可以利用这些数据来验证我们的应用程序了。若SQL *PLUS有“ERROR:ORA-01017: invalid username/password; logon denied”这样的提示,那么,说明数据库MYORACLE中没有SCOTT这个用户。我们可以在安装Oracle数据库的目录(比如你的Oracle数据库安装在C:上)C:\Oracle\Ora81\RDBMS\ADMIN下找到SCOTT.SQL文件,然后以system/manager(这个用户应该有创建用户与表的权限)登录到SQL *PLUS,执行命令:“@C:\\Oracle\\Ora81\\RDBMS\\ADMIN\\SCOTT.SQL;”,或者把SCOTT.SQL文件打开后把文件的内容copy并且在SQL *PLUS中执行,这样就建立了SCOTT用户以及他的一些表,比如表DEPT的数据如下:
DEPTNO DNAME LOC
------ ---------- -------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
2.建立一个工程
1) 打开VC++6.0,选择File/new,在Projects中选择建立的工程类型为MFC AppWizard(exe),然后我们键入工程名字,比如键入COCIExample,同时为工程选择一个路径,并且选择创建新工程。
2) 为了我们把注意力集中在OCI的应用上,我们建立一个基于对话框的应用程序。因此在MFC AppWizard的step 1中选择Dialog Based;在step 2到step 4中,我们都选择缺省值。这样就建立了一个基于对话框的应用程序。
3) 去掉对话框上的所有控件;
3.加入OCI的头文件与库文件
在安装Oracle数据库的时候,若选择了OCI选项,那么Oracle的主目录下就有OCI这样的目录(若你的Oracle数据库安装在C:的根目录下,则有“C:\Oracle\Ora81\oci”,具体在OCI概述中已经介绍)。
首先,加入OCI的一些头文件。在VC++6.0的主菜单上“Tools/Options”的对话框中的“Directories”选项下的“Include files”内容中加入OCI头文件所在的路径“C:\Oracle\Ora81\oci\include”,最后“Tools/Options”的“Include files”的内容如图4所示。同时在工程COCIExample的OCIExampleDlg.h文件中包含头文件oic.h。
图4
其次,加入OCI库文件。就是要加入“C:\Oracle\Ora81\oci\lib\msvc”目录下的文件oci.lib与ociw32.lib。在VC++6.0的主菜单上“Tools/Options”的对话框中的“Directories”选项下的“Libarary files”内容中加入OCI库文件所在的路径“C:\Oracle\Ora81\oci\lib\msvc”,最后“Tools/Options”的“Libarary files”的内容如图5所示。并且在VC的主菜单的“Project\Add to Project\Files”中把这两个OCI库文件加入工程中。
图5
加入OCI的头文件与库文件,也可以采用最简单的办法,即把上述的文件copy到我们所创建的工程的所在路径,OCI库文件oci.lib与ociw32.lib用“Project\Add to Project\Files”加入所创建的工程就可以了。
4.在工程COCIExample中应用OCI
如图2所示,在一个应用程序中应用OCI可以分为六个步骤,下面我们就以OCI程序的步骤为主线来介绍OCI在VC++6.0中的应用。
4.1创建OCI环境
首先,在本工程的COCIExampleDlg类中,加入public类型的一些必须的OCI句柄。如代码4.1.1
代码4.1.1:
|