学习OCI编程
最近公司做的一个项目,要处理海量数据,数据是存放在Oracle数据库里,刚开始用的是ADO访问,速度极慢,后来改用Proc,效果还是不如人意,最后才用的OCI。因为之前对OCI不了解过,经2个星期的努力,终于完成了对Oracle数据库中的海量数据的读取与插入,速度的确很快,测试读取七千五百万条数据连一分钟都不到。
之前用Proc,没用OCI,是因为Proc容易学,OCI相对难学些,说起难学,主要就是因为Oracle提供的一百多个API函数中每个函数都至少带有七八个参数,而每个参数都具有不同的重要的意义,一不小心设置错了,可能会导致潜在的错误,调试的时候也很难发现,这个我深有体会啊!
下面结合我的学习过程,讲一下OCI编程:
1:环境的配置
一:系统环境:要想使用OCI编程需要安装Oracle的客户端,而这个普通的客户端比较大,在Oracle10g版本后推出了大小只有30M的Instantclient(即时客户端)作为Oracle的访问客
户端。
具体的配置可以参考这里:wwwblogs/ychellboy/archive/2010/04/16/1713884.html
二:执行环境:
windows下的配置可以参考这里:blog.csdn/sherlockhua/article/details/4353531
linux下的配置可以参考这里:blog.csdn/sherlockhua/article/details/4353531
2:基本理论
㈠首先要创建OCI 环境即创建和初始化OCI 工作环境,其他的OCI 函数需要OCI 环境才能执行。
㈡分配OCI 环境句柄:它定义所有OCI 函数的调用环境,是其他句柄的父句柄。( 由OCIEnvInit 或OCIEnvCreate 生成 ) 。
㈢错误句柄:作为一些OCI 函数的参数,用来记录这些OCI 函数操作过程中所产生的错误,当有错误发生时,可用OCIErrorGet() 来读取错误句柄中记录的错误信息。
㈣服务器环境句柄:定义OCI 调用的服务器操作环境,它包含服务器、用户会话和事务三种句柄。
㈤服务器句柄:标识数据源,它转换为与服务器的物理连接。
㈥用户会话句柄:定义用户角和权限及OCI 调用的执行环境。
㈦事务句柄:定义执行 SQL 操作的事务环境,事务环境中包含用户的会话状态信息。
㈧语句句柄:是一个标识 SQL 语句或 PL/SQL 块,以及其相关属性的环境。
㈨Bind/Define句柄:属于语句句柄的子句柄,由OCI库隐式自动生成。用户不需要自己再申请,OCI输入变量存储在bind 句柄中,输出变量存储在定义句柄中。
注意:Bind/Define 句柄在执行具体的 SQL 语句的时候,被隐含创建并连接到表达句柄( Statement Handle )上,当表达句柄释放时,它们也被隐含释放。所以在执行每一个 sql
语句时,先分配表达句柄,执行结束后,释放表达句柄,这样做保证不发生由于定位句柄和绑定变量句柄引起的内存泄漏。
3:连接Oracle数据库的步骤
OCI 连接过程比较复杂,除了分配设置各个基本句柄外,还要明确彼此之间的联系,大致流程如下:
创建环境句柄: OCIEnvCreate(&envhp, …);
创建一个指定环境的错误句柄: OCIHandleAlloc((dvoid *)envhp, (dvoid **)&errhp,…);
创建一个指定环境的服务器句柄: OCIHandleAlloc((dvoid *)envhp, (dvoid **)&servhp,…);
建立到数据源的访问路径 : OCIServerAttach(servhpp, errhpp,…);
创建一个指定环境的服务上下文句柄: (void) OCIHandleAlloc((dvoid *)envhpp,…);
为指定的句柄及描述符设置特定的属性: (void) OCIAttrSet((dvoid *)svchpp,…);
创建一个指定环境的用户连接句柄: (void) OCIHandleAlloc((dvoid *)envhpp,…);
为用户连接句柄设置登录名及密码: (void) OCIAttrSet((dvoid *)usrhpp,…);
认证用户建立一个会话连接: OCISessionBegin(svchpp, errhpp,…);
创建一个句子句柄: OCIHandleAlloc((dvoid *)envhpp,…);s
准备 SQL 语句: OCIStmtPrepare(stmthpp, errhpp,…);
绑定输入变量: OCIBindByPos(stmtp &hBind, errhp,…);
绑定输出变量: OCIDefineByPos(stmthpp, &bhp1, errhpp,…);
获得 SQL 语句类型: OCIAttrGet ((dvoid *)stmthpp, (ub4)OCI_HTYPE_STMT,…);
执行 SQL 语句: OCIStmtExecute(svchpp, stmthpp,…);
释放一个会话: OCISessionEnd();
删除到数据源的访问 : OCIServerDetach(servhpp, errhpp, OCI_DEFAULT);
释放句柄: OCIHandleFree((dvoid *) stmthpp, OCI_HTYPE_STMT);
4:常用句柄属性
服务器环境句柄属性: (OCI_HTYPE_SVCCTX)
OCI_ATTR_SERVER— 设置 / 读取服务环境的服务器环境属性
OCI_ATTR_SESSION— 设置 / 读取服务环境的会话认证环境属性
OCI_ATTR_TRANS— 设置 / 读取服务环境的事务环境属性
用户会话句柄属性: (OCI_HTYPE_SESSION)
OCI_ATTR_USERNAME— 设置会话认证所使用的用户名
OCI_ATTR_PASSWORD— 设置会话认证所使用的用户口令
服务器句柄: (OCI_HTYPE_SEVER)
OCI_ATTR_NOBLOCKING_MODE— 设置 / 读取服务器连接: =TRUE 时服务器连接设置为非阻塞方式
语句句柄: (OCI_HTYPE_STMT)
OCI_ATTR_ROWS_RETCHED 取得获取数据记录数
OCI_ATTR_ROW_COUNT— 只读,为当前已处理的行数,其 default=1
OCI_ATTR_STMT_TYPE— 读取当前 SQL 语句的类型:
Eg : OCI_STMT_BEGIN
OCI_STMT_SELECT OCI_STMT_INSERT
OCI_STMT_UPDATE OCI_STMT_DELETE
OCI_ATTR_PARAM_COUNT—返回语句选择列表中的列数
Eg : OCI_STMT_BEGIN
OCI_STMT_SELECT OCI_STMT_INSERT
OCI_STMT_UPDATE OCI_STMT_DELETE
OCI_ATTR_PARAM_COUNT—返回语句选择列表中的列数
5:介绍一下OCI的常用函数,这些常用函数基本可以帮助你完成大多数的操作
一:创建OCI环境
sword OCIEnvCreate(
OCIEnv **envhpp, //OCI环境句柄指针
ub4 mode, //初始化模式:OCI_DEFAULT | OCI_THREADED | OCI_OBJECT等
CONST dvoid *ctxp,
CONST dvoid *(*malicfp)(dvoid *ctxp,size_t size),
CONST dvoid *(ralocfp)(dvoid *ctxp,dvoid *memptr,size_t newsize),
CONST void *(*mfreefp)(dvoid *ctxp,dvoid *memptr),
Size_t xstramemsz,
Dvoid **usrmempp
)
OCIEnv **envhpp, //OCI环境句柄指针
ub4 mode, //初始化模式:OCI_DEFAULT | OCI_THREADED | OCI_OBJECT等
CONST dvoid *ctxp,
CONST dvoid *(*malicfp)(dvoid *ctxp,size_t size),
CONST dvoid *(ralocfp)(dvoid *ctxp,dvoid *memptr,size_t newsize),
CONST void *(*mfreefp)(dvoid *ctxp,dvoid *memptr),
Size_t xstramemsz,
Dvoid **usrmempp
)
eg:创建OCI环境
int nresult=OCIEnvCreate(&envhpp, OCI_DEFAULT, NULL, NULL, NULL, NULL, 0, NULL);
int nresult=OCIEnvCreate(&envhpp, OCI_DEFAULT, NULL, NULL, NULL, NULL, 0, NULL);
二:申请/释放句柄
sword OCIHandleAlloc(
CONST dvoid *parenth, //新申请句柄的父句柄,一般为OCI环境句柄
Dvoid **hndlpp, //申请的新句柄
Ub4 type, type, //句柄类型
Size_t xtramem_sz, //申请的内存数
Dvoid **usrmempp //申请到的内存块指针
)
注: 一般需要申请的句柄有:
服务器句柄OCIServer, 句柄类型OCI_HTYPE_SERVER
错误句柄OCIError,用于捕获OCI错误信息, 句柄类型OCI_HTYPE_ERROR
上下文句柄OCISvcCtx, 句柄类型OCI_HTYPE_SVCCTX
事务句柄OCISession, 句柄类型OCI_HTYPE_SESSION
SQL语句句柄OCIStmt, 句柄类型OCI_HTYPE_STMT
CONST dvoid *parenth, //新申请句柄的父句柄,一般为OCI环境句柄
Dvoid **hndlpp, //申请的新句柄
Ub4 type, type, //句柄类型
Size_t xtramem_sz, //申请的内存数
Dvoid **usrmempp //申请到的内存块指针
)
注: 一般需要申请的句柄有:
服务器句柄OCIServer, 句柄类型OCI_HTYPE_SERVER
错误句柄OCIError,用于捕获OCI错误信息, 句柄类型OCI_HTYPE_ERROR
上下文句柄OCISvcCtx, 句柄类型OCI_HTYPE_SVCCTX
事务句柄OCISession, 句柄类型OCI_HTYPE_SESSION
SQL语句句柄OCIStmt, 句柄类型OCI_HTYPE_STMT
eg: 申请一个错误句柄OCIError
swResult = OCIHandleAlloc(envhpp, (dvoid *)& errhp, OCI_HTYPE_ERROR, 0, NULL);
if(swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO)
{ return FALSE; }
释放句柄
sword OCIHandleFree(
dvoid *hndlp, //要释放的句柄
ub4 type //句柄类型
)
eg: 释放语句句柄
OCIHandleFree(stmtp, OCI_HTYPE_STMT)
if(swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO)
{ return FALSE; }
释放句柄
sword OCIHandleFree(
dvoid *hndlp, //要释放的句柄
ub4 type //句柄类型
)
eg: 释放语句句柄
OCIHandleFree(stmtp, OCI_HTYPE_STMT)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论