从这节开始我们来处理LOB数据的操作,LOB是Large Object的缩写,是Oracle用于替换LONG和LONG RAW类型而设置的,目前LOB的存储数据量最大达到了128T字节。随着LOB使用越来越频繁,LOB的操作也变得重要。LOB主要分为CLOB和BLOB两种,分别用于存放字符数据和二进制数据。
LOB操作中有一个重要的概念是LOB定位符,顾名思义就是通过它找到LOB数据存储的位置,由于LOB数据与LOB列数据是分开存储的,所以Oracle在LOB列数据中存储了LOB定位符,通过定位符再找到LOB数据存储的位置。
在OCI中LOB定位符是一个指针,类型为OCILobLocator,它指向一个分配的空间,空间中包含了LOB定位的信息。所以在使用LOB定位符之前,要先分配定位符,用到函数为OCIDescriptorAlloc(),先看看函数的原型和参数。
sword OCIDescriptorAlloc ( const void *parenth,
void **descpp,
ub4 type,
size_t xtramem_sz,
void **usrmempp);
parenth是一个输入参数,要分配描述符的父句柄,这里是环境句柄。
descpp是一个输出参数,是一个指针的指针,返回描述符的指针。
type是一个输入参数,指示返回描述符的类型,这里输入OCI_DTYPE_LOB,返回LOB定位符。
xtramem_sz是一个输入参数,随描述符额外分配的内存大小。
usrmempp是一个输出参数,返回用户分配的额外内存的指针。
用OCIDescriptorAlloc()分配的描述符,需要用OCIDescriptorFree()函数释放,不要错用OCIHandleFree()函数。
sword OCIDescriptorFree ( void *descp, ub4 type );
descp是一个输入参数,是描述符的指针。
type是一个输入参数,是描述符的类型。
看一个分配LOB定位符的例子。
OCIEnv *envhp = NULL;
int alloc_lob_locator(void)
{
sword rc;
sb4 ec;
OCILobLocator *locp;
text errbuf[512];
/* 分配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 = 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定位符空间,使之与一个LOB字段关联起来,然后才能再操作这个字段。但是如果想要插入一个LOB字段,分配后的LOB定位符由于没有内容,是不能使用的,首先要把它变成一个空LOB定位符才行,也就是要初始化这个定位符。这一步要用到OCIAttrSet()函数,设置空LOB定位符的操作如下。
ub4 lob_empty = 0;
if (OCI_SUCCESS != check_oci_error(errhp,
OCIAttrSet((void *)(*locp), (ub4)OCI_DTYPE_LOB,
(void *)&lob_empty, (ub4)0, (ub4)OCI_ATTR_LOBEMPTY, errhp)))
return (-1);
这样就创建好了一个空的LOB定位符,就可以通过OCI函数插入到一个LOB字段中了,然后通过查询语句再把定位符与LOB字段关联起来,就可以操作LOB字段了。那么不通过查询关联定位符和LOB字段可不可以呢?答案是不行。空LOB字段在插入时,Oracle要做一系列操作,才能生成真正的定位符数据,这个数据与空LOB定位符中的数据是不一样的,所以通过空LOB定位符插入LOB字段后,不能用这个空LOB定位符直接操作LOB字段。
下一节我们看看怎样插入LOB数据。