我正在使用ODBC SQLGetData来检索字符串数据,默认情况下使用256字节缓冲区。如果缓冲区太短,我会为字符串分配一个足够大的新缓冲区并再次调用SQLGetData()。
似乎第二次调用它只返回上次调用后剩下的内容,而不是整个字段。
有没有办法'重置'这种行为,以便SQLGetData将整个字段返回到第二个缓冲区?
char buffer[256];
SQLLEN sizeNeeded = 0;
SQLRETURN ret = SQLGetData(_statement, _columnIndex, SQL_C_CHAR, (SQLCHAR*)buffer, sizeof(buffer), &sizeNeeded);
if(ret == SQL_SUCCESS)
{
return std::string(buffer);
}
else if(ret == SQL_SUCCESS_WITH_INFO)
{
std::auto_ptr<char> largeBuffer(new char[sizeNeeded + 1]);
// Doesn't return the whole field, only what was left...
SQLGetData(_statement, _columnIndex, SQL_C_CHAR, (SQLCHAR*)largeBuffer.get(), sizeNeeded, &sizeNeeded);
}
感谢您的帮助!
答案 0 :(得分:2)
调用者有责任将数据放在一起;以块为单位返回数据的限制可能是由于数据库提供程序而不是代码,因此您需要能够以任何一种方式处理该案例。
此外,您的代码存在逻辑缺陷 - 您可能需要多次调用SQLGetData;每次都可以返回需要附加在循环中的SQL_SUCCESS_WITH_INFO / 01004的额外数据块。
答案 1 :(得分:0)
如果您对“重置”获取缓冲区感兴趣,我相信只有当两个连续调用的列名/索引相同时,才会保留列中的位置。换句话说,使用不同的列名称调用SQLFetchData
应重置原始列中的位置。这是一个片段from MSDN:
对SQLGetData的连续调用将从请求的最后一列中检索数据;先前的抵消变得无效。例如,执行以下序列时:
SQLGetData(icol=n), SQLGetData(icol=m), SQLGetData(icol=n)
第二次调用SQLGetData(icol = n)从n列的开头检索数据。由于之前对该列的SQLGetData调用而导致的数据中的任何偏移都不再有效。
我没有方便的ODBC规范,但MSDN似乎表明这是预期的行为。就个人而言,我总是使用固定大小的缓冲区将多个调用的结果直接累积到字符串中。