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 和 StrLen_or_IndPtr 设置的情况下调用 SQLGetData,驱动程序会将大小写入 StrLen_or_IndPtr。

于 2012-11-12T09:50:35.343 回答
0

你不能。

至少不是以一种安全、通用的方式。微软文档指出:

在每次调用中,长度/指示符缓冲区中返回的值会减少前一次调用中返回的字节数,尽管驱动程序通常无法发现可用数据量并返回 SQL_NO_TOTAL 的字节长度

(强调我的)


让我给你举个例子:

  1. 让我们假设您的字段是 NVARCHAR结果集中的类型。
  2. 您的目标缓冲区是一个 C 字符串。
  3. 因此,ODBC 驱动程序必须将宽字符转换为窄字符。
  4. 驱动程序可以选择SQLGetData“即时”进行转换,同时将数据从其获取缓冲区复制到目标缓冲区。
  5. 一个宽字符(在驱动程序的提取缓冲区中)可以在目标缓冲区中占用 1、2、3 或 4 个字节。除非数据实际上已被转换,否则无法判断。如果转换和复制是一步完成的,那么...
于 2019-02-26T13:12:42.560 回答
-2

在没有指针 (NULL) 的情况下调用 SQLGetData 在 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 回答