OCI编程高级篇(九) LOB读操作
访问www.tomcoding.com网站,学习Oracle内部数据结构,详细文档说明,下载Oracle的exp/imp,DUL,logminer,ASM工具的源代码,学习高技术含量的内容。
上一节介绍了LOB的写操作,对应的就是LOB的读操作,步骤与写操作差不多。
1. 准备LOB SELECT语句,为获取LOB定位符做准备。
2. 定义输出到LOB定位符,LOB定位符在之前要分配好。
3. 执行LOB SELECT语句。
4. 执行Fetch函数,把LOB信息与LOB定位符关联起来。
5. 打开LOB定位符。
6. 读LOB数据,然后处理LOB数据,可以重复执行这个步骤。
7. 关闭LOB定位符。
用到的新函数是LOB读的函数叫做OCILobRead2(),看一下它的原型和参数。
sword OCILobRead2 ( OCISvcCtx *svchp,
OCIError *errhp,
OCILobLocator *locp,
oraub8 *byte_amtp,
oraub8 *char_amtp,
oraub8 offset,
void *bufp,
oraub8 bufl,
ub1 piece,
void *ctxp,
OCICallbackLobRead2 (cbfp)
( void *ctxp,
const void *bufp,
oraub8 lenp,
ub1 piecep
void **changed_bufpp,
oraub8 *changed_lenp
)
ub2 csid,
ub1 csfrm );
svchp是一个输入/输出参数,OCI服务的上下文句柄。
errhp是一个输入/输出参数,错误句柄,返回错误码和错误信息文本。
locp是一个输入参数,LOB定位符指针。
byte_amtp是一个输入/输出参数,要读取的LOB字节数,读完后返回的是读到的LOB字节数,用于BLOB的读取。
char_amtp是一个输入/输出参数,要读取的LOB字符数,读完后返回的是读到的LOB字符数,用于CLOB的读取。
offset是一个输入参数,要读取的LOB的偏移量,CLOB以字符计算,BLOB以字节计算,偏移量从1开始计算。
bufp是一个输入/输出参数,指向一个数据缓冲区,用于接收读到的LOB数据。
bufl是一个输入参数,指定数据接收缓冲区的大小,以字节计算。
piece是一个输入参数,指定读入的数据片类型。随机读使用OCI_ONE_PIECE。流读取第一次读使用OCI_FIRST_PIECE,后续的读使用OCI_NEXT_PIECE。
ctxp是一个输入参数,是回调函数的上下文,可以为NULL。
cbfp是一个输入参数,是回调函数的指针,不使用回调函数设置为NULL。
csid是一个输入参数,指示缓冲区中的数据字符集,Oracle的CLOB数据在数据库中的存储有自己的字符集,读到缓冲区中要进行字符集转换,这里的csid就是转换后数据的字符集。
csfrm是一个输入参数,指示缓冲区数据的字符集形式,取值SQLCS_IMPLICIT表示与数据库字符集一致,取值SQLCS_NCHAR表示使用国际字符集。
使用上一节中写入的LOB数据,我们在这儿读出来,看一看读LOB的过程怎样用OCI实现。
OCIEnv *envhp = NULL; OCIError *errhp = NULL; OCIServer *svrhp = NULL; OCISession *usrhp = NULL; OCISvcCtx *svchp = NULL; OCIStmt *smthp = NULL; int read_lob(void){ int i; sword rc; sb4 ec; int slen; ub1 piece; oraub8 amt; OCIDefine *defp; OCILobLocator *locp; char sqltxt[1024]; text errbuf[512]; char buf[4096]; /* 分配LOB定位符 */ rc = OCIDescriptorAlloc((const void *)envhp, (void **)&locp, OCI_DTYPE_LOB, 0, (void **)NULL); if (rc != OCI_SUCCESS) { OCIErrorGet(envhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCIDescriptorAlloc() - [%d] %s\n", ec, errbuf); return (-1); } /* 下面执行LOB SELECT操作 */ strcpy(sqltxt, "SELECT MESSAGE FROM test_clob_tab WHERE ID=1"); slen = strlen(sqltxt); rc = OCIStmtPrepare(smthp, errhp, (const OraText *)sqltxt, slen, OCI_NTV_SYNTAX, OCI_DEFAULT); if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCIStmtPrepare() - [%d] %s\n", ec, errbuf); return (-1); } /* 定义LOB定位符输出 */ rc = OCIDefineByPos((OCIStmt *)smthp, (OCIDefine **)&defp, (OCIError *)errhp, (ub4)1, (void *)&locp, (sb4)sizeof(OCILobLocator *), (ub2)SQLT_CLOB, (void *)NULL, (ub2 *)NULL, (ub2 *)NULL, (ub4)OCI_DEFAULT); if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCIDefineByPos() - [%d] %s\n", ec, errbuf); return (-1); } /* 执行语句 */ rc = OCIStmtExecute(svchp, smthp, /* stmthp */ errhp, /* errhp */ 0, /* iters */ 0, /* rowoff */ NULL, /* snap_in */ NULL, /* snap_out */ OCI_DEFAULT); /* mode */ if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCIExecute() - [%d] %s\n", ec, errbuf); return (-1); } /* 执行fetch操作 */ rc = OCIStmtFetch(smthp, errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT); if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCIStmtFetch() - [%d] %s\n", ec, errbuf); return (-1); } /* 打开LOB */ rc = OCILobOpen(svchp, errhp, locp, OCI_LOB_READWRITE); if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCILobOpen() - [%d] %s\n", ec, errbuf); return (-1); } for (i=0; ; i++) { if (i == 0) piece = OCI_FIRST_PIECE; else piece = OCI_NEXT_PIECE; amt = 4000; rc = OCILobRead2(svchp, errhp, locp, NULL, &amt, 1, buf, 4000, piece, 0, SQLCS_IMPLICIT); if (rc == OCI_NEED_DATA) { /* 读取的数据在buf中,在这里处理数据,我们只打印读到的数据量值作为演示 */ fprintf(stdout, "read data amount=%d\n", amt); /* 进行下一次读 */ continue; } else if (rc == OCI_SUCCESS) { /* 读到了最后一片数据,处理数据后,退出循环 */ fprintf(stdout, "read data amount=%d\n", amt); break; } if (rc == OCI_ERROR) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCILobWrite2() - [%d] %s\n", ec, errbuf); return (-1); } /* 其他错误 */ fprntf(stderr, "Other error found !\n"); return (-1); } /* 关闭LOB */ rc = OCILobClose(svchp, errhp, locp); if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCILobClose() - [%d] %s\n", ec, errbuf); return (-1); } /* 释放LOB定位符 */ rc = OCIDescriptorFree((void *)locp, OCI_DTYPE_LOB); if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCIDescriptorFree() - [%d] %s\n", ec, errbuf); return (-1); } return (0); }

浙公网安备 33010602011771号