OCI编程高级篇(七) LOB绑定和定义

要插入LOB字段数据有多种办法,其中一种就是把LOB数据当做普通数据来处理,直接绑定变量,变量指向LOB数据,然后执行语句,就能插入数据。这时CLOB要用VARCHAR2类型绑定,BLOB用RAW类型绑定。这种方式适合插入小数据量的LOB数据,如果要插入大量的LOB数据(一般超过4000字节),就需要绑定LOB定位符,然后插入一个空的LOB定位符,随后通过LOB SELECT操作得到这个LOB的完整定位符信息,通过LOB的写函数,分批写入LOB数据。

先看看LOB定位符的绑定,使用OCIBindByPos()函数,绑定值是LOB定位符的指针,大小为定位符指针的大小sizeof(OCILobLocator *),其他参数与绑定别的字段类型相同。如果是绑定CLOB,操作如下。

OCILobLocator    *locp;

OCIBindByPos((smthp,
        (OCIBind **)&bndp,
        errhp,
        (ub4)1,
        (void *)&locp,
        (sb4)sizeof(OCILobLocator *),
        (ub2)SQLT_CLOB,
        (void *)NULL,       /* indicator */
        (ub2 *)NULL,        /* alenp */
        (ub2 *)NULL,        /* column return code pointer */
        (ub4)0,                 /* maxarr_len */
        (ub4 *)NULL,        /* curelep */
        (ub4)OCI_DEFAULT);
 

执行LOB SELECT操作就要进行变量输出定义,用到OCIDefineByPos()函数,还以定义CLOB为例,操作如下。

OCILobLocator    *locp;

OCIDefineByPos(smthp,
          (OCIDefine **)&defp,
          errhp,
          (ub4)1,
          (void *)&locp,
          (sb4)sizeof(OCILobLocator *),
          (ub2)SQLT_CLOB,
          (void *)NULL,
          (ub2 *)NULL,
          (ub2 *)NULL,
          (ub4)OCI_DEFAULT);
 

注意在绑定和定义函数中LOB定位符输入的都是定位符的地址,是一个指针的指针,千万不要用错了。

我们举一个例子,创建一个CLOB表叫做test_clob_tab,创建语句为CREATE TABLE test_clob_tab (ID NUMBER, MESSAGE CLOB)。然后向表中插入一条数据INSERT INTO test_clob_tab values (1, EMPTY_CLOB()),然后通过SELECT MESSAGE FROM test_clob_tab WHERE ID=1查询语句得到LOB的定位符。我们写一段程序通过OCI来实现上面的操作,这也是为后面向LOB字段中写入LOB数据做准备。

OCIEnv		*envhp = NULL;
OCIError	*errhp = NULL;
OCIServer	*svrhp = NULL;
OCISession	*usrhp = NULL;
OCISvcCtx	*svchp = NULL;
OCIStmt		*smthp = NULL;

​​
int insert_one_lob(void)
{
    sword	         rc;
    sb4		         ec;
    int		         slen;
    sb2              ind_msg;
    ub2              alen_msg;
    ub4              lob_empty = 0;
    OCIBind	         *bndp;
    OCIDefine        *defp;
    OCILobLocator    *locp;
    char	         sqltxt[1024];
    text             errbuf[512];


    strcpy(sqltxt, "INSERT INTO test_clob_tab (ID, MESSAGE) values (1, :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 = 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 */
    rc = OCIAttrSet((void *)(*locp), (ub4)OCI_DTYPE_LOB,
        (void *)&lob_empty, (ub4)0, (ub4)OCI_ATTR_LOBEMPTY, errhp);

    if (rc != OCI_SUCCESS) {
        OCIErrorGet(envhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
        fprintf(stderr, "OCIAttrSet() - [%d] %s\n", ec, errbuf);
        return (-1);
    }

    /* 绑定LOB定位符 */
    rc = OCIBindByPos((OCIStmt *)smthp,
          (OCIBind **)&bndp,
          errhp,
          (ub4)1,
          (void *)&locp,
          (sb4)sizeof(OCILobLocator *),
          (ub2)SQLT_CLOB,
          (void *)&ind_msg,	    /* indp */
          (ub2 *)&alen_msg,	    /* alenp */
          (ub2 *)NULL,	        /* column return code pointer */
          (ub4)0,		        /* maxarr_len */
          (ub4 *)NULL,		    /* curelep */
          (ub4)OCI_DEFAULT);	/* mode */

    if (rc != OCI_SUCCESS) {
        OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
        fprintf(stderr, "OCIBindByPos() - [%d] %s\n", ec, errbuf);
        return (-1);
    }

    ind_msg  = 0;
    alen_msg = sizeof(OCILobLocator *);

    /* 执行语句 */
    rc = OCIStmtExecute(svchp,
           smthp,		/* stmthp */
           errhp,		/* errhp */
           1,			/* 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);
    }

    /* 提交改变 */
    rc = OCITransCommit(svchp, errhp, OCI_DEFAULT);

    if (rc != OCI_SUCCESS) {
        OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
        fprintf(stderr, "OCITransCommit() - [%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 *)&ind_msg,
        (ub2 *)&alen_msg,
        (ub2 *)NULL,			/* column return code pointer */
        (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);
    }

    /* 至此,ID=1的记录中的LOB字段的LOB定位符就存储在了locp指针中了
     * 后面,就可以通过这个定位符写入数据了
     * 从上面的代码也看到,要写入LOB数据,之前的操作很繁琐
     */

    /* 释放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);
}

从上面的代码看到在插入空LOB到写入LOB数据之前,要经过很繁琐的操作,当你真正写一段能跑起来的代码不能说象噩梦,至少也够头疼的,有没有办法把这个过程变得简洁一些,省去这些繁琐的代码呢?OCI提供了你想要的一切功能,只要你能想到好的办法,编程永远是思想比代码重要,后面我们会介绍一种节约代码的方法。

你可能感兴趣的:(数据库,oracle,数据库开发)