从结果集中提取行 (OLE DB)

此示例显示如何从结果集中提取行。 IA64 平台不支持此示例。

此示例要求使用 AdventureWorks 示例数据库,可以从 Microsoft SQL Server Samples and Community Projects(Microsoft SQL Server 示例和社区项目)主页下载该数据库。

安全说明安全说明

请尽可能使用 Windows 身份验证。 如果 Windows 身份验证不可用,请在运行时提示用户输入其凭据。 不要将凭据存储在一个文件中。 如果必须保存凭据,应当用 Win32 crypto API(Win32 加密 API)加密它们。

示例

说明

使用 ole32.lib 和 oleaut32.lib 编译并执行以下 C++ 代码列表。 此应用程序连接到您的计算机上默认的 SQL Server 实例。 在某些 Windows 操作系统上,您需要将 (localhost) 或 (local) 更改为您的 SQL Server 实例的名称。 若要连接到命名实例,请将连接字符串从 L"(local)" 更改为 L"(local)\\name",其中 name 是命名实例。 默认情况下,SQL Server Express 安装在命名实例中。 请确保您的 INCLUDE 环境变量包括含有 sqlncli.h 的目录。

代码

// compile with: ole32.lib oleaut32.lib
int InitializeAndEstablishConnection();
int ProcessResultSet();

#define UNICODE
#define _UNICODE
#define DBINITCONSTANTS
#define INITGUID
#define OLEDBVER 0x0250   // to include correct interfaces

#include <stdio.h>
#include <tchar.h>
#include <stddef.h>
#include <windows.h>
#include <iostream>
#include <oledb.h>
#include <sqlncli.h>
#include <msdadc.h>   // for IDataConvert
#include <msdaguid.h>   // for IDataConvert

using namespace std;

IDBInitialize* pIDBInitialize = NULL;
IDBProperties* pIDBProperties = NULL;
IDBCreateSession* pIDBCreateSession = NULL;
IDBCreateCommand* pIDBCreateCommand = NULL;
ICommandText* pICommandText = NULL;
IRowset* pIRowset = NULL;
IColumnsInfo* pIColumnsInfo = NULL;

DBCOLUMNINFO* pDBColumnInfo = NULL;
IAccessor* pIAccessor =  NULL;
DBPROP InitProperties[4];
DBPROPSET rgInitPropSet[1];

ULONG i, j;
HRESULT hr;
DBROWCOUNT cNumRows = 0;
DBORDINAL lNumCols;
WCHAR* pStringsBuffer;
DBBINDING* pBindings;
DBLENGTH ConsumerBufColOffset = 0;
HACCESSOR hAccessor;
DBCOUNTITEM lNumRowsRetrieved;
HROW hRows[10];
HROW* pRows = &hRows[0];

int main() {
   // The command to execute.
   WCHAR* wCmdString = OLESTR("SELECT StandardCost, ListPrice FROM Production.Product WHERE ListPrice > 14.00");

   // Call a function to initialize and establish connection. 
   if (InitializeAndEstablishConnection() == -1) {
      // Handle error.
      cout << "Failed to initialize and connect to the server.\n";
      return -1;
   }

   // Create a session object.
   if (FAILED(pIDBInitialize->QueryInterface( IID_IDBCreateSession,
      (void**) &pIDBCreateSession))) {
         cout << "Failed to obtain IDBCreateSession interface.\n";
         // Handle error.
         return -1;
   }

   if (FAILED(pIDBCreateSession->CreateSession( NULL, 
      IID_IDBCreateCommand, 
      (IUnknown**) &pIDBCreateCommand))) {
         cout << "pIDBCreateSession->CreateSession failed.\n";
         // Handle error.
         return -1;
   }

   // Access the ICommandText interface.
   if (FAILED(pIDBCreateCommand->CreateCommand( NULL, 
      IID_ICommandText, 
      (IUnknown**) &pICommandText))) {
         cout << "Failed to access ICommand interface.\n";
         // Handle error.
         return -1;
   }

   // Use SetCommandText() to specify the command text.
   if (FAILED(pICommandText->SetCommandText(DBGUID_DBSQL, wCmdString))) {
      cout << "Failed to set command text.\n";
      // Handle error.
      return -1;
   }

   // Execute the command.
   if (FAILED(hr = pICommandText->Execute( NULL, 
      IID_IRowset, 
      NULL, 
      &cNumRows, 
      (IUnknown **) &pIRowset))) {
         cout << "Failed to execute command.\n";
         // Handle error.
         return -1;
   }

   // Process the result set.
   ProcessResultSet(); 

   pIRowset->Release();

   // Free up memory.
   pICommandText->Release();
   pIDBCreateCommand->Release();
   pIDBCreateSession->Release();

   if (FAILED(pIDBInitialize->Uninitialize())) {
      // Uninitialize is not required, but it fails if an interface
      // has not been released.  This can be used for debugging.
      cout << "Problem uninitializing.\n";
   }

   pIDBInitialize->Release();
   CoUninitialize();
};

