Condividi tramite


SQLMoreResults

SQLMoreResults consente all'applicazione di recuperare più set di righe di risultati. Un'istruzione Transact-SQL SELECT contenente una clausola COMPUTE, o un batch inviato di istruzioni ODBC o Transact-SQL, fa sì che il driver ODBC di SQL Server Native Client generi più set di risultati. SQL Server non consente la creazione di un cursore server per elaborare i risultati in entrambi i casi. Pertanto, lo sviluppatore deve assicurarsi che l'istruzione ODBC sia bloccata. Lo sviluppatore deve esaurire i dati restituiti o annullare l'istruzione ODBC prima di elaborare i dati di altre istruzioni attive nella connessione.

Lo sviluppatore può determinare le proprietà delle colonne e delle righe dei set di risultati generate dalla clausola COMPUTE di un'istruzione Transact-SQL SELECT. Per ulteriori dettagli, vedere SQLColAttribute.

Se SQLMoreResults viene chiamato con righe di dati non recuperate nel set di risultati, tali righe andranno perse e verranno resi disponibili i dati del successivo set di righe di risultati.

Esempi

void GetComputedRows
    (
    SQLHSTMT hStmt
    ) 
    {
    SQLUSMALLINT    nCols;
    SQLUSMALLINT    nCol;
    PODBCSETINFO    pODBCSetInfo = NULL;
    SQLRETURN       sRet;
    UINT            nRow;
    SQLINTEGER      nComputes = 0;
    SQLINTEGER      nSet;
    BYTE*           pValue;

    // If SQLNumResultCols failed, then some error occurred in
    //  statement execution. Exit.
    if (!SQL_SUCCEEDED(SQLNumResultCols(hStmt, (SQLSMALLINT*) &nCols)))
        {
        goto EXIT;
        }

    // Determine the presence of COMPUTE clause result sets. The SQL
    //  Server Native Client ODBC driver uses column attributes to report multiple
    //  sets. The column number must be less than or equal to the 
    //  number of columns returned. You are guaranteed to have at least
    //  one, so use '1' for the SQLColAttribute ColumnNumber
    //  parameter.
    SQLColAttribute(hStmt, 1, SQL_CA_SS_NUM_COMPUTES,
        NULL, 0, NULL, (SQLPOINTER) &nComputes);

    // Create a result info structure pointer array, one element for
    //  the normal result rows and one for each compute result set.
    //  Initialize the array to NULL pointers.
    pODBCSetInfo = new ODBCSETINFO[1 + nComputes];

    // Process the result sets...
    nSet = 0;
    while (TRUE)
        {
        // If required, get the column information for the result set.
        if (pODBCSetInfo[nSet].pODBCColInfo == NULL)
            {
            if (pODBCSetInfo[nSet].nCols == 0)
                {
                SQLNumResultCols(hStmt, (SQLSMALLINT*) &nCols);
                pODBCSetInfo[nSet].nCols = nCols;
                }

            if (GetColumnsInfo(hStmt, pODBCSetInfo[nSet].nCols,
                &(pODBCSetInfo[nSet].pODBCColInfo)) == SQL_ERROR)
                {
                goto EXIT;
                }
            }

        // Get memory for bound return values if required.
        if (pODBCSetInfo[nSet].pRowValues == NULL)
            {
            CreateBindBuffer(&(pODBCSetInfo[nSet]));
            }

        // Rebind columns each time the result set changes.
        myBindCols(hStmt, pODBCSetInfo[nSet].nCols,
            pODBCSetInfo[nSet].pODBCColInfo,
            pODBCSetInfo[nSet].pRowValues);

        // Set for ODBC row array retrieval. Fast retrieve for all
        //  sets. COMPUTE row sets have only a single row, but
        //  normal rows can be retrieved in blocks for speed.
        SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_BIND_TYPE,
            (void*) pODBCSetInfo[nSet].nResultWidth, SQL_IS_UINTEGER);
        SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_ARRAY_SIZE,
            (void*) pODBCSetInfo[nSet].nRows, SQL_IS_UINTEGER);
        SQLSetStmtAttr(hStmt, SQL_ATTR_ROWS_FETCHED_PTR,
            (void*) &nRowsFetched, sizeof(SQLINTEGER));

        while (TRUE)
            {
            // In ODBC 3.x, SQLFetch supports arrays of bound rows or
            //  columns. SQLFetchScroll (or ODBC 2.x SQLExtendedFetch)
            //  is not necessary to support fastest retrieval of 
            //  data rows.
            if (!SQL_SUCCEEDED(sRet = SQLFetch(hStmt)))
                {
                break;
                }

            for (nRow = 0; nRow < (UINT) nRowsFetched; nRow++)
                {
                for (nCol = 0; nCol < pODBCSetInfo[nSet].nCols;
                        nCol++)
                    {
                    // Processing row and column values...
                    }
                }
            }

        // sRet is not SQL_SUCCESS and is not SQL_SUCCESS_WITH_INFO.
        //  If it's SQL_NO_DATA, then continue. If it's an
        //  error state, stop.
        if (sRet != SQL_NO_DATA)
            {
            break;
            }

        // If there's another set waiting, determine the result set
        //  indicator. The indicator is 0 for regular row sets or an
        //  ordinal indicating the COMPUTE clause responsible for the
        //  set.
        if (SQLMoreResults(hStmt) == SQL_SUCCESS)
            {
            sRet = SQLColAttribute(hStmt, 1, SQL_CA_SS_COMPUTE_ID,
                NULL, 0, NULL, (SQLPOINTER) &nSet);
            }
        else
            {
            break;
            }
        }

EXIT:
    // Clean-up anything dynamically allocated and return.
    return;
    }