OCI编程高级篇(七) LOB绑定和定义
访问www.tomcoding.com网站,学习Oracle内部数据结构,详细文档说明,下载Oracle的exp/imp,DUL,logminer,ASM工具的源代码,学习高技术含量的内容。
要插入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提供了你想要的一切功能,只要你能想到好的办法,编程永远是思想比代码重要,后面我们会介绍一种节约代码的方法。

浙公网安备 33010602011771号