int InitializeAndEstablishConnection() {    
   CoInitialize(NULL);

   // Obtain access to the SQLNCLI provider.
   hr = CoCreateInstance( CLSID_SQLNCLI11,
      NULL,
      CLSCTX_INPROC_SERVER,
      IID_IDBInitialize,
      (void **) &pIDBInitialize);


   if (FAILED(hr)) {
      printf("Failed to get IDBInitialize interface.\n");
      // Handle errors here.
      return -1;
   }

   // Initialize the property values needed to establish the connection.
   for ( i = 0 ; i < 4 ; i++ )
      VariantInit(&InitProperties[i].vValue);

   // Server name.
   InitProperties[0].dwPropertyID = DBPROP_INIT_DATASOURCE;
   InitProperties[0].vValue.vt = VT_BSTR;

   InitProperties[0].vValue.bstrVal= SysAllocString(L"(local)");
   InitProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;
   InitProperties[0].colid = DB_NULLID;

   // Database.
   InitProperties[1].dwPropertyID = DBPROP_INIT_CATALOG;
   InitProperties[1].vValue.vt = VT_BSTR;
   InitProperties[1].vValue.bstrVal = SysAllocString(L"AdventureWorks");
   InitProperties[1].dwOptions = DBPROPOPTIONS_REQUIRED;
   InitProperties[1].colid = DB_NULLID;

   InitProperties[2].dwPropertyID = DBPROP_AUTH_INTEGRATED;
   InitProperties[2].vValue.vt = VT_BSTR;
   InitProperties[2].vValue.bstrVal = SysAllocString(L"SSPI");
   InitProperties[2].dwOptions = DBPROPOPTIONS_REQUIRED;
   InitProperties[2].colid = DB_NULLID;

   // Properties are set, now construct the DBPROPSET structure (rgInitPropSet) used to pass 
   // an array of DBPROP structures (InitProperties) to the SetProperties method.
   rgInitPropSet[0].guidPropertySet = DBPROPSET_DBINIT;
   rgInitPropSet[0].cProperties = 4;
   rgInitPropSet[0].rgProperties = InitProperties;

   // Set initialization properties.
   hr = pIDBInitialize->QueryInterface(IID_IDBProperties, (void **)&pIDBProperties);
   if (FAILED(hr)) {
      cout << "Failed to get IDBProperties interface.\n";
      // Handle errors here.
      return -1;
   }

   hr = pIDBProperties->SetProperties(1, rgInitPropSet); 
   if (FAILED(hr)) {
      cout << "Failed to set initialization properties.\n";
      // Handle errors here.
      return -1;
   }

   pIDBProperties->Release();

   // Now establish the connection to the data source.
   if (FAILED(pIDBInitialize->Initialize())) {
      cout << "Problem in establishing connection to the data"
         "source.\n";
      // Handle errors here.
      return -1;
   }
   return 0;
}

