IRowsetFastLoad を使用したデータの一括コピー (OLE DB)
このサンプルでは、IRowsetFastLoad を使用して、レコードをテーブルに一括コピーする方法を示します。
コンシューマーは、SQLOLEDB プロバイダー固有のプロパティ SSPROP_ENABLEFASTLOAD を VARIANT_TRUE に設定することにより、一括コピーを実行する必要があることを SQLOLEDB に通知します。 コンシューマーはデータ ソースのプロパティ セットを使用して、SQLOLEDB セッションを作成します。 この新しいセッションによって、コンシューマーから IRowsetFastLoad にアクセスできるようになります。
IRowsetFastLoad を使用してレコードをテーブルに一括コピーする方法を示す完全なサンプル コードが用意されています。 このサンプルでは、テーブル IRFLTable に 10 個のレコードを追加します。 テーブル IRFLTable をデータベース内に作成する必要があります。
このサンプルには AdventureWorks サンプル データベースが必要です。このサンプル データベースは、Microsoft SQL Server のサンプルとコミュニティのプロジェクトのホーム ページからダウンロードできます。
セキュリティに関する注意 |
---|
可能な場合は、Windows 認証を使用します。 Windows 認証が使用できない場合は、実行時に資格情報を入力するようユーザーに求めます。 資格情報をファイルに保存するのは避けてください。 資格情報を保存する必要がある場合は、Win32 Crypto API を使用して暗号化してください。 |
SQL Server テーブルにデータを一括コピーするには
データ ソースへの接続を確立します。
SQLOLEDB プロバイダー固有のデータ ソース プロパティである SSPROP_ENABLEFASTLOAD を VARIANT_TRUE に設定します。 このプロパティを VARIANT_TRUE に設定すると、新しく作成されたセッションを使用して、コンシューマーから IRowsetFastLoad にアクセスできるようになります。
IOpenRowset インターフェイスを要求するセッションを作成します。
IOpenRowset::OpenRowset を呼び出して、(一括コピー操作によるデータのコピー先の) テーブルのすべての行が含まれる行セットを開きます。
必要なバインドを実行し、IAccessor::CreateAccessor を使用してアクセサーを作成します。
テーブルへのデータのコピー元となる、メモリ バッファーを設定します。
IRowsetFastLoad::InsertRow を呼び出して、テーブルにデータを一括コピーします。
使用例
この例では、テーブル IRFLTable に 10 個のレコードを追加します。 テーブル IRFLTable をデータベース内に作成する必要があります。 このサンプルは IA64 ではサポートされていません。
1 つ目の (Transact-SQL) コード リストを実行して、アプリケーションで使用するテーブルを作成します。
ole32.lib と oleaut32.lib を使用して次の C++ コード リストをコンパイルし、実行します。 このアプリケーションは、コンピューターの既定の SQL Server インスタンスに接続します。 一部の Windows オペレーティング システムでは、(localhost) または (local) を実際の SQL Server インスタンスの名前に変更する必要があります。 名前付きインスタンスに接続するには、接続文字列を L"(local)" から L"(local)\\name" に変更します。name は名前付きインスタンスです。 SQL Server Express は、既定で名前付きインスタンスとしてインストールされます。 INCLUDE 環境変数に、sqlncli.h が保存されているディレクトリが含まれていることを確認します。
3 つ目の (Transact-SQL) コード リストを実行して、アプリケーションで使用したテーブルを削除します。
USE AdventureWorks
GO
IF EXISTS (SELECT name FROM sysobjects WHERE name = 'IRFLTable')
DROP TABLE IRFLTable
GO
CREATE TABLE IRFLTable (col_vchar varchar(30))
// compile with: ole32.lib oleaut32.lib
#define DBINITCONSTANTS
#define OLEDBVER 0x0250 // to include correct interfaces
#include <oledb.h>
#include <oledberr.h>
#include <stdio.h>
#include <stddef.h> // for offsetof
#include <sqlncli.h>
// @type UWORD | 2 byte unsigned integer.
typedef unsigned short UWORD;
// @type SDWORD | 4 byte signed integer.
typedef signed long SDWORD;
WCHAR g_wszTable[] = L"IRFLTable";
WCHAR g_strTestLOC[100] = L"localhost";
WCHAR g_strTestDBName[] = L"AdventureWorks";
const UWORD g_cOPTION = 4;
const UWORD MAXPROPERTIES = 5;
const ULONG DEFAULT_CBMAXLENGTH = 20;
IMalloc* g_pIMalloc = NULL;
IDBInitialize* g_pIDBInitialize = NULL;
// Given an ICommand pointer, properties, and query, a rowsetpointer is returned.
HRESULT CreateSessionCommand( DBPROPSET* rgPropertySets, ULONG ulcPropCount, CLSID clsidProv );
// Use to set properties and execute a given query.
HRESULT ExecuteQuery ( IDBCreateCommand* pIDBCreateCommand,
WCHAR* pwszQuery,
DBPROPSET* rgPropertySets,
ULONG ulcPropCount,
LONG* pcRowsAffected,
IRowset** ppIRowset,
BOOL fSuccessOnly = TRUE );
// Use to set up options for call to IDBInitialize::Initialize.
void SetupOption ( DBPROPID PropID, WCHAR *wszVal, DBPROP * pDBProp );
// Sets fastload property on/off for session.
HRESULT SetFastLoadProperty(BOOL fSet);
// IRowsetFastLoad inserting data.
HRESULT FastLoadData();
// How to lay out each column in memory.
struct COLUMNDATA {
DBLENGTH dwLength; // Length of data (not space allocated).
DWORD dwStatus; // Status of column.
BYTE bData[1]; // Store data here as a variant.
};
#define COLUMN_ALIGNVAL 8
#define ROUND_UP(Size, Amount)(((DWORD)(Size) + ((Amount)-1)) & ~((Amount)-1))
int main() {
HRESULT hr = NOERROR;
HRESULT hr2 = NOERROR;
// OLE initialized?
BOOL fInitialized = FALSE;
// One property set for initializing.
DBPROPSET rgPropertySets[1];
// Properties within above property set.
DBPROP rgDBProperties[g_cOPTION];
IDBCreateCommand* pIDBCreateCommand = NULL;
IRowset* pIRowset = NULL;
DBPROPSET* rgProperties = NULL;
IAccessor* pIAccessor = NULL;
// Basic initialization.
if ( FAILED(CoInitialize(NULL)) )
goto cleanup;
else
fInitialized = TRUE;
hr = CoGetMalloc(MEMCTX_TASK, &g_pIMalloc);
if ((!g_pIMalloc) || FAILED(hr))
goto cleanup;
// Set up property set for call to IDBInitialize in CreateSessionCommand.
rgPropertySets[0].rgProperties = rgDBProperties;
rgPropertySets[0].cProperties = g_cOPTION;
rgPropertySets[0].guidPropertySet = DBPROPSET_DBINIT;
SetupOption(DBPROP_INIT_CATALOG, g_strTestDBName, &rgDBProperties[0]);
SetupOption(DBPROP_AUTH_INTEGRATED, L"SSPI", &rgDBProperties[1]);
SetupOption(DBPROP_INIT_DATASOURCE, g_strTestLOC, &rgDBProperties[3]);
if (!SUCCEEDED( hr = CreateSessionCommand(rgPropertySets, 1, CLSID_SQLNCLI11)))
goto cleanup;
// Get IRowsetFastLoad and insert data into IRFLTable.
if (FAILED(hr = FastLoadData()))
goto cleanup;
cleanup:
// Release memory.
if (rgProperties && rgProperties->rgProperties)
delete [](rgProperties->rgProperties);
if (rgProperties)
delete []rgProperties;
if (pIDBCreateCommand)
pIDBCreateCommand->Release();
if (pIAccessor)
pIAccessor->Release();
if (pIRowset)
pIRowset->Release();
if (g_pIMalloc)
g_pIMalloc->Release();
if (g_pIDBInitialize) {
hr2 = g_pIDBInitialize->Uninitialize();
if (FAILED(hr2))
printf("Uninitialize failed\n");
}
if (fInitialized)
CoUninitialize();
if (SUCCEEDED(hr))
printf("Test completed successfully.\n\n");
else
printf("Test failed.\n\n");
}
HRESULT FastLoadData() {
HRESULT hr = E_FAIL;
HRESULT hr2 = E_FAIL;
DBID TableID;
IDBCreateSession* pIDBCreateSession = NULL;
IOpenRowset* pIOpenRowsetFL = NULL;
IRowsetFastLoad* pIFastLoad = NULL;
IAccessor* pIAccessor = NULL;
HACCESSOR hAccessor = 0;
DBBINDSTATUS oneStatus = 0;
DBBINDING oneBinding;
ULONG ulOffset = 0;
TableID.uName.pwszName = NULL;
LONG i = 0;
void* pData = NULL;
COLUMNDATA* pcolData = NULL;
TableID.eKind = DBKIND_NAME;
// if ( !(TableID.uName.pwszName = new WCHAR[wcslen(g_wszTable) + 2]) )
LPOLESTR x = TableID.uName.pwszName = new WCHAR[wcslen(g_wszTable) + 2];
if (!x)
return E_FAIL;
wcsncpy_s(TableID.uName.pwszName, wcslen(g_wszTable) + 2, g_wszTable, wcslen(g_wszTable)+1);
TableID.uName.pwszName[wcslen(g_wszTable)+1] = (WCHAR) NULL;
// Get the fastload pointer.
if (FAILED(hr = SetFastLoadProperty(TRUE)))
goto cleanup;
if ( FAILED( hr =
g_pIDBInitialize->QueryInterface( IID_IDBCreateSession, (void **) &pIDBCreateSession )))
goto cleanup;
if ( FAILED( hr =
pIDBCreateSession->CreateSession( NULL, IID_IOpenRowset, (IUnknown **) &pIOpenRowsetFL )))
goto cleanup;
// Get IRowsetFastLoad initialized to use the test table.
if (FAILED(hr =
pIOpenRowsetFL->OpenRowset(NULL,
&TableID,
NULL,
IID_IRowsetFastLoad,
0,
NULL,
(LPUNKNOWN *)&pIFastLoad)))
goto cleanup;
// Set up custom bindings.
oneBinding.dwPart = DBPART_VALUE | DBPART_LENGTH | DBPART_STATUS;
oneBinding.iOrdinal = 1;
oneBinding.pTypeInfo = NULL;
oneBinding.obValue = ulOffset + offsetof(COLUMNDATA,bData);
oneBinding.obLength = ulOffset + offsetof(COLUMNDATA,dwLength);
oneBinding.obStatus = ulOffset + offsetof(COLUMNDATA,dwStatus);
oneBinding.cbMaxLen = 30; // Size of varchar column.
oneBinding.pTypeInfo = NULL;
oneBinding.pObject = NULL;
oneBinding.pBindExt = NULL;
oneBinding.dwFlags = 0;
oneBinding.eParamIO = DBPARAMIO_NOTPARAM;
oneBinding.dwMemOwner = DBMEMOWNER_CLIENTOWNED;
oneBinding.bPrecision= 0;
oneBinding.bScale = 0;
oneBinding.wType = DBTYPE_STR;
ulOffset = oneBinding.cbMaxLen + offsetof(COLUMNDATA, bData);
ulOffset = ROUND_UP( ulOffset, COLUMN_ALIGNVAL );
if ( FAILED( hr =
pIFastLoad->QueryInterface(IID_IAccessor, (void **) &pIAccessor)))
return hr;
if (FAILED(hr = pIAccessor->CreateAccessor( DBACCESSOR_ROWDATA,
1,
&oneBinding,
ulOffset,
&hAccessor,
&oneStatus)))
return hr;
// Set up memory buffer.
pData = new BYTE[40];
if (!(pData /* = new BYTE[40]*/ )) {
hr = E_FAIL;
goto cleanup;
}
pcolData = (COLUMNDATA*)pData;
pcolData->dwLength = (SDWORD)strlen("Show the data") + 1;
pcolData->dwStatus = 0;
memcpy(&(pcolData->bData), "Show the data", strlen("Show the data") + 1);
for ( i = 0 ; i < 10 ; i++ )
if (FAILED(hr = pIFastLoad->InsertRow(hAccessor, pData)))
goto cleanup;
if (FAILED(hr = pIFastLoad->Commit(TRUE)))
printf("Error on IRFL::Commit\n");
cleanup:
if (FAILED(hr2 = SetFastLoadProperty(FALSE)))
printf("SetFastLoadProperty(FALSE) failed with %x", hr2);
if (pIAccessor && hAccessor)
if (FAILED(pIAccessor->ReleaseAccessor(hAccessor, NULL)))
hr = E_FAIL;
if (pIAccessor)
pIAccessor->Release();
if (pIFastLoad)
pIFastLoad->Release();
if (pIOpenRowsetFL)
pIOpenRowsetFL->Release();
if (pIDBCreateSession)
pIDBCreateSession->Release();
if (TableID.uName.pwszName)
delete []TableID.uName.pwszName;
return hr;
}
HRESULT SetFastLoadProperty(BOOL fSet) {
HRESULT hr = S_OK;
IDBProperties* pIDBProps = NULL;
DBPROP rgProps[1];
DBPROPSET PropSet;
VariantInit(&rgProps[0].vValue);
rgProps[0].dwOptions = DBPROPOPTIONS_REQUIRED;
rgProps[0].colid = DB_NULLID;
rgProps[0].vValue.vt = VT_BOOL;
rgProps[0].dwPropertyID = SSPROP_ENABLEFASTLOAD;
if (fSet == TRUE)
rgProps[0].vValue.boolVal = VARIANT_TRUE;
else
rgProps[0].vValue.boolVal = VARIANT_FALSE;
PropSet.rgProperties = rgProps;
PropSet.cProperties = 1;
PropSet.guidPropertySet = DBPROPSET_SQLSERVERDATASOURCE;
if (SUCCEEDED(hr = g_pIDBInitialize->QueryInterface(IID_IDBProperties, (LPVOID *)&pIDBProps)))
hr = pIDBProps->SetProperties(1, &PropSet);
VariantClear(&rgProps[0].vValue);
if (pIDBProps)
pIDBProps->Release();
return hr;
}
HRESULT CreateSessionCommand( DBPROPSET* rgPropertySets,// @parm [in] property sets
ULONG ulcPropCount, // @parm [in] count of prop sets.
CLSID clsidProv) { // @parm [in] Provider CLSID.
HRESULT hr = NOERROR;
IDBCreateSession* pIDBCreateSession = NULL;
IDBProperties* pIDBProperties = NULL;
UWORD i = 0, j = 0; // indexes.
if (ulcPropCount && !rgPropertySets) {
hr = E_INVALIDARG;
return hr;
}
if (!SUCCEEDED(hr = CoCreateInstance(clsidProv,
NULL,CLSCTX_INPROC_SERVER,
IID_IDBInitialize,
(void **)&g_pIDBInitialize)))
goto CLEANUP;
if (!SUCCEEDED(hr = g_pIDBInitialize->QueryInterface( IID_IDBProperties,
(void **)&pIDBProperties)))
goto CLEANUP;
if (!SUCCEEDED(hr = pIDBProperties->SetProperties(ulcPropCount, rgPropertySets)))
goto CLEANUP;
if (!SUCCEEDED(hr = g_pIDBInitialize->Initialize())) {
printf("Call to initialize failed.\n");
goto CLEANUP;
}
CLEANUP:
if (pIDBProperties)
pIDBProperties->Release();
if (pIDBCreateSession)
pIDBCreateSession->Release();
for (i = 0 ; i < ulcPropCount ; i++)
for (j = 0 ; j < rgPropertySets[i].cProperties ; j++)
VariantClear(&(rgPropertySets[i].rgProperties[j]).vValue);
return hr;
}
void SetupOption (DBPROPID PropID, WCHAR *wszVal, DBPROP * pDBProp ) {
pDBProp->dwPropertyID = PropID;
pDBProp->dwOptions = DBPROPOPTIONS_REQUIRED;
pDBProp->colid = DB_NULLID;
pDBProp->vValue.vt = VT_BSTR;
pDBProp->vValue.bstrVal = SysAllocStringLen(wszVal, wcslen(wszVal));
}
USE AdventureWorks
GO
IF EXISTS (SELECT name FROM sysobjects WHERE name = 'IRFLTable')
DROP TABLE IRFLTable
GO