Partager via


SQLMoreResults

SQLMoreResults permet à l'application de récupérer plusieurs jeux de lignes de résultat. Une instruction Transact-SQL SELECT contenant une clause COMPUTE, ou un lot soumis d'instructions ODBC ou Transact-SQL, entraîne la génération de plusieurs jeux de résultats par le pilote ODBC SQL Server Native Client. SQL Server n'autorise pas la création d'un curseur côté serveur pour traiter les résultats. Par conséquent, le développeur doit s'assurer que l'instruction ODBC bloque. Il doit consommer les données retournées ou annuler l'instruction ODBC avant de traiter les données des autres instructions actives sur la connexion.

[!REMARQUE]

Une instruction Transact-SQL SELECT contenant une clause COMPUTE n'est prise en charge que lors de la connexion à une version de serveur antérieure à SQL Server 2012.

Le développeur peut déterminer les propriétés des colonnes et lignes de jeux de résultats qui sont générées par la clause COMPUTE d'un instruction Transact-SQL SELECT. Pour plus d'informations, consultez SQLColAttribute.

Lorsque SQLMoreResults est appelé avec des lignes de données non extraites dans le jeu de résultats, ces lignes sont perdues, et les données de ligne du jeu de lignes de résultat suivant sont rendues disponibles.

Exemples

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;
    }

Voir aussi

Concepts

Détails d'implémentation d'une API ODBC

Autres ressources

Fonction SQLMoreResults