2

関数を呼び出す前に、テーブルで使用可能なデータの正確なサイズを知りたいですSQLGetData。現在、私は以下のコードに従っていますが、それは私にとってはうまくいきますが、それが安全かどうかはわかりません。

誰か助けてもらえますか?

char*ptr = new char[0];


        if (retcode = SQLGetData(hstmt, 31, SQL_C_BINARY, ptr,0,&cbfdata) != SQL_NO_DATA)
        {
            delete[] ptr;
            vector<char> vec(cbfdata);

            SQLGetData(hstmt, 31, SQL_C_BINARY, &vec[0],cbfdata,&cbfdata);

            ofstream fout;
            fout.open(file,ios::binary);
            fout.write(&vec[0],cbfdata);
            fout.close();
            vec.clear();
        }
4

3 に答える 3

0

最初にデータptrなしでSQLGetDataを呼び出し、StrLen_or_IndPtrを設定すると、ドライバーがサイズをStrLen_or_IndPtrに書き込みます。

于 2012-11-12T09:50:35.343 に答える
0

できません。

少なくとも安全で一般的な方法ではありません。Microsoftのドキュメントには次のように記載されています。

長さ/インジケーターバッファに返される値は、各呼び出しで前の呼び出しで返されたバイト数だけ減少しますが、ドライバが使用可能なデータの量を検出できず、SQL_NO_TOTALのバイト長を返すことは一般的です

(強調鉱山)


例を挙げましょう:

  1. NVARCHARあなたのフィールドが結果セットのタイプであると仮定しましょう 。
  2. ターゲットバッファはC文字列です。
  3. したがって、ODBCドライバーはワイド文字からナロー文字に変換する必要があります。
  4. ドライバーはSQLGetData、フェッチバッファーからターゲットバッファーにデータをコピーしながら、「オンザフライ」で変換を実行することを選択できます。
  5. (ドライバーのフェッチバッファー内の)1つのワイド文字は、ターゲットバッファー内で1、2、3、または4バイトを取ることができます。データが実際に変換されていない限り、見分けることはできません。変換とコピーが1つのステップで行われる場合、まあ...
于 2019-02-26T13:12:42.560 に答える
-2

ポインタなしでSQLGetDataを呼び出すと(NULL)、cbfdataに7が返されますが、これは実際のサイズではありません。

他の小さなプロジェクトで0サイズのポインタを作成して削除してみました。失敗しません。

ただし、リスクを冒さずに、削除を最後に配置してサイズを大きくすることで、コードを少し改善します

1バイトまで。

        char*ptr = new char[1];

        if (retcode = SQLGetData(hstmt, 31, SQL_C_BINARY, ptr,0,&cbfdata) != SQL_NO_DATA)
        {
            vector<char> vec(cbfdata);
            SQLGetData(hstmt, 31, SQL_C_BINARY, &vec[0],cbfdata,&cbfdata);

            ofstream fout;
            fout.open(file,ios::binary);
            fout.write(&vec[0],cbfdata);
            fout.close();
            vec.clear();
        }
        delete[] ptr;
于 2012-11-13T11:35:03.290 に答える