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是一个输入参数,指示缓冲区中的数据字符集,OracleCLOB数据在数据库中的存储有自己的字符集,读到缓冲区中要进行字符集转换,这里的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);
}

 

posted @ 2025-08-14 18:04  汤姆花花  阅读(17)  评论(0)    收藏  举报