SQLMoreResults
Gilt für: SQL Server
Azure SQL-Datenbank
Azure SQL verwaltete Instanz
Azure Synapse Analytics Analytics
Platform System (PDW)
SQLMoreResults ermöglicht es der Anwendung, mehrere Ergebniszeilensätze abzurufen. Eine Transact-SQL SELECT-Anweisung, die eine COMPUTE-Klausel oder einen übermittelten Batch von ODBC- oder Transact-SQL-Anweisungen enthält, bewirkt, dass der SQL Server Native Client ODBC-Treiber mehrere Resultsets generiert. SQL Server lässt das Erstellen eines Servercursors nicht zu, um die Ergebnisse in beiden Fällen zu verarbeiten. Deshalb muss der Entwickler sicherstellen, dass die ODBC-Anweisung blockierend wirkt. Der Entwickler muss die zurückgegebenen Daten vollständig nutzen oder die ODBC-Anweisung abbrechen, bevor Daten aus anderen aktiven Anweisungen für die Verbindung verarbeitet werden.
Hinweis
Eine Transact-SQL SELECT-Anweisung, die eine COMPUTE-Klausel enthält, wird nur unterstützt, wenn eine Verbindung mit einer Serverversion vor SQL Server 2012 (11.x) hergestellt wird.
Der Entwickler kann die Eigenschaften der Resultsetsspalten und Zeilen bestimmen, die von der COMPUTE-Klausel einer Transact-SQL SELECT-Anweisung generiert werden. Weitere Informationen finden Sie unter SQLColAttribute.
Wenn SQLMoreResults mit nicht abgerufenen Datenzeilen im Resultset aufgerufen wird, gehen diese Zeilen verloren und die Zeilendaten der nächsten Resultsetzeile werden zur Verfügung gestellt.
Beispiele
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;
}