2012-02-28 18 views
0

我使用ODBC SQLGetData檢索字符串數據,使用256字節的緩衝區爲默認值。如果緩衝區太短,我將爲該字符串分配一個足夠大的新緩衝區,並再次調用SQLGetData()。如何使用ODBC處理長字符串?

看起來第二次調用這個函數只返回最後一次調用後留下的內容,而不是整個字段。

有什麼辦法可以'重置'這種行爲,所以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

爲什麼不只是已接收到的數據複製到新的緩衝區,然後追加新的數據? – 2012-02-28 13:21:44

+0

注意,有許多原因,它可能返回SQL_SUCCESS_WITH_INFO,不只是緩衝區被截斷。您需要調用SQLGetDiagRec來查找SQLSTATE是否爲您的特定條件的01004。 – Joe 2012-02-28 13:22:09

+0

的確,謝謝。 – James 2012-02-28 13:27:48

回答

2

將數據放在一起是調用者的責任;數據塊返回的限制可能是由於數據庫提供者而不是你的代碼,所以你需要能夠處理這種情況。

另外你的代碼有一個邏輯缺陷 - 你可能需要多次調用SQLGetData;每次都可以通過SQL_SUCCESS_WITH_INFO/01004返回額外的數據塊,這些數據塊需要附加在循環中。

+0

謝謝,我沒有意識到這一點。 – James 2012-02-28 13:27:38

0

如果您對「重置」提取緩衝區感興趣,我相信只有列名/索引對於兩個連續調用而言是相同的,才能保留列中的位置。換句話說,使用不同的列名稱調用SQLFetchData應該重置原始列中的位置。這裏是一個片段from MSDN

連續調用SQLGetData將檢索請求的最後一列的數據;先前的抵消失效。例如,當執行如下序列:

SQLGetData(icol=n), SQLGetData(icol=m), SQLGetData(icol=n) 

到SQLGetData(ICOL = N)的第二呼叫從n列的開始檢索數據。由於之前對該列的SQLGetData調用而導致數據中的任何偏移都不再有效。

我沒有ODBC規範方便,但MSDN似乎表明,這是預期的行爲。就個人而言,我一直使用固定大小的緩衝區將多次調用的結果直接累加到一個字符串中。

+0

確實如此 - 但必須使用SQL Server按順序訪問列。光標僅爲正向。 – James 2012-02-28 18:41:28