Obtendo dados grandes
Aplica-se a: SQL Server Banco de Dados SQL do Azure Instância Gerenciada de SQL do Azure Azure Synapse Analytics Analytics Platform System (PDW)
Em geral, os consumidores devem isolar o código que cria um objeto de armazenamento do OLE DB Driver for SQL Server do código que manipula dados não referenciados por meio de um ponteiro de interface ISequentialStream.
Este artigo refere-se à funcionalidade disponível com as seguintes funções:
IRowset:GetData
IRow::GetColumns
ICommand::Execute
O consumidor deverá buscar somente uma única linha de dados em uma chamada ao método GetNextRows quando a propriedade DBPROP_ACCESSORDER, no grupo de propriedades do conjunto de linhas, for definida como DBPROPVAL_AO_SEQUENTIAL ou DBPROPVAL_AO_SEQUENTIALSTORAGEOBJECTS. Isso ocorre porque os dados do BLOB não são armazenados em buffer. Se o valor de DBPROP_ACCESSORDER for definido como DBPROPVAL_AO_RANDOM, o consumidor poderá buscar várias linhas de dados em GetNextRows.
O Driver do OLE DB para SQL Server não recuperará dados grandes do SQL Server enquanto isso não for solicitado pelo consumidor. O consumidor deve associar todos os dados curtos em um acessador e usar um ou mais acessadores temporários para recuperar valores de dados grandes conforme necessário.
Exemplo
Este exemplo recupera um valor de dados grandes de uma única coluna:
HRESULT GetUnboundData
(
IRowset* pIRowset,
HROW hRow,
ULONG nCol,
BYTE* pUnboundData
)
{
UINT cbRow = sizeof(IUnknown*) + sizeof(ULONG);
BYTE* pRow = new BYTE[cbRow];
DBOBJECT dbobject;
IAccessor* pIAccessor = NULL;
HACCESSOR haccessor;
DBBINDING dbbinding;
ULONG ulbindstatus;
ULONG dwStatus;
ISequentialStream* pISequentialStream;
ULONG cbRead;
HRESULT hr;
// Set up the DBOBJECT structure.
dbobject.dwFlags = STGM_READ;
dbobject.iid = IID_ISequentialStream;
// Create the DBBINDING, requesting a storage-object pointer from
// The OLE DB Driver for SQL Server.
dbbinding.iOrdinal = nCol;
dbbinding.obValue = 0;
dbbinding.obStatus = sizeof(IUnknown*);
dbbinding.obLength = 0;
dbbinding.pTypeInfo = NULL;
dbbinding.pObject = &dbobject;
dbbinding.pBindExt = NULL;
dbbinding.dwPart = DBPART_VALUE | DBPART_STATUS;
dbbinding.dwMemOwner = DBMEMOWNER_CLIENTOWNED;
dbbinding.eParamIO = DBPARAMIO_NOTPARAM;
dbbinding.cbMaxLen = 0;
dbbinding.dwFlags = 0;
dbbinding.wType = DBTYPE_IUNKNOWN;
dbbinding.bPrecision = 0;
dbbinding.bScale = 0;
if (FAILED(hr = pIRowset->
QueryInterface(IID_IAccessor, (void**) &pIAccessor)))
{
// Process QueryInterface failure.
return (hr);
}
// Create the accessor.
if (FAILED(hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, 1,
&dbbinding, 0, &haccessor, &ulbindstatus)))
{
// Process error from CreateAccessor.
pIAccessor->Release();
return (hr);
}
// Read and process BLOCK_SIZE bytes at a time.
if (SUCCEEDED(hr = pIRowset->GetData(hRow, haccessor, pRow)))
{
dwStatus = *((ULONG*) (pRow + dbbinding.obStatus));
if (dwStatus == DBSTATUS_S_ISNULL)
{
// Process NULL data
}
else if (dwStatus == DBSTATUS_S_OK)
{
pISequentialStream = *((ISequentialStream**)
(pRow + dbbinding.obValue));
do
{
if (SUCCEEDED(hr =
pISequentialStream->Read(pUnboundData,
BLOCK_SIZE, &cbRead)))
{
pUnboundData += cbRead;
}
}
while (SUCCEEDED(hr) && cbRead >= BLOCK_SIZE);
pISequentialStream->Release();
}
}
else
{
// Process error from GetData.
}
pIAccessor->ReleaseAccessor(haccessor, NULL);
pIAccessor->Release();
delete [] pRow;
return (hr);
}