OCI编程,请问如何来什么时候使用事物物

学习OCI编程 - 推酷
学习OCI编程
最近公司做的一个项目,要处理海量数据,数据是存放在Oracle数据库里,刚开始用的是ADO访问,速度极慢,后来改用Proc,效果还是不如人意,最后才用的OCI。因为之前对OCI不了解过,经2个星期的努力,终于完成了对Oracle数据库中的海量数据的读取与插入,速度的确很快,测试读取七千五百万条数据连一分钟都不到。
之前用Proc,没用OCI,是因为Proc容易学,OCI相对难学些,说起难学,主要就是因为Oracle提供的一百多个API函数中每个函数都至少带有七八个参数,而每个参数都具有不同的重要的意义,一不小心设置错了,可能会导致潜在的错误,调试的时候也很难发现,这个我深有体会啊!
下面结合我的学习过程,讲一下OCI编程:
1:环境的配置
一:系统环境:要想使用OCI编程需要安装Oracle的客户端,而这个普通的客户端比较大,在Oracle10g版本后推出了大小只有30M的Instantclient(即时客户端)作为Oracle的访问客户端。
具体的配置可以参考这里:
二:执行环境:
windows下的配置可以参考这里:
linux下的配置可以参考这里:
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—返回语句选择列表中的列数&
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&
eg:创建OCI环境
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&
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)&
三:读取/设置句柄属性
sword&OCIAttrSet(
dvoid&*trgthndlp,&&//需设置的句柄名&
ub4&&trghndltyp,&//句柄类型&
dvoid&*attributep,&//设置的属性名&
ub4&size,&//属性值长度&
ub4&attrtype,&&&&&//属性类型&
OCIError&*errhp&&&//错误句柄&
注:一般要设置的属性有:&
服务器实例:&
句柄类型OCI_HTYPE_SVCCTX,属性类型&OCI_ATTR_SERVER&
连接数据库的用户名:&
句柄类型OCI_HTYPE_SESSION,属性类型&OCI_ATTR_USERNAME&
连接数据库用户密码:
句柄类型OCI_HTYPE_SESSION,属性类型&OCI_ATTR_PASSWORD&
句柄类型OCI_HTYPE_SVCCTX,属性类型&OCI_ATTR_SESSION&
eg:设置用户名和密码&
char&username[20],passwd[20];&
strcpy(username,”tiger”)&
strcpy(passwd,”cotton”)&
swResult&=&OCIAttrSet(usrhp,&OCI_HTYPE_SESSION,&&(text*)&username,&strlen(username),&&
OCI_ATTR_USERNAME,&errhp);&
if(swResult&!=&OCI_SUCCESS&&&&swResult&!=&OCI_SUCCESS_WITH_INFO)&
return&FALSE;&
swResult&=&OCIAttrSet(usrhp,&OCI_HTYPE_SESSION,&&&&(text*)&passwd,&strlen(passwd),&&
OCI_ATTR_PASSWORD,&errhp);&
if(swResult&!=&OCI_SUCCESS&&&&swResult&!=&OCI_SUCCESS_WITH_INFO)&
return&FALSE;&
sword&OCIAttrGet(&
dvoid&*trgthndlp,&&//&需读取的句柄名&
ub4&&trghndltyp,&//句柄类型&
dvoid&*attributep,&//读取的属性名&
ub4&*sizep,&//属性值长度&
ub4&attrtype,&&&&&//属性类型&
OCIError&*errhp&&&//错误句柄&
四:连接/断开服务器&
多用户方式连接:&
sword&&OCIServerAttach(&
OCIServer&&&&&*srvhp,//&未初始化的服务器句柄&
OCIError&&&&&&*errhp,&
CONST&text&&&&*dblink,//服务器SID&
sb4&&&&&&&&&&&dblink_len,&
ub4&&&&&&&&&&&mode&//=OCI_DEFAULT,&系统环境将设为阻塞方式&
sword&OCIServerDetach&(
OCIServer&&&*srvhp,&
OCIError&&&&*errhp,&
ub4&&&&&&&&&mode&//OCI_DEFAULT&
五:开始/结束一个会话
sword&OCISessionBegin&(&&
OCISvcCtx&&&&&*svchp,&&//服务&环境句柄&
OCIError&&&&&&*errhp,&
OCISession&&&&*usrhp,&&&//用户会话句柄&
ub4&&&&&&&&&&&credt,&&&&//认证类型&
ub4&&&&&&&&&&&mode&&&//操作模式&
认证类型:&
OCI_CRED_RDBMS:&用数据库用户名和密码进行认证,则先要设置OCI_ATTR_USERNAME和OCI_ATTR_PASSWORD属性&
OCI_CRED_EXT:&外部认证,不需要设置用户和密码&
OCI_DEFAULT:用户会话环境只能被指定的服务器环境句柄所设置&
OCI_SYSDBA:用户&要具有sysdba权限&
OCI_SYSOPER:用户要具有sysoper权限&
sword&OCISessionEnd&(&&
OCISvcCtx&&&&&&&*svchp,&
OCIError&&&&&&&&*errhp,&
OCISession&&&&&&*usrhp,&
ub4&&&&&&&&&&&&&mode&);&
六:读取错误信息&
sword&OCIErrorGet&(&
dvoid&&&&&&*hndlp,&//&错误句柄&
ub4&&&&&&&&recordno,//从那里读取错误记录,从1开始&
text&&&&&&&*sqlstate,//已取消,=NULL&
sb4&&&&&&&&*errcodep,&//错误号&
text&&&&&&&*bufp,&&//错误内容&
ub4&&&&&&&&bufsiz,&&//bufp长度&
ub4&&&&&&&&type&//传递的错误句柄类型 //=OCI_HTYPE_ERROR错误句柄& //=OCI_HTYPE_ENV:&环境句柄&
ub4&&&&ub4RecordNo&=&1;&
OCIError*&hError&
sb4&&&&sb4ErrorC&
char&&&sErrorMsg[1024];&
if&(OCIErrorGet(hError,&ub4RecordNo++,&NULL,&&sb4ErrorCode,&(OraText*)&sErrorMsg,&sizeof(sErrorMsg),&OCI_HTYPE_ERROR)&==&OCI_SUCCESS)&
printf(“error&msg:%s\n”,&sErrorMsg);&
七:准备SQL语句&
sword&OCIStmtPrepare&(&&
OCIStmt&&&&&&&*stmtp,//语句句柄&&&
OCIError&&&&&&*errhp,&
CONST&text&&&&*stmt,&&//SQL语句&
ub4&&&&&&&&&&&stmt_len,&&&//语句长度&
ub4&&&&&&&&&&&language,&&//语句的语法格式=OCI_NTV_SYNTAX&
ub4&&&&&&&&&&&mode&//=OCI_DEFAULT&
char&sSQL[1024];&
sprintf(sSQL,&“select&table_name&from&user_tables”);&
swResult&=&OCIStmtPrepare(stmtp&errhp,&&(CONST&OraText*)sSQL,&strlen(sSQL),&OCI_NTV_SYNTAX,&OCI_DEFAULT);&
if(swResult&!=&OCI_SUCCESS&&&&swResult&!=&OCI_SUCCESS_WITH_INFO)&
return&FALSE;&
八:绑定输入参数
OCIBindByName()----------------------按名绑定&
OCIBindByPos()------------------------按位置绑定,建议一般按此方式绑定
OCIBindArrayOfStruct()&&-------------数组绑定,一般用于批量操作
OCIBindDynamic()&Sets&additional&attributes&after&bind&with&OCI_DATA_AT_EXEC&mode&&&
OCIBindObject()&Set&additional&attributes&for&bind&of&named&data&type&&
注:&OCIBindArrayOfStruct&必须先用OCIBindByPos初始化,然后在OCIBindArrayOfStruct中定义每个参数所跳过的字节数。
sword&OCIBindByName&(
OCIStmt&&&&&&&*stmtp,&//&语句句柄&
OCIBind&&&&&&&**bindpp,//结合句柄,=NULL&
OCIError&&&&&&*errhp,&
CONST&text&&&&*placeholder,//占位符名称&
sb4&&&&&&&&&&&placeh_len,&//&占位符长度&
dvoid&&&&&&&&&*valuep,&//要替换的值的地址
sb4&&&&&&&&&&&value_sz,&//&要替换的值的最大字节数
ub2&&&&&&&&&&&dty,&&//绑定的类型
dvoid&&&&&&&&&*indp,&//指示符变量指针(sb2类型),单条绑定时为NULL,
ub2&&&&&&&&&&&*alenp,&//&说明执行前后被结合的数组变量中各元素数据实际的长度,单条绑定时为NULL&
ub2&&&&&&&&&&&*rcodep,//&列级返回码数据指针,单条绑定时为NULL&
ub4&&&&&&&&&&&maxarr_len,&//最多&的记录数,如果是单条绑定,则为0&
ub4&&&&&&&&&&&*curelep,&//实际的记录数,单&条绑定则为NULL&
ub4&&&&&&&&&&&mode&//=OCI_DEFAULT&
OCIStmt&&&&&&*stmtp,
OCIBind&&&&&&**bindpp,
OCIError&&&&&*errhp,&
ub4&&&&&&&&&&position,//&绑&定的位置&
dvoid&&&&&&&&*valuep,&
sb4&&&&&&&&&&value_sz,&
ub2&&&&&&&&&&dty,&
dvoid&&&&&&&&*indp,&
ub2&&&&&&&&&&*alenp,&
ub2&&&&&&&&&&*rcodep,&
ub4&&&&&&&&&&maxarr_len,&
ub4&&&&&&&&&&*curelep,&&
ub4&&&&&&&&&&mode&);&
sword&OCIBindArrayOfStruct&(&
OCIBind&&&&&*bindp,//绑定的结构句柄,由OCIBindByPos定义&
OCIError&&&&*errhp,&
ub4&&&&&&&&&pvskip,&//下一列跳过的字节数
ub4&&&&&&&&&indskip,//&下一个指示器或数组跳过的字节数&&
ub4&&&&&&&&&alskip,&//下一个实际值跳过的字节数&
ub4&&&&&&&&&rcskip&//下一个列级返回值跳过的字节数&
九:定义输出变量
OCIDefineArrayOfStruct()&&&Set&additional&attributes&for&static&array&define&&&
OCIDefineByPos()&&&Define&an&output&variable&association&&&
OCIDefineDynamic()&&&Sets&additional&attributes&for&define&in&OCI_DYNAMIC_FETCH&mode&&&
OCIDefineObject()&&&Set&additional&attributes&for&define&of&named&data&type&&&
sword&OCIDefineByPos&(&&
OCIStmt&&&&&*stmtp,&//语句句柄&&
OCIDefine&&&**defnpp,//&定义句柄—用于数组变量&
OCIError&&&&*errhp,&
ub4&&&&&&&&&position,//&位置序号(从1&开始)&
dvoid&&&&&&&*valuep,&//输出的变量名&
sb4&&&&&&&&&value_sz,&//&变量长度&
ub2&&&&&&&&&dty,&&//数据类型&
dvoid&&&&&&&*indp,&//&指示器变量/指示器变量数组,如果此字段可能存在空值,则要指示器变量,否则单条处理时为NULL&
ub2&&&&&&&&&*rlenp,&//&提取的数据长度&
ub2&&&&&&&&&*rcodep,&//列级返回码数组指针&
ub4&&&&&&&&&mode&//OCI_DEFAULT&
sword&OCIDefineArrayOfStruct&(&&
OCIDefine&&&*defnp,//&由OCIDefineByPos定义的句柄&
OCIError&&&&*errhp,&
ub4&&&&&&&&&pvskip,&//&下一列跳过的字节数,一般就是结构的大小&
ub4&&&&&&&&&indskip,//下一个指示器或结构&跳过的字节数,=0&&
ub4&&&&&&&&&rlskip,&//下一个实际值跳过的字节数,=0&
ub4&&&&&&&&&rcskip&//&下一个列列级返回值跳过的字节数,=0&
sword&OCIDefineObject&(
OCIDefine&&&&&&&*defnp,
OCIError&&&&&&&&*errhp,&
CONST&OCIType&&&*type,&
dvoid&&&&&&&&&&&**pgvpp,&&
ub4&&&&&&&&&&&&&*pvszsp,&&
dvoid&&&&&&&&&&&**indpp,&&
ub4&&&&&&&&&&&&&*indszp
sql:&select&username,age&from&student&&where&username=:p1;&
如果此字段有可能有空值,则&
hDefine&=&NULL;&
swResult&=&OCIDefineByPos(stmtp&&hDefine,&errhp,&1,&tstd.username,&sizeof(tstd.username),&SQLT_CHR,&&&sb2aInd[0],&NULL,&NULL,&OCI_DEFAULT);&
如果此字段没有空值,则&
hDefine&=&NULL;&
swResult&=&OCIDefineByPos(stmtp&&hDefine,&errhp,&1,&tstd.username,&sizeof(tstd.username),&SQLT_CHR,&NULL,&NULL,&NULL,&OCI_DEFAULT);&
select&username,age&from&student&&where&age&;30;&
hDefine&=&NULL;&
swResult&=&OCIDefineByPos(stmtp,&&hDefine,&errhp,&1,&&tstd[0].username,&&
sizeof(tstd[0].usenmae),&SQLT_CHR,&NULL,&NULL,&NULL,&OCI_DEFAULT);&
swResult&=&OCIDefineArrayOfStruct(hDefine,&errhp,&sizeof(tstd[0]),&0,&0,&0);&
十:执行SQL语句
sword&OCIStmtExecute&(&&
OCISvcCtx&&&&&&&&&&&*svchp,&&//&服务环境句柄&
OCIStmt&&&&&&&&&&&&&*stmtp,&&//语句句柄&
OCIError&&&&&&&&&&&&*errhp,&
ub4&&&&&&&&&&&&&&&&&iters,&//&**&
ub4&&&&&&&&&&&&&&&&&rowoff,&//**&
CONST&OCISnapshot&&&*snap_in,&
OCISnapshot&&&&&&&&&*snap_out,&
ub4&&&&&&&&&&&&&&&&&mode&//**
1.&iters:对于select语句,它说明一次执行读取到buffer中的记录行数,如果不能确定select语句所返回的行数,可将iters设置为&0,而对于其他的语句,iters表示这些语句的执行次数,此时iters不能为0。&
2.&rowoff:在多行执行时,该参数表示从所结合的数据变量中的第几条记录开始执行(即记录偏移量)。&
=OCI_DEFAULT:default模式
=OCI_DESCRIBE_ONLY:描述模式,只返回选择列表的描述信息,而不执行语句&
=OCI_COMMIT_ON_SUCCESS:自动提交模式,当执行成功后,自动提交。&
=OCI_EXACT_FETCH:精确提取模式。&
=OCI_BATCH_ERRORS:批错误执行模式:用&于执行数组方式的操作,在此模式下,批量insert&,update,delete时,执行过程中任何一条记录错误不会导致整个&insert&,update,delete失败,系统自动会收集错误信息,而在非批错误方式下,其中的任何一条记录错误,将会导致整个操作失败。&
swResult&=&OCIStmtExecute(svchp,&stmtp,&&errhp,1,&0,&NULL,&NULL,&OCI_DEFAULT);&
批量执行100次:&
swResult&=&OCIStmtExecute(svchp,&stmtp,&&errhp,&100,&0,&NULL,&NULL,&OCI_DEFAULT);&
十一:提取结果&
sword&OCIStmtFetch&(&
OCIStmt&&&&&*stmtp,//语句句柄&
OCIError&&&&*errhp,&&
ub4&&&&&&&&&nrows,&//从当前位置处开始一次提取的记录数,对于数据变量,可&以&;1,否则不能&;1&
ub2&&&&&&&&&orientation,//提取&的方向:OCI_FETCH_NEXT&
ub4&&&&&&&&&mode&//OCI_DEFAULT&
while&((swResult=OCIStmtFetch&stmtp&errhp,1,OCI_FETCH_NEXT,OCI_DEFAULT))&!=&OCI_NO_DATA)&
十二:事务操作&
开始一个事务&
sword&OCITransStart&(&&
OCISvcCtx&&&&*svchp,&&
OCIError&&&&&*errhp,&&
uword&&&&&&&&timeout,&//**&&
ub4&&&&&&&&&&flags&);&
1.&Timeout:&
当flag=OCI_TRANS_RESUME:它表示还有多少秒事务将被激活&,=OCI_TRANS_NEW:&事务响应的超时时间(秒)&
2.&Flags:指定一个新的事务还是已有事务&
=OCI_TRANS_NEW:定义一个新的事务&
=OCI_TRANS_RESUME&
准备一个事务:&
sword&OCITransPrepare&(&
OCISvcCtx&&&&*svchp,
OCIError&&&&&*errhp,&
ub4&&&&&&&&&&flags&);//OCI_DEFAULT&
sword&OCITransForget&(&&
OCISvcCtx&&&&&*svchp,&&
OCIError&&&&&&*errhp,&
ub4&&&&&&&&&&&flags&);//OCI_DEFAULT&
断开一个事务:&
sword&OCITransDetach&(&&
OCISvcCtx&&&&*svchp,&
OCIError&&&&&*errhp,&
ub4&&&&&&&&&&flags&);//OCI_DEFAULT&
提交一个事务:&
sword&OCITransCommit&(&
OCISvcCtx&&&&*svchp,&&//服务环境句柄&
OCIError&&&&&*errhp,&
ub4&&&&&&&&&&flags&);&//OCI_DEFAULT&
回滚一个事务&
sword&OCITransRollback&(&
dvoid&&&&&&&&*svchp,&&
OCIError&&&&&*errhp,&
ub4&&&&&&&&&&flags&);&//OCI_DEFAULT&
关于OCI编程的各个函数的参数详细解释可以参考Oracle官网的在线手册,非常好用。
参考地址:
6:介绍一下OCI需要注意的地方
一:&关于输出变量定义:如果在语句执行前就知道select语句的选择列表结构,则定义输出操作可在调用&OCISTMTExecute前进行,如果查询语句的参数为用户动态输入的,则必须在执行后定义。
二:OCI函数返回值:
OCI_SUCCESS&–函数执行成功&(=0)&
OCI_SUCCESS_WITH_INFO&–&执行成功,但有诊断消息返回,可能是警告信息&
OCI_NO_DATA—函数执行完成,但没有其他数据&
OCI_ERROR—函数执行错&误&
OCI_INVALID_HANDLE—传递给函数的参数为无效句柄,或传回的句柄无效&
OCI_NEED_DATA—需要应用程序&提供运行时刻的数据&
OCI_CONTINUE—回调函数返回代码,说明回调函数需要OCI库恢复其正常的处理操作&
OCI_STILL_EXECUTING&—服务环境建立在非阻塞模式,OCI函数调用正在执行中。&
三:&OCI连接有二种方式:Blocking(阻塞方式)和non_Blocking(非阻塞方式),阻塞方式就是当调用&OCI操作时,必须等到此OCI操&作完成后服务器才返回客户端相应的信息,不管是成功还是失败。非阻塞方式是当客户端提交OCI操作给服务器后,服务器立即返回&OCI_STILL_EXECUTING信息,而并不等待服务端的操作完成。&对于non-&blocking方式,应用程序若收到一个OCI函数的返回值为&OCI_STILL_EXECUTING时必须再次对每一个OCI函数的返回值进行判&断,判断其成功与否。&可通过设置服务器属性为OCI_ATTR_NONBLOCKING_MODE来实现。系统默认方式为阻塞模式。
四:&OCI函数设置的模式有:
OCI_DEFUALT:使用OCI默认的环境&
OCI_THREADED:线程环境下使用OCI&
OCI_OBJECT:对象模式&&&//大家注意这个,当使用Orcale Spatial空间数据库时需要加上次模式。
OCI_SHARED:共享模式&
OCI_EVENTS&
OCI_NO_UCB&
OCI_ENV_NO_MUTEX:非互斥访问模式&
其中模式可以用逻辑运算符进行迭加,将函数设置成多多种模式:如&mode=OCI_SHREADED|&OCI_OBJECT&
五:&当应用进程与服务器断开连接时,程序没有使用OCITransCommit()进行事务的提交,则所有活动的事务会自动回滚。&
六:&OCI重定义数据类型&
typedef&unsigned&char&&ub1;&&&&&
typedef&&&signed&char&&sb1;&
typedef&unsigned&short&&&&ub2;&&&
typedef&&&signed&short&&&&sb2;&
typedef&unsigned&int&&ub4;&&&&
typedef&&&signed&int&&sb4;&&&
typedef&&&&&&&&&ub4&&&&&&&&&&&
typedef&&&&&&&&&sb4&&&&&&&&&&&
typedef&&&&&&&&&dsword&&&&
七:&在SQL语句准备后,可以用OCIAttrSet(设置该语句的类型属性OCI_ATTR_STMT_TYPE,以后可读取语句属性,根据属性分别进行处理。&
八:&批量绑定输入和定义输出参数:将数据存入一个静态数据组中。一次执行可以提交或读取多行记录值。&
九:结合占位符和指示器变量:
①占位符:在程序中,一些SQL语句需要在程序运行时才能确定它的语句数据,在设计时可用一个占位符来代替,当程序运行&时,在它准备好语句后,必须为每个占位符指定一个变量,即将占位符与程序变量地址结合,执行时,Oracle就从这些变量中读取数据,并将它们与SQL语&句一起传递给Oracle服务器执行。OCI结合占位符时,它将占位符与程序变量关联起来,并同时要指出程序变量的数据类型和数据长度。&
如:select&*&from&test&where&name=:p1&and&age=:p2&&(:p1和:p2为占位符&)
②指示器变量:由于在Oracle中,列值可以为NULL,但在C语言中没有NULL&值,为了能使OCI程序表达NULL列值,OCI函数允许程序为所执行语句中的结合变量同时关联一个指示符变量或指示符变量数组,以说明所结合的占位符是&否为NULL或所读取的列值是否为NULL,以及所读取的列值是否被截取。&
除SQLT_NTY(SQL&Named&DataType)外,指示符变量或指示符变量数组的数据类型为sb2,其值说明:&
作为输入变量时:(如insert&,update语句中)&
=-1:OCI程序将NULL赋给Oracle表的列,忽略占位符结合的程序变量值&
&;=0:应用程序将程序变量值赋给指定列&
作&为输出变量时:(如select语句中)&
=-2:所读取的列数据长度大于程序变量的长度,则被截取。&
=-1:所读取的值为&NULL,输出变量的值不会被改变。&
=0:数据被完整读入到指定的程序变量中&
>0:所读取的列数据长度大于程序变量的长度,则被截&取,指示符变量值为所读取数据被截取前的实际长度&
终于写完了,基本上就这么多了,希望对你有帮助。
这里不能添加附加,直接贴代码的话,不是我的风格。下面给大家介绍可以学习和直接拿来用的代码地址:
①一个简单的连接Oracle数据库的代码,详细的说明了连接Oracle数据库的步骤(比较简单,没有输入与输出)
参考地址:
(适合初学者)
②我写的一个简单的OCI接口类,能批量读取和插入数据的类,里面涉及了一些比较常用函数的用法,值得看一下
③关于Oracle空间数据库的读取与写入&&(比较全面,也比较复杂)
参考地址:
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致【图文】多平台编程_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
多平台编程
上传于||暂无简介
大小:55.50KB
登录百度文库,专享文档复制特权,财富值每天免费拿!
你可能喜欢c# 事物处理
以下示例创建一个 OleDbConnection 和一个 OleDbTransaction。它还演示了如何使用 BeginTransaction、Commit 和 Rollback 方法。
public void RunOleDbTransaction(string myConnString)
OleDbConnection myConnection = new OleDbConnection(myConnString);
myConnection.Open();
OleDbCommand myCommand = myConnection.CreateCommand();
OleDbTransaction myT
// Start a local transaction
myTrans = myConnection.BeginTransaction(IsolationLevel.ReadCommitted);
// Assign transaction object for a pending local transaction
myCommand.Connection = myC
myCommand.Transaction = myT
mandText = &&Insert into Region (RegionID, RegionDescription) VALUES (100, &Description&)&&;
myCommand.ExecuteNonQuery();
mandText = &&Insert into Region (RegionID, RegionDescription) VALUES (101, &Description&)&&;
myCommand.ExecuteNonQuery();
Console.WriteLine(&&Both records are written to database.&&);
catch(Exception e)
myTrans.Rollback();
catch (OleDbException ex)
if (myTrans.Connection != null)
Console.WriteLine(&&An exception of type && + ex.GetType() +
&& was encountered while attempting to roll back the transaction.&&);
Console.WriteLine(&&An exception of type && + e.GetType() +
&& was encountered while inserting the data.&&);
Console.WriteLine(&&Neither record was written to database.&&);
myConnection.Close();
提交数据库事务。
public virtual void Commit();
OleDbTransaction.Rollback 方法
从挂起状态回滚事务。
public virtual void Rollback();
OleDbConnection.BeginTransaction 方法
开始数据库事务。
public OleDbTransaction BeginTransaction();
以当前的 IsolationLevel 值开始数据库事务。
public OleDbTransaction BeginTransaction(IsolationLevel);
IsolationLevel 枚举?
指定连接的事务锁定行为。 在执行事务时,.NET Framework 数据提供程序使用 IsolationLevel 值。在显式更改之前,IsolationLevel 保持有效,但是可以随时对它进行更改。新值在执行时使用,而不是在分析时使用。如果在事务期间更改,服务器的预期行为是,对其余所有语句应用新的锁定级别。
IsolationLevel成员 ReadCommitted
在正在读取数据时保持共享锁,以避免脏读,但是在事务结束之前可以更改数据,从而导致不可重复的读取或幻像数据。
OleDbConnection.CreateCommand 方法
创建和返回一个与 OleDbConnection 相关联的 OleDbCommand 对象。
public OleDbCommand CreateCommand();
OleDbCommand.Connection 属性
获取或设置 OleDbCommand 的此实例使用的 OleDbConnection。
public OleDbConnection Connection {}
如何在.NET中实现事务(1)
如何在.NET中实现事务机制呢? 通常可以使用2种方式: 直接写入到sql 中;使用ADO.NET 实现。下面依次作一下介绍:
方法1:直接写入到sql 中
使用 BEGIN TRANS, COMMIT TRANS, ROLLBACK TRANS 实现:
BEGIN TRANS
DECLARE @orderDetailsError int, @productError int
DELETE FROM &&Order Details&& WHERE ProductID=42
SELECT @orderDetailsError = @@ERROR
DELETE FROM Products WHERE ProductID=42
SELECT @productError = @@ERROR
IF @orderDetailsError = 0 AND @productError = 0
COMMIT TRANS
ROLLBACK TRANS
这种方法比较简单,具体可以查阅相关sql server 帮助
方法2 :使用ADO.NET 实现,使用这种方式的优点是可以在中间层来管理事务,当然你也可以选择在数据层来实现。
SqlConnection 和OleDbConnection 对象有一个 BeginTransaction 方法,它可以返回 SqlTransaction 或者OleDbTransaction 对象。而且这个对象有 Commit 和 Rollback 方法来管理事务,具体例子如下:
cnNorthwind.Open()
Dim trans As SqlTransaction = cnNorthwind.BeginTransaction()
Dim cmDel As New SqlCommand()
cmDel.Connection = cnNorthwind
cmDel.Transaction = trans
mandText = _
&&DELETE [Order Details] WHERE ProductID = 42&&
cmDel.ExecuteNonQuery()
mandText = &&DELETE Products WHERE ProductID = 42&&
cmDel.ExecuteNonQuery()
Catch Xcp As Exception
trans.Rollback()
cnNorthwind.Close()
Ok,通过上面的例子可以实现与方法1同样的效果。
如果没有锁定且多个用户同时访问一个数据库,则当他们的事务同时使用相同的数据时可能会发生问题。并发问题包括: 丢失或覆盖更新,未确认的相关性(脏读),不一致的分析(非重复读),幻像读。但是如何来避免数据读取时脏读等问题出现呢?
二、事务实例
using(SqlTransaction trans = conn.BeginTransaction())
&//循环进行信息的插入
&for(int count = 0; count & applyInfo.L count ++)
&  //声明参数并赋值
&  SqlParameter[] parms =
{ Database.MakeInParam (&&@Stu_ID&&,System.Data.SqlDbType.VarChar,11,applyInfocount].StuID),
Database.MakeInParam&&@Bank_Name&&,System.Data.SqlDbType.VarChar,50,applyInfo[count].BankName),& Database.MakeInParam&&@Apply_Loan_Money&&,System.Data.SqlDbType.Money,8,applyInfo[count].ApplyLoanMoney), Database.MakeInParam(&&@Apply_Loan_Year&&,System.Data.SqlDbType.VarChar,20,applyInfo[count].ApplyLoanYear),& Database.MakeInParam&&@Apply_Year&&,System.Data.SqlDbType.Char,6,applyInfo[count].ApplyYear),&&&&&& Database.MakeInParam(&&@Apply_Length&&,System.Data.SqlDbType.Int,4,applyInfo[count].ApplyLength),&&&&&& Database.MakeInParam(&&@Apply_Pass&&,System.Data.SqlDbType.Char,1,applyInfo[count].ApplyPass),
Database.MakeInParam(&&@Apply_Remark&&,System.Data.SqlDbType.VarChar,100,applyInfo[count].ApplyRemark)
      & };
& //执行新增操作
& SqlHelper.ExecuteNonQuery(trans,CommandType.StoredProcedure, &&ApplyInfo_Create&&, parms);
      //未出现错误,则提交事务
&  mit();
       catch(Exception ex)
&&//出错则回滚
&&trans.Rollback();
       }
四、注意事项
  事务的定义必须在连接打开后,提交必须在关闭以前
  使用事务时必须即是把事务添加到sqlCommand中去。
另外,以下是一段在LINQ中实现的事务:
if (ctx.Connection != null) ctx.Connection.Open();
&&&&&&& DbTransaction tran = ctx.Connection.BeginTransaction();
&&&&&&& ctx.Transaction =
&&&&&&& try
&&&&&&&&&&& CreateTest(new tbTest {ID=3,Name=&妹子& });
&&&&&&&&&&& CreateTest(new tbTest {ID=2,Name=&哥们& });//因为ID=2已经存在,所以程序出错跳向Catc
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'

我要回帖

更多关于 oci编程实例 的文章

 

随机推荐