Applies to: SQL Server Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Analytics Platform System (PDW)

SQLGetData is used to retrieve result set data without binding column values. SQLGetData can be called successively on the same column to retrieve large amounts of data from a column with a text, ntext, or image data type.

There is no requirement that an application bind variables to fetch result set data. The data of any column can be retrieved from the SQL Server Native Client ODBC driver by using SQLGetData.

The SQL Server Native Client ODBC driver does not support using SQLGetData to retrieve data in random column order. All unbound columns processed with SQLGetData must have higher column ordinals than the bound columns in the result set. The application must process data from the lowest unbound ordinal column value to the highest. Attempting to retrieve data from a lower ordinally numbered column results in an error. If the application is using server cursors to report result set rows, the application can refetch the current row and then fetch the value of a column. If a statement is executed on the default read-only, forward-only cursor, you must re-execute the statement to back up SQLGetData.

The SQL Server Native Client ODBC driver accurately reports the length of text, ntext, and image data retrieved using SQLGetData. The application can make good use of the StrLen_or_IndPtr parameter return to retrieve long data rapidly.


For large value types, StrLen_or_IndPtr will return SQL_NO_TOTAL in cases of data truncation.

SQLGetData Support for Enhanced Date and Time Features

Result column values of date/time types are converted as described in Conversions from SQL to C.

For more information, see Date and Time Improvements (ODBC).

SQLGetData Support for Large CLR UDTs

SQLGetData supports large CLR user-defined types (UDTs). For more information, see Large CLR User-Defined Types (ODBC).


SQLHDBC     hDbc = NULL;  
SQLHSTMT    hStmt = NULL;  
long        lEmpID;  
PBYTE       pPicture;  
SQLINTEGER  pIndicators[2];  
// Get an environment, connection, and so on.  
// Get a statement handle and execute a command.  
SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt);  
if (SQLExecDirect(hStmt,  
    (SQLCHAR*) "SELECT EmployeeID, Photo FROM Employees",  
    SQL_NTS) == SQL_ERROR)  
    // Handle error and return.  
// Retrieve data from row set.  
SQLBindCol(hStmt, 1, SQL_C_LONG, (SQLPOINTER) &lEmpID, sizeof(long),  
while (SQLFetch(hStmt) == SQL_SUCCESS)  
    cout << "EmployeeID: " << lEmpID << "\n";  
    // Call SQLGetData to determine the amount of data that's waiting.  
    if (SQLGetData(hStmt, 2, SQL_C_BINARY, pPicture, 0, &pIndicators[1])  
        cout << "Photo size: " pIndicators[1] << "\n\n";  
        // Get all the data at once.  
        pPicture = new BYTE[pIndicators[1]];  
        if (SQLGetData(hStmt, 2, SQL_C_DEFAULT, pPicture,  
            pIndicators[1], &pIndicators[1]) != SQL_SUCCESS)  
            // Handle error and continue.  
        delete [] pPicture;  
        // Handle error on attempt to get data length.  

See Also

SQLGetData Function
ODBC API Implementation Details