获取varchar2列值时是否可以动态调整缓冲区大小?

时间:2011-12-16 16:48:59

标签: oracle oci

给定一个包含许多可能很大字符串的 FAT 行的表:

create table t (s1 varchar2(4000), ..., sN varchar2(4000))

我知道如何使用直接绑定来获取这些列,即

std::vector<char> buf1(4000, '\0');
OCIDefineByPos(..., 1, &buf1.front(), sb4(buf1.size()),
               SQLT_CHR, &ind1, &rlen1, 0, OCI_DEFAULT);
foreach row {
  std::string actual1(buf1.begin(), buf1.begin() + rlen1);
}

这种方法的问题在于它需要知道所有列max-size的先验(一个描述也可以告诉我,但这更多的工作),但也强制在包含数据时预先分配许多大缓冲区在每个细胞中,实际上要小得多。

我尝试过使用分段提取,用OCI_DYNAMIC_FETCH替换OCI_DEFAULT并使用OCIDefineDynamic注册我的回调,然后我用OCI_FIRST_PIECE调用,以动态提供缓冲区,但是这里提供的缓冲区必须足够大,并且OCI没有提供所获取的varchar2列的实际大小,正如人们所预料的那样,能够根据需要动态调整缓冲区的大小,或者只接受太短的缓冲区并使用OCI_NEXT_PIECE再次调用我,这样我就可以按块积累值块。

现在我系统地得到ORA-01406: fetched column value was truncated

有人能提供动态分配的获取缓冲区的示例吗? TIA,--DD

1 个答案:

答案 0 :(得分:0)

我相信你可以通过提取SQLT_VST代替SQLT_CHR并依赖OCIString来实现这一目标。内存分配在OCI内自动管理,实际上你得到一个指向它的指针。然后,您可以使用OCIStringSize()malloc()来获取实际值的大小并将其复制,或者只是通过char*将其用作常规OCIStringPtr()指针。