OCI编程高级篇(十) 如何更简单的获取LOB定位符

前面我们看到在LOB操作之前都要执行一个LOB SELECT操作,用于得到LOB定位符,尤其在插入一个空LOB,随后写入的情况,操作起来非常繁琐。那时我们希望有一种方法能简洁的得到LOB定位符,现在我们来看一下。

OCI在SQL语句INSERT,UPDATE,DELETE后面可以跟随一个RETURNING字句,相当于一个查询语句跟一个DML语句合并在一起执行,先执行完DML语句,然后执行一个查询语句,把查询的内容返回给程序。

这里仿照前面插入空LOB然后写入数据的例子,看看怎样使用这个字句。我们插入一条数据,SQL语句是INSERT INTO test_clob_tab (ID, MESSAGE)  VALUES (2, EMPTY_CLOB()),然后执行SELECT MESSAGE FROM test_clob_tab WHERE ID=2,定义一个LOB定位符的输出变量,得到LOB定位符。如果合并到一起SQL语句是这样的INSERT INTO test_clob_tab (ID, MESSAGE)  VALUES (2, EMPTY_CLOB()) RETURNING MESSAGE INTO :1。然后通过绑定函数绑定一个LOB定位符的输出变量,只要执行一次,就能插入空LOB数据然后得到一个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)
{
    int              i;
    sword	         rc;
    sb4		         ec;
    int		         slen;
    sb2              ind_msg;
    ub2              alen_msg;
    ub1              piece;
    oraub8           amt;
    OCIBind	         *bndp;
    OCILobLocator    *locp;
    char	         sqltxt[1024];
    text             errbuf[512];


    strcpy(sqltxt,
        "INSERT INTO test_clob_tab (ID, MESSAGE) values (2, EMPTY_CLOB()) RETURNING MESSAGE INTO :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 = 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);
    }

    /* 打开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<20; i++) {
        if (i == 0)
            piece = OCI_FIRST_PIECE;
        else if (i == 19)
            piece = OCI_LAST_PIECE;
        else
            piece = OCI_NEXT_PIECE;

        sprintf(buf, "%02d", i);
        memset(&buf[2], 3998, 'B');

        amt = 4000;

        rc = OCILobWrite2(svchp, errhp, locp, NULL, &amt, 1,
            buf, 4000, piece, 0, SQLCS_IMPLICIT);
        if (rc != OCI_SUCCESS) {
            OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
            fprintf(stderr, "OCILobWrite2() - [%d] %s\n", ec, errbuf);
            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);
    }

    /* 提交改变 */
    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定位符 */
    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 SELECT操作得到LOB定位符才行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值