// Retrieve and display data resulting from a query.
int ProcessResultSet() {
   // Obtain access to the IColumnInfo interface, from the Rowset object.
   hr = pIRowset->QueryInterface(IID_IColumnsInfo, (void **)&pIColumnsInfo);
   if (FAILED(hr)) {
      cout << "Failed to get IColumnsInfo interface.\n";
      // Handle errors here.
      return -1;
   } 

   // Retrieve the column information.
   pIColumnsInfo->GetColumnInfo(&lNumCols, &pDBColumnInfo, &pStringsBuffer);

   // Free the column information interface.
   pIColumnsInfo->Release();

   // Create a DBBINDING array.
   DBBINDING * p = (pBindings = new DBBINDING[lNumCols]);
   if (!(p /* pBindings = new DBBINDING[lNumCols] */ ))
      return -1;

   // Using the ColumnInfo structure, fill out the pBindings array.
   for ( j = 0 ; j < lNumCols ; j++ ) {
      pBindings[j].iOrdinal = j+1;
      pBindings[j].obValue = ConsumerBufColOffset;
      pBindings[j].pTypeInfo = NULL;
      pBindings[j].pObject = NULL;
      pBindings[j].pBindExt = NULL;
      pBindings[j].dwPart = DBPART_VALUE;
      pBindings[j].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
      pBindings[j].eParamIO = DBPARAMIO_NOTPARAM;
      pBindings[j].cbMaxLen = (pDBColumnInfo[j].wType == DBTYPE_WSTR) ? pDBColumnInfo[j].ulColumnSize * 2 : pDBColumnInfo[j].ulColumnSize;
      pBindings[j].dwFlags = 0;
      pBindings[j].wType = pDBColumnInfo[j].wType;
      pBindings[j].bPrecision = pDBColumnInfo[j].bPrecision;
      pBindings[j].bScale = pDBColumnInfo[j].bScale;

      // Compute the next buffer offset.
      ConsumerBufColOffset = 
         ConsumerBufColOffset + pBindings[j].cbMaxLen;
   };

   // Get the IAccessor interface.
   hr = pIRowset->QueryInterface(IID_IAccessor, (void **) &pIAccessor);
   if (FAILED(hr)) {
      cout << "Failed to obtain IAccessor interface.\n";
      // Handle errors here.
      return -1;
   }

   // Create an accessor from the set of bindings (pBindings).
   pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, lNumCols, pBindings, 0, &hAccessor, NULL);

   // Print column names.
   for ( j = 0 ; j < lNumCols ; j++ )
      printf("%-40S", pDBColumnInfo[j].pwszName);

   printf("\n");   // new line after the column names

   // Get a set of 10 rows.
   pIRowset->GetNextRows( NULL, 0, 10, &lNumRowsRetrieved, &pRows);

   // Allocate space for the row buffer.
   BYTE * pBuffer = new BYTE[ConsumerBufColOffset];
   if (!(pBuffer /* = new BYTE[ConsumerBufColOffset] */ )) {
      // Free up all allocated memory.
      pIAccessor->ReleaseAccessor(hAccessor, NULL);
      pIAccessor->Release();
      delete [] pBindings;

      return 0;
   }

   // Create an instance of the data conversion library to convert DBTYPE_CY to string for display
   IDataConvert* pIDataConvert;
   CoCreateInstance(CLSID_OLEDB_CONVERSIONLIBRARY,
      NULL,
      CLSCTX_INPROC_SERVER,
      IID_IDataConvert,
      (void**)&pIDataConvert);

   // variables used in DataConvert
   DBLENGTH cbDstLength;
   DBSTATUS dbsStatus;
   char strCurrency0[25];
   char strCurrency1[25];

   // Display the rows.
   while ( lNumRowsRetrieved > 0 ) {
      // For each row, print the column data.
      for ( j = 0 ; j < lNumRowsRetrieved ; j++ ) {
         // Clear the buffer.
         memset(pBuffer, 0, ConsumerBufColOffset);

         // Get the row data values.
         pIRowset->GetData(hRows[j], hAccessor, pBuffer);

         // Convert DBTYPE_CY values to string 
         pIDataConvert->DataConvert(DBTYPE_CY,   // wSrcType
            DBTYPE_STR,   // wDstType
            sizeof(LARGE_INTEGER),   // cbSrcLength 
            &cbDstLength,   // pcbDstLength
            &pBuffer[pBindings[0].obValue],   // pSrc
            strCurrency0,   // pDst
            sizeof(strCurrency0),   //cbDstMaxLength
            DBSTATUS_S_OK,   // dbsSrcStatus
            &dbsStatus,   // pdbsStatus
            0,   // bPrecision (used for DBTYPE_NUMERIC only)
            0,   // bScale (used for DBTYPE_NUMERIC only)
            DBDATACONVERT_DEFAULT);   // dwFlags

         pIDataConvert->DataConvert(DBTYPE_CY,   // wSrcType
            DBTYPE_STR,   // wDstType
            sizeof(LARGE_INTEGER),   // cbSrcLength 
            &cbDstLength,   // pcbDstLength
            &pBuffer[pBindings[1].obValue],   // pSrc
            strCurrency1,   // pDst
            sizeof(strCurrency1),   // cbDstMaxLength
            DBSTATUS_S_OK,   // dbsSrcStatus
            &dbsStatus,   // pdbsStatus
            0,   // bPrecision (used for DBTYPE_NUMERIC only)
            0,   // bScale (used for DBTYPE_NUMERIC only)
            DBDATACONVERT_DEFAULT); // dwFlags

         // Print cost and price values.
         printf("%-40s%s\n", strCurrency0, strCurrency1); //sparra
      };

      // Release the rows retrieved.
      pIRowset->ReleaseRows(lNumRowsRetrieved, hRows, NULL, NULL, NULL);

      // Get the next set of 10 rows.
      pIRowset->GetNextRows(NULL, 0, 10, &lNumRowsRetrieved, &pRows);
   }

   // Free up all allocated memory.
   delete [] pBuffer;
   pIAccessor->ReleaseAccessor(hAccessor, NULL);
   pIAccessor->Release();
   delete [] pBindings;

   return 0;
}

请参阅

概念

处理结果操作指南主题 (OLE DB)