SQLGetData使用C ++和SQL Native Client发出问题

时间:2008-09-16 15:02:25

标签: c++ sql-server sqlncli

我有一个使用SQL Native Client连接到MS SQL Server 2000的C ++应用程序。

我正在尝试从包含比最初分配给它的缓冲区提供的数据更多的数据的TEXT列中检索结果。为了澄清我的问题,我将概述我正在做的事情(下面的代码):

  1. 使用
  2. 分配1024字节的缓冲区
  3. 使用SQLBindColumn将缓冲区绑定到列
  4. 使用SQLExecute执行SELECT查询
  5. 使用SQLFetch
  6. 迭代结果
  7. SQLFetch无法将整个结果返回到我的缓冲区:我想使用SQLGetData来检索整个列值
  8. 上述操作顺序存在一个问题:SQLGetData不适用于我的驱动程序中的绑定列。

    一个可行的解决方案是使用SQL_DATA_AT_EXEC标志,如下面的代码所示。

    开始代码:

    #include <windows.h>
    
    #include <sql.h>
    #include <sqlext.h>
    #include <sqltypes.h> 
    #include <sqlncli.h>
    
    #include <cstdio>
    #include <string>
    
    const int MAX_CHAR = 1024;
    
    bool test_retcode( RETCODE my_code, const char* my_message )
    {
        bool success = ( my_code == SQL_SUCCESS_WITH_INFO || my_code == SQL_SUCCESS );
        if ( ! success )
        {
            printf( "%s", my_message );
        }
    
        return success;
    }
    
    int main ( )
    {
        SQLHENV EnvironmentHandle;
    
        RETCODE retcode = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &EnvironmentHandle );
        test_retcode( retcode, "SQLAllocHandle(Env) failed!" );
    
        retcode = SQLSetEnvAttr( EnvironmentHandle, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER );
        test_retcode( retcode, "SQLSetEnvAttr(ODBC version) Failed" );
    
        SQLHDBC ConnHandle;
        retcode = SQLAllocHandle( SQL_HANDLE_DBC, EnvironmentHandle, &ConnHandle );
        test_retcode( retcode, "Could not allocate MS SQL 2000 connection handle." );
    
        SQLSMALLINT driver_out_length;
        retcode = SQLDriverConnect( ConnHandle,
            NULL, // we're not interested in spawning a window
            (SQLCHAR*) "DRIVER={SQL Native Client};SERVER=localhost;UID=username;PWD=password;Database=Test;",
            SQL_NTS,
            NULL,
            0,
            &driver_out_length,
            SQL_DRIVER_NOPROMPT );
        test_retcode( retcode, "SQLConnect() Failed" );
    
        SQLHSTMT StatementHandle;
        retcode = SQLAllocHandle(SQL_HANDLE_STMT, ConnHandle, &StatementHandle);
        test_retcode( retcode, "Failed to allocate SQL Statement handle." );
    
        char* buffer = new char[ MAX_CHAR ];
        SQLINTEGER length = MAX_CHAR - 1;
    
        // -- Bind Block
        retcode = SQLBindCol( StatementHandle, 
            1,
            SQL_C_CHAR,
            (SQLPOINTER) NULL,
            (SQLINTEGER) SQL_DATA_AT_EXEC,
            &length );
    
        test_retcode( retcode, "Failed to bind column." );
        // -- End Bind Block
    
        retcode = SQLExecDirect( StatementHandle, (SQLCHAR*) "SELECT VeryLong FROM LongData", SQL_NTS );
        test_retcode( retcode, "SQLExecDirect failed." );
    
        // -- Fetch Block
        retcode = SQLFetch( StatementHandle );
        if ( retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO && retcode != SQL_NO_DATA )
        {
            printf( "Problem fetching row.\n" );
            return 9;
        }
    
        printf( "Fetched data.  length: %d\n", length );
        // -- End Fetch Block
    
    
        bool sql_success;
        std::string data;
        RETCODE r2;
        do
        {
            r2 = SQLGetData( StatementHandle, 1, SQL_C_CHAR, buffer, MAX_CHAR, &length );
    
            if ( sql_success = test_retcode( r2, "SQLGetData failed." ) )
            {
                data.append( buffer );
            }
            else
            {
                char* err_msg = new char[ MAX_CHAR ];
                SQLSMALLINT req = 1;
                SQLCHAR state[6];
                SQLINTEGER error;
                SQLINTEGER output_length;
    
                int sql_state = SQLGetDiagRec( SQL_HANDLE_STMT, StatementHandle, req, state, &error, (SQLCHAR*) err_msg, (SQLINTEGER) MAX_CHAR, (SQLSMALLINT*) &output_length );
    
                // state is: 07009, error_msg: "[Microsoft][SQL Native Client]Invalid Descriptor Index"
                printf( "%s\n", err_msg );
    
                delete err_msg;
    
                return 9;
            }
        } 
        while ( sql_success && r2 != SQL_SUCCESS );
    
        printf( "Done.\n" );
    
        return 0;
    }
    

1 个答案:

答案 0 :(得分:3)

  1. 尝试在SQLExecDirect之后放置SQLBindCol。

  2. 对于TEXT列使用

    retcode = SQLBindCol(StatementHandle,1,SQL_C_CHAR,
    (SQLPOINTER)NULL,(SQLINTEGER)SQL_DATA_AT_EXEC,&amp; length);

  3. 通过这种方式,您可以重复SQLGetData以多个部分读取整个TEXT数据