??xml version="1.0" encoding="utf-8" standalone="yes"?> Oracle Database Development (7). The thinking of the OCI example . Vert Melon Jun 26,2007 The central content in this article is about the common operations with Oracle . Just 1. Connection Connection is surely a first step done with the database . OCI provides two mode of a. Single User, Single Connection Either OCIEnvCreate() or ( OCIInitialize() and OCIEnvInit() ) allocates a environment There is also a very important handle , which appears in mostly OCI calls . That is the After the preparation of Environment and Error , we will come to the actual code about Is is a very good custom that release the resource allocated at first in an order when The corresponding functions in the example listed as follows : You can change the content of the file Main.cpp to implement the different operation . #include "OCIDB.h" 2. Execute non-query SQL Non-query SQL means that SQL doesn't return any data , such as create , insert , delete At first you should allocate a statement handle in the envionment handle. A statement After finished the steps above , call OCIStmtExecute() to execute the statement. For DDL You may use these code statements in Main.cpp as the following : insert into liwei_test (id,name,note)values(1,'aABD','cadsf') This statement is a simple one to insert some data known. When you prepare a SQL statement insert into liwei_test (id,name,note)values(:id,:name,:note) A. One-off bind with a predefine structure #include "OCIDB.h" #include "OCIDB.h" Notice : The class function starts with "User" is a series which performs a common template . In this section i'd like to introduce a simple query example about the select statement which #include "OCIDB.h" UserSelect OCIHandleAlloc() , OCIStmtPrepare(), OCIStmtExecute() and then the OCIAttrGet() ! This example is just for a demonstration or a accidence . You mush not stop here only . ------------------------------------------------------------------------------------------------------- Oracle数据库开??.OCICZ开发说?/p>
草木?/p>
2007-6-26 q篇文章的主要内Ҏ(gu)介绍的常见的OCI数据操作。可以顺着文章思\l合OCI 一、数据库q接 数据库连接是操作数据库的W一步。OCI提供?jin)两U模式的q接Q即单用?br>单连接和多用户多q接。我q里的OCICZ也分别提供了(jin)两种实现方式?/p>
a.单用P单连?br> ----------------------------------------------------------------------------- 不管是OCIEnvCreate()q是(OCIInitialize()和OCIEnvInit())都分配了(jin)一个数据库环境?br>柄。我q里定义?jin)私有成员变量m_pOCIEnv用来存储环境句柄?/p>
OCI中还有一个很重要的句柄,l常出现在OCI调用q程中。这是错误句柄。错?br>句柄理在OCI数据操作中出现的各类错误Q如果在调用中出错,可以把错误句?br>传递给OCIErrorGet()来获取更多的错误信息?br> OCIException::CheckError() 是一个完整的错误处理CZ?br> 在程序结束时手工释放资源是很好的?fn)惯Q可参见OCIDB::Single_Disc()?br> 如果应用E序对单一数据库连接需要维护多个用户会(x)话,需要用另一U方式了(jin)?br> 你可以自行更改Main.cpp内容以完成不同的数据操作?br> 二、执行无q回值的SQL语句 q类语句一般包括create , insert和delete{等Q无q回D句一般也可以理解为DDL 完成上面步骤后,可以调用OCIStmtExecute() 执行SQL语句?jin)?br> 大多数DML语句或者一些查?带where条g?需要向SQL传递一些数据,下面的例?br>是在E序~译时就已经知道要传递的数倹{?/p>
insert into liwei_test (id,name,note)values(1,'aABD','cadsf') insert into liwei_test (id,name,note)values(:id,:name,:note) q节主要介绍一个简单的查询例子Q例子中的查询列在执行前已经知道?br> 查询语句q回数据库中所需数据Q执行查询时必须要定义外部的输出变量或者变 #include "OCIDB.h" q个例仅做演C。不q不必仅停留于此Q如要提高,l合在线文多练卛_?br>q个例子的代码在某些斚w昄不够规范Q如未在传g使用constQ这也是以后 Oracle Database Development (6). A first exploration of OCI Vert Melon Jun 25,2007 1.Preface Last time , i provided a full example of OCI , which contains the actual code of connection As the same as Pro*C you might confirm that you have installed it correctly . Look at this The main platform we use here is Linux . And the Windows ? How can i config it in Windows ? What is the Oracle Call Interface? The Oracle Call Interface (OCI) is a set of low-level APIs (Application Programming Interface Calls) Also I have found a official explaination about the choice between Pro*C and OCI . 3.Obsolescent OCI Routines After get through the section "Something you should know" , you may find some strange It's time to make out the source file , and the first one is Makefile which is a trunk in a project . Notice that the head files of OCI are put in two directories and the lib file is libclntsh.so.9.0 [root@liwei oci]# make clean; [OCIException.o] [Exception.o] [OCIError.o] [Main.o] [link] ... That's good . Take a rest for next step . ------------------------------------------------------------------------------------------------------- Oracle数据库开??.OCI应用初探 草木?/p>
2007.6.25 在上一ơ,我提供了(jin)一个完整的OCICZQ内容包括数据库q接和SQL操作的实际代码?br>当然一个小例子不可能包括所有内容,不过我认为对初学者是一个不错的开始?/p>
与Pro*C一P需要确认安装OCIlgQ查看下面的路径Q?br> OCI是什?Q?br> 我这里也扄一份关于在Pro*C和OCI之间选择的官方说明?br> 看过上节Q你?x)发C些奇怪的单词Qoexec , ologoff ?oclose 。这些都是先前版?br>旧的OCI标准?/p>
OCI 8.0 引入一套全新的E序l构Q是7.3以前没有的?.1版本又扩展了(jin)一些函数?br>在Oracle 9i中虽然支持这些旧的标准,不过Oracle强烈使用全新的OCI标准库?br> 参考OCI文?介绍和升U内?一节,获取更多信息?br> 现在差不多该介绍源代码了(jin)Q首先的是Makefile文gQ可以说成是整个目的中?j),?br>看例中的文g内容。注意头文g目录有两个,库文件和Pro*C使用的一Pq是 libclntsh.so.9.0 Q?br>相关路径自已调整?br> q个Makefile比较单,把前面文章罗列的所有代码复制ƈ建立相应文gQ?make all" [root@liwei oci]# make clean; [OCIException.o] [Exception.o] [OCIError.o] [Main.o] [link] ... Makefile相关知识可以去Google一下,文章从现在开始,p陆箋(hu)介绍一些OCI OCI(Oracle Call Inte***ce)是由头文件和库函数等l成的一套Oracle数据库应用程序编E接口工POCIE序实质上就是用高语言写的E序Q其特点是内部含有对OCI子函数库的调用?br>OCIE序对开发环境的要求相对较低Q只要有C语言的OCI开发工具包和C~译器就可以Q程序设计相比PRO*C复杂?jin)点?/p>
1、创建和初始化OCI环境 OCIInitialize( OCIEnvInit( 其中m_envhp出参敎ͼ是一个指向OCI环境句柄的指针,OCI_DEFAULT 是OCI环境的初始化模式。OCIEnvInit()函数中的size_tcd变量为分配给用户的内存数量,dvoid **cd变量指向用户的内存区域,该区域的大小{于size_tcd变量?br>OCI函数中,大量使用OCI定义的数据类型和宏,其定义可参?ORACLE_HOME/rdbms/demo目录下的oci.h头文件?/p>
2、申请句?br>句柄是指向OCI库所分配的内存区域的指针Q该内存区域中的数据由O(jin)CI库维护,应用E序可通过句柄讉K其中的数据。下面是应用E序中最常用的几个句柄:(x) OCIHandleAlloc( OCIHandleAlloc( OCIHandleAlloc( 其中m_errhp为新甌的句柄,m_envhp为它的父环境句柄QOCI_HTYPE_ERROR为句柄类型,表示q是一个错误报告句柄,OCI_HTYPE_SERVER表示服务器句柄,OCI_HTYPE_SVCCTX表示服务环境句柄QOCI_HTYPE_STMT表示语句句柄?/p>
存储在句柄中的数据称为句柄属性,所有OCI句柄都具有属性,可以调用OCIAttrGet()和OCIAttrSet()函数来读取、设|句柄属性?/p>
3、连接服务器建立?x)?br>首先调用 然后调用 4、执行SQL语句q处理数?br>要执行的SQL语句copy到szSqlStr字符串中: OCIStmtPrepare(m_stmthp, m_errhp, (text*)szSqlStr, (ub4) strlen(szSqlStr), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT); //准备SQL语句 OCIDefine *defnp0 = (OCIDefine *) 0; //定义输出变量 OCIDefineByPos( m_stmthp, &defnp0, m_errhp, 1, (dvoid *)szUSERNAME, 100, SQLT_STR, (dvoid *) 0, (ub2 *)0, (ub2 *)0, OCI_DEFAULT); //l定变量 OCIStmtExecute( m_svchp, m_stmthp, m_errhp, (ub4) 1, (ub4) 0, (OCISnapshot *) NULL,(OCISnapshot *) NULL, (ub4) OCI_DEFAULT); //执行SQL语句 5、结束会(x)话断开数据库连?br>OCILogoff( m_svchp, m_errhp ); 6、断开与数据源的连接,释放句柄 (2)利用Oracle自带的Make文gQ?br>首先?ORACLE_HOME/rdbms/demo/demo_rdbms.mk文gcopy到OCI源程序所在的目录Q将源文件编译ؓ(f)目标文gQ?br>#gcc –c example.o -I$(ORACLE_HOME)/rdbms/demo -I$(ORACLE_HOME)/network/public -I$(ORACLE_HOME)/rdbms/public/ example.c
]]>
follow the instructions and enrich the relevant knowledge by the OCI official document .
I'd like to copy many sentences from OCI official document . It would save me many
trouble and these sentences are more exactly .
connection , which is Single User, Single Connection and Multiple Sessions or Connections.
The example also gave the both implement .
-----------------------------------------------------------------------------
An application maintains only a single user session for each database connection
at any time .
The corresponding functions in the example listed as follows :
OCIDB::Single_Conn()
OCIDB::Single_Disc()
The calling order of routines :
OCIEnvCreate
OCIHandleAlloc <ERROR>
OCILogon
OCILogoff
OCIHandleFree <ERROR>
OCIHandleFree <ENV>
An application of OCI must have one environment handle , which is created by OCIEnvCreate()
here . The environment handle defines a context in which all OCI functions are invoked .
It is the base of almost all of the other handles which would be seen in future.
OCIEnvCreate() creates and initializes an environment for OCI functions to work under .
This call should be invoked before any other OCI call and should be used instead of
the OCIInitialize() and OCIEnvInit() calls. OCIInitialize() and OCIEnvInit() calls will be
supported for backward compatibility. But 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 . OCIInitialize() and OCIEnvInit() call is used in OCIDB::Multiple_Conn() ,
we'll cover it soon.
Almost all OCI calls include in their parameter list one or more handles. A handle is an
opaque pointer to a storage area allocated by the OCI library. You use a handle to store
context or connection information, (for example, an environment or service context handle),
or it may store information about OCI functions or data (for example, an error or describe
handle). Handles can make programming easier, because the library, rather than the application,
maintains this data.
handle . I defined a private member variable named m_pOCIEnv to store it . You can find
the both routines return a address as environment handle .
error handle .The error handle maintains information about errors that occur during an OCI
operation. If an error occurs in a call, the error handle can be passed to OCIErrorGet() to
obtain additional information about the error that occurred.
Go and look at OCIException::CheckError() which shows a integral error management .
the connection . OCILogon() and OCILogoff() is quite easy to us . Notice that a service
context handle will be created during the time processing OCILogon().
A service context handle defines attributes that determine the operational context for
OCI calls to a server. The service context contains three handles as its attributes, that
represent a server connection, a user session, and a transaction. OCILogon() call also
implicitly allocates server and user session handles associated with the session.
the program comes the end . OCIDB::Single_Disc() does it explicitly .
b. Multiple Sessions or Connections
-----------------------------------------------------------------------------
If an application needs to maintain multiple user sessions on a database connection,
the application requires a different set of calls to set up the sessions and connections.
OCIDB::Multiple_Conn()
OCIDB::Multiple_Disc()
The calling order of routines :
OCIInitialize
OCIEnvInit
OCIHandleAlloc <Error>
OCIHandleAlloc <Server Context >
OCIHandleAlloc <Server>
OCIAttrSet <Set Server Into ServerContext>
OCIServerAttach <AttachServer>
OCIHandleAlloc <Session>
OCIAttrSet <Set Session Into ServerContext>
OCISessionBegin
...
Compare with OCILogon() it becomes more complex . Each handle is allocated by
hand here .
There is someting new . All OCI handles have attributes associated with them. These
attributes represent data stored in that handle. You can read handle attributes using the
attribute get call, OCIAttrGet(), and you can change them with the attribute set call,
OCIAttrSet(). OCIServerAttach() creates an access path to the data server for OCI
operations. OCISessionBegin() establishes a session for a user against a particular server.
This call is required for the user to be able to execute any operation on the server.
Notice that the calling order of OCIAttrSet() or OCIServerAttach() is random . As the
same , either call OCIAttrSet() before OCISessionBegin() or call OCISessionBegin()
before OCIAttrSet() is OK .
Some code for test is listed below :
int main() {
OCIDB db;
db.Single_Conn();
db.Single_Disc();
}
#include "OCIDB.h"
int main() {
OCIDB db;
db.Multiple_Conn();
db.Multiple_Disc();
}
and so on . These SQL statements also could be comprehanded as DDL . OCI also support
the bind for extern values and we will discuss it in next section. Please search the relevant
code in the example. The function OCIDB::ExecuteSql() covers it .
handle is the context that identifies a SQL or PL/SQL statement and its associated attributes.
Every SQL statement must be prepared for execution by OCIStmtPrepare() then. This is a
completely local call, requiring no round trip to the server. No association is made at this
point between the statement and a particular server.
statements, no further steps are necessary.
#include "OCIDB.h"
int main() {
OCIDB db;
db.Multiple_Conn();
db.ExecuteSql("update liwei_test set id =123 where note='test' ");
db.Multiple_Disc();
}
3. Bind variable
Most DML statements, and some queries (such as those with a WHERE clause), require a
program to pass data to Oracle as part of a SQL or PL/SQL statement. Such data can be constant
or literal data, known when your program is compiled.
or PL/SQL block that contains input data to be supplied at runtime, placeholders in the SQL statement
or PL/SQL block mark where data must be supplied. For example, the following SQL statement
contains three placeholders, indicated by the leading colons (for example, :id), that show where
input data must be supplied by the program.
In this example I also made two different way using the bind . Look at this content of Main.cpp :
int main() {
OCIDB db;
db.Multiple_Conn();
db.BindAddVar(":id", 19809);
db.BindAddVar(":name", "liwei");
db.BindAddVar(":note", "test");
db.BindSql("insert into liwei_test (id,name,note)values(:id,:name,:note) ");
db.BindAddVar(":id", 169);
db.BindAddVar(":name", "sstem ch");
db.BindSql("insert into liwei_test (id,name)values(:id,:name) ");
db.Multiple_Disc();
}
OCIDB::BindAddVar() add the user parameters into the share variable which name
is m_BindVars . It has several overrided patterns .
OCIDB::BindSql() execute the SQL statement binding the structural variable . All of
the OCI operation needed is called in an order .
Notice : OCIDB::BindAddVar() allocates memory automaticly as the bind variable need .
B. Bind the variable step by step consistent with the defined order of OCI
int main() {
OCIDB db;
db.Multiple_Conn();
db.UserPrepare("insert into liwei_test (id,name,note)values(:id,:name,:note)");
db.UserBind(":id",10701);
db.UserBind(":name", "liweitest");
db.UserBind(":note", "asdfasdf");
db.UserExecute();
db.UserCommit();
db.UserFree();
db.Multiple_Disc();
}
The process had been divided into several steps here . In this case you can extend some
further functions more easily .
Both the two methods above follow this calling order :
OCIHandleAlloc <stmt>
OCIStmtPrepare
OCIBindByName/OCIBindByPos
OCIStmtExecute
OCITransCommit/OCITransRollback
OCIHandleFree <stmt>
4. Get the Recordset from a SQL Select statement
select-list cols is known before execution.
Query statements return data from the database to your application. When processing a query,
you must define an output variable or an array of output variables for each item in the select-list
from which you want to retrieve data.
int main() {
OCIDB db;
db.Multiple_Conn();
db.UserSelect("select id,name,note,value from liwei_test where note='test'");
while(db.UserFetch()==0) {
printf("id:%f\n", db.UserGetFloat("id"));
printf("name:%s\n", db.UserGetString("name"));
printf("note:%s\n", db.UserGetString("note"));
printf("value:%f\n\n", db.UserGetFloat("value"));
}
db.UserSelectFree();
}
As you see , a simple one is gave now , which still seems a bit complex . Firstly i defined
a structure "TSelectVar" to store select-list . "TSelectVar" had a union to store values in
different type . Then i encapsuled the select operation into the four parts .
UserFetch
UserGet
UserSelectFree
So let's have a look at the first part -- OCIDB::UserSelect() .
I want to know the column count of the select-list , so used OCIAttrGet() there . For each
column , i called OCIParamGet() to get a OCI parameter and then used OCIAttrGet() to
fetch lots of useful imformation such as name, size, presision and so on .
After the get of attribute , you should define the content of the select-list using OCIDefineByPos()
or OCIDefineByName() then.
The purpose of these Get() and Define() calls is to describe the select-list for the following
action which is get . OCIDB::UserFetch() is easily comprehanded , for only one call OCIStmtFetch
in it .
Pay attention to the member function like OCIDB::UserGet , these functions is interface
to exterior user . It is overrided also .
int UserGetInt(int index);
int UserGetInt(char * name);
char * UserGetString(int index);
char * UserGetString(char * name);
float UserGetFloat(int index);
float UserGetFloat(char * name);
Peruse the code patiently and you will gain much knowledge .
5.The Last
Take this way for more info by practice and online help. Obviousely there are many points
which are not very standard in the article , for a exam i didn't use CONST while passing a
value . This is a important aspect to improve .
For you may not acclimatize youself to the variety of the OCI type , take it easy , try to
get together with the OCI Function Reference and force a type conversion .
相关Oracle文ȝ解。这里从原文中复制?jin)不原句,q个省了(jin)很多ȝ(ch)而且
q些表达更ؓ(f)准确?/p>
应用E序对于某一数据库连接仅支持单用戯E?br>
例子中对应的函数q程Q?br> OCIDB::Single_Conn()
OCIDB::Single_Disc()
OCI内部q程的调用顺序如下:(x)
OCIEnvCreate
OCIHandleAlloc <ERROR>
OCILogon
OCILogoff
OCIHandleFree <ERROR>
OCIHandleFree <ENV>
OCI应用E序必须有一个环境句柄,在这里由 OCIEnvCreate()创徏。环境句柄相?br>于定义一个容器,包含?jin)以后的所有OCI句柄Q这是OCI调用的基?br> OCIEnvCreate()创徏q初始化?jin)一个OCI函数的工作环境,必须先于其他OCI函数
之前调用。一般来_(d)从兼Ҏ(gu)方面考虑Q最好用OCIInitialize() ?OCIEnvInit()替代
OCIEnvCreate()。不q如果你在写dll或者共享库之类的东西,最好还是用OCIEnvCreate()?br>OCIDB::Multiple_Conn()中就使用?jin)OCIInitialize()和OCIEnvInit() Q我们一?x)?x)提到?br>
l大多数的OCI调用都用了(jin)一个或多个句柄。句柄指向由O(jin)CI库自动分配的内存
I间。可以存储连接环境信?如,数据库连接环境或服务环境句柄) QOCI函数执行
q程中相关信?如,错误句柄或者描q句?。OCI句柄让开发工作变得简单v来,
q些相关信息是由O(jin)CI库所理Q而不是用L(fng)应用E序?/p>
准备好环境句柄和错误句柄后,该到数据库连接的实际代码?jin)。这里的OCILogon()
?OCILogoff() 理解hq不难。要注意OCILogon()执行q程中返回了(jin)一个服务环?br>句柄?br> 服务环境句柄定义一些重要属性,直接军_?jin)连接数据库的方式方法。服务环?br>句柄包含三个属性,其实是另外独立的三个句柄,x(chng)务连接,用户?x)话和事务?br> OCILogon()执行q程中其实也声明?jin)服务连接和用户会(x)话的相兛_柄,只不q是?br>式声明?/p>
b.多用P多连?br> -----------------------------------------------------------------------------
例子中对应的函数q程Q?br> OCIDB::Multiple_Conn()
OCIDB::Multiple_Disc()
OCI内部q程的调用顺序如下:(x)
OCIInitialize
OCIEnvInit
OCIHandleAlloc <Error>
OCIHandleAlloc <Server Context >
OCIHandleAlloc <Server>
OCIAttrSet <Set Server Into ServerContext>
OCIServerAttach <AttachServer>
OCIHandleAlloc <Session>
OCIAttrSet <Set Session Into ServerContext>
OCISessionBegin
...
与OCILogon()相比Q变的有些复杂,每个句柄在这里都是手工去创徏。需要提?br>的是Q所有的OCI句柄都有其相兛_性,q些属性存储了(jin)一些有用的数据。可以
用OCIAttrGet()获取对应信息Q也可以通过OCIAttrSet()q行修改。OCIServerAttach()
创徏?jin)一个OCI操作的数据服务访问\径,OCISessionBegin() 立用户?x)话q接?br>q里完成后,才可以进行实际的数据操作?br> 注意q里的OCIAttrSet()和OCIServerAttach()的调用顺序不是固定的Q类似的 OCISessionBegin()
?OCIAttrSet() 先后序也是可以互换的?/p>
#include "OCIDB.h"
int main() {
OCIDB db;
db.Single_Conn();
db.Single_Disc();
}
#include "OCIDB.h"
int main() {
OCIDB db;
db.Multiple_Conn();
db.Multiple_Disc();
}
语句。OCI也支持对SQL语句q行变量l定Q下节会(x)专门讨论?br> 例子中相关的函数是OCIDB::ExecuteSql() ?br>
首先你需要在环境句柄中声明一个语句句柄。语句句柄包含了(jin)SQL或者PL/SQL
语句?qing)其相关属性,每个SQL语句在执行前必须要用OCIStmtPrepare()q行预处理?br>q个是本地化调用Q不?x)向服务器端发送请求?/p>
代码语句如下Q?br>
#include "OCIDB.h"
int main() {
OCIDB db;
db.Multiple_Conn();
db.ExecuteSql("update liwei_test set id =123 where note='test' ");
db.Multiple_Disc();
}
三、变量绑?/p>
q是个简单的例子Q当预处理一个SQL语句或者PL/SQL块,其中有些数值是需要在q?br>行中才能定的。这时就需要在q行动态去l定变量?jin),我们在SQL语句或者PL/SQL?br>中?id之类的符P表示可以做ؓ(f)变量l定。如Q?/p>
q个例子中,我用了(jin)两种途径来绑定变量?br>
A.通过预定义的l构体一ơ性绑?br>
#include "OCIDB.h"
int main() {
OCIDB db;
db.Multiple_Conn();
db.BindAddVar(":id", 19809);
db.BindAddVar(":name", "liwei");
db.BindAddVar(":note", "test");
db.BindSql("insert into liwei_test (id,name,note)values(:id,:name,:note) ");
db.BindAddVar(":id", 169);
db.BindAddVar(":name", "sstem ch");
db.BindSql("insert into liwei_test (id,name)values(:id,:name) ");
db.Multiple_Disc();
}
OCIDB::BindAddVar() 相关的用户变量参数d到m_BindVars变量中,q个函数
有不同的重蝲形式?br> OCIDB::BindSql() l定l构体定义的变量Qƈ执行SQL语句?br>
注意QOCIDB::BindAddVar() Ҏ(gu)l定的变量D动分配内?br>
B. Ҏ(gu)OCI内部序一步一步绑?br>
#include "OCIDB.h"
int main() {
OCIDB db;
db.Multiple_Conn();
db.UserPrepare("insert into liwei_test (id,name,note)values(:id,:name,:note)");
db.UserBind(":id",10701);
db.UserBind(":name", "liweitest");
db.UserBind(":note", "asdfasdf");
db.UserExecute();
db.UserCommit();
db.UserFree();
db.Multiple_Disc();
}
q里把整个过E划分成多步Q可以方便以后扩展功能?br>
注意QUser打头的这些系列函敎ͼ其实是比较常用的一套模ѝ?br>
q两U方式调用OCI内部函数的顺序都是一L(fng)Q?br>
OCIHandleAlloc <stmt>
OCIStmtPrepare
OCIBindByName/OCIBindByPos
OCIStmtExecute
OCITransCommit/OCITransRollback
OCIHandleFree <stmt>s
四、从Select语句获取记录?/p>
量数l来存储你所需要检索的数据?/p>
int main() {
OCIDB db;
db.Multiple_Conn();
db.UserSelect("select id,name,note,value from liwei_test where note='test'");
while(db.UserFetch()==0) {
printf("id:%f\n", db.UserGetFloat("id"));
printf("name:%s\n", db.UserGetString("name"));
printf("note:%s\n", db.UserGetString("note"));
printf("value:%f\n\n", db.UserGetFloat("value"));
}
db.UserSelectFree();
}
上面是一个小例子。首先我先定义了(jin)一个结构体TSelectVar(与绑定变量的l构?br>cM)准备存储q回的结果集。TSelectVar 中用了(jin)Union存储不同cd的数倹{然?br>我把整个OCI Selectq程装成如下四部分Q?br>
UserSelect
UserFetch
UserGet
UserSelectFree
我们先看W一部分 OCIDB::UserSelect() ?br> OCIHandleAlloc() , OCIStmtPrepare(), OCIStmtExecute() 然后是OCIAttrGet() ?br> OCIAttrGet()主要是ؓ(f)?jin)获取返回结果集的列数。对于每一列,使用?jin)OCIParamGet()
先获取整列的OCIParmQ然后再使用OCIAttrGet()依次获取象列名,列大,_ֺ{?br> 有用的信息?br>
获取q些属性后Q就需要调用OCIDefineByPos()或OCIDefineByName为结果集定义
内容?jin)?br>
其实q些Get()和Define()是Z(jin)描述Select执行后返回的l果集,方便我们获取其中
数据。OCIDB::UserFetch() 里面只有个OCIStmtFetch()Q比较好理解Q说白了(jin)是控制
游标?br>
注意象OCIDB::UserGet的这些个成员函数Q是对外的数据接口,以下是不同的重蝲?br> 式:(x)
int UserGetInt(int index);
int UserGetInt(char * name);
char * UserGetString(int index);
char * UserGetString(char * name);
float UserGetFloat(int index);
float UserGetFloat(char * name);
q里没有什么好说的Q读M码就?x)清楚?br>
五、写在最?/p>
要提高的斚w?br> 另外Q刚接触OCIӞ可能?x)对内部的一堆类型不太适应Q这里多看看函数的参考,
量做一些强制性的转换?nbsp;
]]>
and SQL . Certainly it could not cover all of the knowledge , but i think it is a good beginning
for the fresher .
paths as follows :
Windows : $ORACLE_HOME\oci
Linux/Unix : $ORACLE_HOME/rdbms/demo
There are many examples offered by ORACLE . Though it seems like a clutter , you also
can get some useful imformation .
It would be a comfy thing if you have read the chapters recorded in <Oracle Database Development (1). Config OCI In Windows> .
It is easily comprehend by analogy .
2.Something you should know
used to interact with Oracle databases. It allows one to use operations like logon, execute,
parse, fetch, etc. OCI programs are normally written in C or C++, although they can be written
in almost any programing language. Unlike with the Oracle Precompilers (like Pro*C and Pro*COBOL),
OCI programs are not precompiled.
Should one use OCI or the Oracle Precompilers?
OCI is superior to Pro*C in the following ways:
Performance is much better with OCI
Reduced code size
Direct access to built-in functions (No intermediate files or substitutions).
Piecewise Operation on LONG fields (All LONG field problems are solved)
In Pro*C one cannot dynamically allocate memory to be used as bind variables
You cannot control the Pro*C precompiler to provide better and more compilable C-code.
...
Common problems with OCI:
OCI code is difficult to write and to maintain
Very few people can write, let alone maintain OCI code
...
An OCI application program must do the following:
Connect to one or more databases: call the OCILogon (olog, olon or orlon) routines
Open the cursors needed by the program: use oexec, oexn, ofen or oftech calls.
Process the SQL statements that are needed to perform the application's tasks.
Close the cursors using the oclose routine.
Disconnect from the databases: use ologoff to close an open connection to oracle.
words : oexec , ologoff or oclose . There are old routines in preceding release .
Release 8.0 of the Oracle Call Interface introduced an entirely new set of functions which
were not available in release 7.3. Release 8.1 added more new functions. Oracle9i OCI continues
to support these new functions, and adds more new calls. The earlier 7.x calls are still available,
but Oracle strongly recommends that existing applications use the new calls to improve performance
and provide increased functionality.
To get more information , check it in the chapter named "Introduction and Upgrading" in
OCI document .
4. Introduce to OCI Makefile
But then it is the end of a first exploration .
which is the same as Pro*C . This is a simple one , just copy the code in last article and
divide into the corresponding files as the list . Then use "make all" or "make clean" to deal with
the source file automaticly . You would see something like this .
rm -f OCIDB OCIDB.o OCIException.o Exception.o OCIError.o Main.o
[root@liwei oci]# make all;
[OCIDB.o]
---------------------
g++ -g -o OCIDB.o -I/home/ora/ora9/oracle/rdbms/demo -I/home/ora/ora9/oracle/rdbms/public -c OCIDB.cpp
---------------------
g++ -g -o OCIException.o -I/home/ora/ora9/oracle/rdbms/demo -I/home/ora/ora9/oracle/rdbms/public -c OCIException.cpp
---------------------
g++ -g -o Exception.o -I/home/ora/ora9/oracle/rdbms/demo -I/home/ora/ora9/oracle/rdbms/public -c Exception.cpp
---------------------
g++ -g -o OCIError.o -I/home/ora/ora9/oracle/rdbms/demo -I/home/ora/ora9/oracle/rdbms/public -c OCIError.cpp
---------------------
g++ -g -o Main.o -I/home/ora/ora9/oracle/rdbms/demo -I/home/ora/ora9/oracle/rdbms/public -c Main.cpp
---------------------
g++ -g -o OCIDB OCIDB.o OCIException.o Exception.o OCIError.o Main.o -L/home/ora/ora9/oracle/lib -lclntsh
一、序
Windows : $ORACLE_HOME\oci
Linux/Unix : $ORACLE_HOME/rdbms/demo
q些目录包含一些由O(jin)RACLE提供的一些示例。虽然有些杂乱,不过q是一些帮助的?br> 我们q里使用的主要^台是Linux?Windows下怎么讄呢?可以参见《Oracle数据?br>开?一).Windows下配|用ProC》一文,都是cM的?/p>
二、一些你需要知道的东西
OCI是一l底层的API(应用E序接口)Q主要和Oracle数据库进行交互。你可以调用一?br>操作?logon , execute, parse, fecth {等。OCI支持大数据语aQ通常使用C/C++。与Oracle
Pro*C{不同,OCI不需要预~译?/p>
我应该用OCIq是Pro*CQ?br>
OCI比Pro*C的一些优势:(x)
OCI的性能十分?gu)?br> 代码大量~减
对内|函数直接访?br> 对LONGcd的分D|?可以处理LONG相关的Q何错?
Pro*C不能为绑定变量动态分配内?br> 不能控制Pro*C自动生成的代?span class=Apple-converted-space>
OCI开发的一些常见问题:(x)
OCI代码不容易掌?br> ...
OCI开发流E:(x)
q接多个数据库:(x)使用OCILogon (olog, olon or orlon)
打开游标Qoexec, oexn, ofen 或?oftech
执行相应SQL语句
关于游标Qoclose
断开q接Qologoff
三、废弃的一些程序标?/p>
四、OCI Makefile 介绍
"make clean" 命o(h)Q你应该能看到如下类似的内容Q?nbsp;
rm -f OCIDB OCIDB.o OCIException.o Exception.o OCIError.o Main.o
[root@liwei oci]# make all;
[OCIDB.o]
---------------------
g++ -g -o OCIDB.o -I/home/ora/ora9/oracle/rdbms/demo -I/home/ora/ora9/oracle/rdbms/public -c OCIDB.cpp
---------------------
g++ -g -o OCIException.o -I/home/ora/ora9/oracle/rdbms/demo -I/home/ora/ora9/oracle/rdbms/public -c OCIException.cpp
---------------------
g++ -g -o Exception.o -I/home/ora/ora9/oracle/rdbms/demo -I/home/ora/ora9/oracle/rdbms/public -c Exception.cpp
---------------------
g++ -g -o OCIError.o -I/home/ora/ora9/oracle/rdbms/demo -I/home/ora/ora9/oracle/rdbms/public -c OCIError.cpp
---------------------
g++ -g -o Main.o -I/home/ora/ora9/oracle/rdbms/demo -I/home/ora/ora9/oracle/rdbms/public -c Main.cpp
---------------------
g++ -g -o OCIDB OCIDB.o OCIException.o Exception.o OCIError.o Main.o -L/home/ora/ora9/oracle/lib -lclntsh
实质性的内容?jin)?/p>
首先要在源程序中包含OCI头文Ӟ(x)#include <oci.h>
OCI环境即OCI函数的工作环境,在调用其他函C前必d调用OCIInitialize()和OCIEnvInit()函数创徏和初始化OCI环境Q其他OCI函数要在q个环境中才能执行?br>先定义变量:(x)
OCIEnv** m_envhp;
OCIError* m_errhp;
OCIServer* m_srvhp;
OCISvcCtx* m_svchp;
OCIStmt * m_stmthp;
(ub4) OCI_DEFAULT,
(dvoid *)0,
(dvoid * (*)(dvoid *, size_t))0,
(dvoid * (*)(dvoid *, dvoid *, size_t))0,
(void (*)(dvoid *, dvoid *))0
);
(OCIEnv **)&m_envhp,
OCI_DEFAULT, (size_t)0,
(dvoid **)0
);
OCIHandleAlloc(
(dvoid *)m_envhp,
(dvoid **)&m_errhp,
OCI_HTYPE_ERROR,
(size_t)0,
(dvoid **)0
);
(dvoid *)m_envhp,
(dvoid **)&m_srvhp,
OCI_HTYPE_SERVER,
(size_t)0,
(dvoid **)0
);
(dvoid *)m_envhp,
(dvoid **)&m_svchp,
OCI_HTYPE_SVCCTX,
(size_t) 0,
(dvoid **)0
);
(dvoid *)m_envhp,
(dvoid **)&m_stmthp,
OCI_HTYPE_STMT,
(size_t)0,
(dvoid **)0
);
OCIServerAttach(m_srvhp, m_errhp, (text *)"", strlen(""), OCI_DEFAULT);
函数建立与指定服务器的连接,text *cd变量为空Q表C接默认数据库服务QOCI_DEFAULT表示应用E序的操作模式ؓ(f)d模式Q在q种方式下,只有当OCI调用完成后才控制权q回l客L(fng)应用E序?/p>
OCILogon(m_envhp,m_errhp, &m_svchp, (text*)m_szUser,strlen(m_szUser), (text*)m_szPassword, strlen(m_szPassword), (text*)m_szDbName, strlen(m_szDbName));
建立数据库会(x)话。此函数隐含甌服务器句柄和用户?x)话句柄Q登录后Q句柄是只读的,不能再设|句柄属性?/p>
snprintf( szSqlStr, sizeof(szSqlStr), "select PASSWORD from USERS where USERNAME=’chen’ ");
执行下列语句Q?/p>
OCIServerDetach( m_srvhp, m_errhp, OCI_DEFAULT ); //断开与数据源的连?br>OCIHandleFree((dvoid *) m_stmthp, OCI_HTYPE_STMT); //释放句柄
OCIHandleFree((dvoid *) m_svchp, OCI_HTYPE_SVCCTX);
OCIHandleFree((dvoid *) m_srvhp, OCI_HTYPE_SERVER);
OCIHandleFree((dvoid *) m_errhp, OCI_HTYPE_ERROR)
3.7生成可执行文Ӟ两种Ҏ(gu)Q?br>(1)同普通的CE序Q?br> gcc -o exampled –I. –I$(ORACLE_HOME)/precomp/public example.c
然后用命令:(x)#make -f demo_rdbms.mk build OBJ*=**ample.o EXE=exampledQexampled׃ؓ(f)生成的可执行文g
]]>
]]>