2012-02-28 31 views
0

私はODBCのSQLGetDataを使って文字列データを検索しています。デフォルトでは256バイトのバッファを使用しています。バッファーが短すぎる場合、私は文字列のために十分な大きさの新しいバッファーを割り当てて、SQLGetData()をもう一度呼び出しています。ODBCで長い文字列を処理する方法は?

これは2度目の呼び出しでは、フィールド全体ではなく最後の呼び出し後に残されたものだけを返すようです。

SQLGetDataが2番目のバッファにフィールド全体を返すようにこの動作をリセットする方法はありますか?

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

受信したデータを新しいバッファにコピーして新しいデータを追加するだけではどうですか? –

+0

バッファが切り捨てられただけでなく、SQL_SUCCESS_WITH_INFOが返される理由はたくさんあることに注意してください。特定の条件に対してSQLSTATEが01​​004かどうかを調べるには、SQLGetDiagRecを呼び出す必要があります。 – Joe

+0

本当にありがとうございます。 – James

答えて

2

データをまとめて送信するのは発信者の責任です。チャンク内のデータを返すことの制限は、データベースプロバイダーであり、コードではない可能性があります。そのため、どちらの場合でもケースを処理できる必要があります。

また、コードにロジックの欠陥があります.SQLGetDataを複数回呼び出す必要があります。ループごとに追加する必要があるSQL_SUCCESS_WITH_INFO/01004で追加のチャンクを返すことがあります。

+0

ありがとう、私はそれを実現していませんでした。 – James

0

フェッチバッファをリセットすることに興味がある場合は、列名/インデックスが連続する2回の呼び出しで同じである場合、列内の位置は保持されると考えています。つまり、別の列名を使用してSQLFetchDataを呼び出すと、元の列の位置がリセットされます。ここではスニペットですfrom MSDN

最後にSQLGetDataを呼び出すと、要求された最後の列からデータが取得されます。以前のオフセットは無効になります。以下のシーケンスが実行されるとき、例えば:

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

のSQLGetData(ICOL = N)の2番目の呼び出しは、n列の先頭からデータを取り出します。列のSQLGetDataへの以前の呼び出しによるデータ内のオフセットは、もはや有効ではありません。

ODBC仕様は便利ではありませんが、MSDNはこれが予期された動作であると思われます。個人的には、固定サイズのバッファを使用して複数の呼び出しの結果を文字列に直接蓄積してきました。

+0

これは当てはまりますが、SQL Serverを使用して列に順次アクセスする必要があります。カーソルは前方のみです。 – James

関連する問題