SQLMoreResults

SQLMoreResults 允许应用程序检索多个结果行集。如果 Transact-SQL SELECT 语句包含 COMPUTE 子句,或是提交了一批 ODBC 或 Transact-SQL 语句,将导致 SQL Server Native Client ODBC 驱动程序生成多个结果集。SQL Server 不允许通过创建服务器游标来处理任一种情况下的结果。因此,开发人员必须确保 ODBC 语句具有阻塞作用。开发人员必须用完返回的数据或者取消 ODBC 语句,然后才能处理来自连接中其他活动语句的数据。

开发人员可以确定由 Transact-SQL SELECT 语句的 COMPUTE 子句生成的结果集行列的属性。有关详细信息,请参阅 SQLColAttribute

如果调用 SQLMoreResults 时结果集中存在未提取的数据行,这些行将丢失,转而提供下一结果行集中的行数据。

示例

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

请参阅

概念

其他资源