SQLMoreResults
SQLMoreResults permite que o aplicativo recupere vários conjuntos de linhas de resultado. Uma instrução SELECT transact-SQL que contém uma cláusula COMPUTE ou um lote enviado de instruções ODBC ou Transact-SQL faz com que o SQL Server Native Client driver ODBC gere vários conjuntos de resultados. SQL Server não permite a criação de um cursor de servidor para processar os resultados em ambos os casos. Portanto, o desenvolvedor deve assegurar que a instrução ODBC esteja bloqueando. O desenvolvedor deve esvaziar os dados retornados ou cancelar a instrução ODBC antes de processar dados de outras instruções ativas na conexão.
Observação
Uma instrução SELECT transact-SQL que contém uma cláusula COMPUTE só tem suporte ao se conectar a uma versão do servidor antes de SQL Server 2012.
O desenvolvedor pode determinar as propriedades das colunas e linhas dos conjuntos de resultados que são geradas pela cláusula COMPUTE de uma instrução SELECT Transact-SQL. Para obter mais detalhe, consulte SQLColAttribute.
Quando SQLMoreResults é chamado com linhas de dados não buscadas no conjunto de resultados, essas linhas são perdidas e os dados da linha do próximo conjunto de resultados se tornam disponíveis.
Exemplos
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;
}