IBCPSession2::BCPSetBulkMode
IBCPSession2::BCPSetBulkMode rappresenta un'alternativa a IBCPSession::BCPColFmt (OLE DB) per la specifica del formato della colonna. A differenza di IBCPSession::BCPColFmt, che consente di impostare singoli attributi di formato di colonna, IBCPSession2::BCPSetBulkMode consente di impostare tutti gli attributi.
Sintassi
HRESULT BCPSetBulkMode (
int property,
void * pField,
int cbField,
void * pRow,
int cbRow
);
Argomenti
property
Costante di tipo BYTE. Per un elenco di costanti, vedere la tabella nella sezione Osservazioni.pField
Puntatore al valore del carattere di terminazione del campo.cbField
Lunghezza, in byte, del valore del carattere di terminazione del campo.pRow
Puntatore al valore del carattere di terminazione della riga.cbRow
Lunghezza, in byte, del valore del carattere di terminazione della riga.
Valori restituiti
IBCPSession2::BCPSetBulkMode può restituire uno dei valori seguenti:
S_OK |
Il metodo è riuscito. |
E_FAIL |
Si è verificato un errore specifico del provider. Per informazioni dettagliate, utilizzare l'interfaccia ISQLServerErrorInfo. |
E_UNEXPECTED |
La chiamata al metodo non era prevista. Non è stato ad esempio chiamato il metodo IBCPSession2::BCPInit prima di chiamare IBCPSession2::BCPSetBulkMode. |
E_INVALIDARG |
L'argomento non è valido. |
E_OUTOFMEMORY |
Errore di memoria insufficiente. |
Osservazioni
È possibile utilizzare IBCPSession2::BCPSetBulkMode per eseguire una copia bulk da una query o una tabella. Quando si utilizza IBCPSession2::BCPSetBulkMode per eseguire una copia bulk da un'istruzione di query, è necessario chiamare tale metodo prima di IBCPSession::BCPControl(BCP_OPTIONS_HINTS, …) per specificare l'istruzione di query.
È necessario evitare di combinare la sintassi di chiamata RPC con la sintassi di query batch (ad esempio {rpc func};SELECT * from Tbl) in un unico testo di comando. Un'operazione di questo tipo comporterebbe la restituzione di un errore da parte di ICommandPrepare::Prepare, rendendo impossibile il recupero dei metadati. Utilizzare la sintassi ODBC CALL (ad esempio {call func}; SELECT * from Tbl) se è necessario combinare l'esecuzione della stored procedure e una query batch in un singolo testo di comando.
Nella tabella seguente sono elencate le costanti per il parametro property.
Proprietà |
Descrizione |
---|---|
BCP_OUT_CHARACTER_MODE |
Specifica la modalità di output carattere. Corrisponde all'opzione -c in BCP.EXE e a IBCPSession::BCPColFmt con la proprietà eUserDataType impostata su BCP_TYPE_SQLCHARACTER. |
BCP_OUT_WIDE_CHARACTER_MODE |
Specifica la modalità di output Unicode. Corrisponde all'opzione -w in BCP.EXE e a IBCPSession::BCPColFmt con la proprietà eUserDataType impostata su BCP_TYPE_SQLNCHAR. |
BCP_OUT_NATIVE_TEXT_MODE |
Specifica tipi nativi per i tipi non carattere e Unicode per i tipi carattere. Corrisponde all'opzione -N in BCP.EXE e a IBCPSession::BCPColFmt con la proprietà eUserDataType impostata su BCP_TYPE_SQLNCHAR se il tipo di colonna è una stringa o su BCP_TYPE_DEFAULT se non è una stringa. |
BCP_OUT_NATIVE_MODE |
Specifica tipi di database nativi. Corrisponde all'opzione -n in BCP.EXE e a IBCPSession::BCPColFmt con la proprietà eUserDataType impostata su BCP_TYPE_DEFAULT. |
È possibile chiamare IBCPSession::BCPControl e IBCPSession2::BCPSetBulkMode per le opzioni IBCPSession::BCPControl che non comportano conflitti con IBCPSession2::BCPSetBulkMode. È ad esempio possibile chiamare IBCPSession::BCPControl con BCP_OPTION_FIRST e IBCPSession2::BCPSetBulkMode.
Non è possibile chiamare IBCPSession::BCPControl con BCP_OPTION_TEXTFILE e IBCPSession2::BCPSetBulkMode.
Se si tenta di chiamare IBCPSession2::BCPSetBulkMode con una sequenza di chiamate di funzione che include IBCPSession::BCPColFmt, IBCPSession::BCPControl e IBCPSession::BCPReadFmt, una delle chiamate di funzione restituirà un errore nella sequenza. Se si sceglie di correggere l'errore, chiamare IBCPSession::BCPInit per reimpostare le impostazioni e ricominciare.
Nella tabella seguente sono illustrati alcuni esempi di chiamate di funzione che comportano un errore nella sequenza della funzione:
Sequenza di chiamata |
---|
|
|
|
|
|
|
|
|
Esempio
Nell'esempio seguente vengono creati quattro file utilizzando impostazioni diverse per IBCPSession2::BCPSetBulkMode.
// compile with: sqlncli11.lib oleaut32.lib ole32.lib
#include <stdio.h>
#include "sqlncli.h"
IDBInitialize* g_pIDBInitialize = NULL;
IBCPSession2 * g_pIBcpSession = NULL;
class COLEDBPropSet : public DBPROPSET {
public:
COLEDBPropSet() {
rgProperties = NULL;
cProperties = 0;
};
COLEDBPropSet(const GUID& guid) {
rgProperties = NULL;
cProperties = 0;
guidPropertySet = guid;
};
~COLEDBPropSet() {
for ( ULONG i = 0 ; i < cProperties ; i++ )
VariantClear(&rgProperties[i].vValue);
CoTaskMemFree(rgProperties);
}
void SetGUID(const GUID& guid) {
guidPropertySet = guid;
};
bool AddProperty(DWORD dwPropertyID, bool bValue) {
if (!Add())
return false;
rgProperties[cProperties].dwPropertyID = dwPropertyID;
rgProperties[cProperties].vValue.vt = VT_BOOL;
rgProperties[cProperties].vValue.boolVal = (bValue) ? VARIANT_TRUE : VARIANT_FALSE;
cProperties++;
return true;
};
bool AddProperty(DWORD dwPropertyID, long nValue) {
if (!Add())
return false;
rgProperties[cProperties].dwPropertyID = dwPropertyID;
rgProperties[cProperties].vValue.vt = VT_I4;
rgProperties[cProperties].vValue.lVal = nValue;
cProperties++;
return true;
};
bool AddProperty(DWORD dwPropertyID,LPCWSTR szValue) {
if (!Add())
return false;
rgProperties[cProperties].dwPropertyID = dwPropertyID;
rgProperties[cProperties].vValue.vt = VT_BSTR;
rgProperties[cProperties].vValue.bstrVal = SysAllocString(szValue);
cProperties++;
return true;
};
bool Add() {
DBPROP* p = (DBPROP*)CoTaskMemRealloc(rgProperties, (cProperties + 1) * sizeof(DBPROP));
if (p != NULL) {
rgProperties = p;
rgProperties[cProperties].dwOptions = DBPROPOPTIONS_REQUIRED;
rgProperties[cProperties].colid = DB_NULLID;
rgProperties[cProperties].vValue.vt = VT_EMPTY;
return true;
}
else
return false;
};
};
void OLEDBCleanUp() {
if (g_pIDBInitialize) {
g_pIDBInitialize->Release();
g_pIDBInitialize = NULL;
}
if (g_pIBcpSession) {
g_pIBcpSession->Release();
g_pIBcpSession = NULL;
}
}
BOOL MakeOLEDBConnect(LPWSTR pServer) {
BOOL ret = true;
IDBProperties * pIDBProperties = NULL;
IDBCreateSession * pIDBCreateSession = NULL;
COLEDBPropSet PropSet(DBPROPSET_DBINIT);
COLEDBPropSet BcpProperty(DBPROPSET_SQLSERVERDATASOURCE);
try {
HRESULT hr = CoInitializeEx(NULL,COINIT_MULTITHREADED);
hr = CoCreateInstance(SQLNCLI_CLSID, NULL, CLSCTX_INPROC_SERVER, IID_IDBInitialize, (LPVOID *)&g_pIDBInitialize);
if (FAILED(hr)) {
printf("CoCreateInstance failed\n");
return false;
}
PropSet.AddProperty(DBPROP_INIT_DATASOURCE, (LPWSTR)pServer);
PropSet.AddProperty(DBPROP_AUTH_INTEGRATED, L"SSPI");
hr = g_pIDBInitialize->QueryInterface(IID_IDBProperties, (void**) &pIDBProperties);
if (FAILED(hr)) {
printf("g_pIDBInitialize->->QueryInterface(IID_IDBProperties...) failed\n");
throw false;
}
hr = pIDBProperties->SetProperties(1, &PropSet);
if (FAILED(hr)) {
printf("g_pIDBInitialize->->SetProperties(...) failed\n");
throw false;
}
hr = g_pIDBInitialize->Initialize();
if (FAILED(hr)) {
printf("g_pIDBInitialize->->Initialize() failed\n");
throw false;
}
BcpProperty.AddProperty(SSPROP_ENABLEFASTLOAD, true);
BcpProperty.AddProperty(SSPROP_ENABLEBULKCOPY, true);
hr = pIDBProperties->SetProperties(1, &BcpProperty);
if (FAILED(hr)) {
printf("g_pIDBInitialize->->SetProperties() for bcp failed\n");
throw false;
}
hr = g_pIDBInitialize->QueryInterface(IID_IDBCreateSession, (void**) &pIDBCreateSession);
if (FAILED(hr)) {
printf("g_pIDBInitialize->QueryInterface(IID_IDBCreateSession..) failed\n");
throw false;
}
hr = pIDBCreateSession->CreateSession(NULL, IID_IBCPSession2, (IUnknown**) &g_pIBcpSession);
if (FAILED(hr)) {
printf("g_pIDBCreateSession->CreateSession() failed\n");
throw false;
}
}
catch(...) {
ret = false;
}
if (pIDBProperties)
pIDBProperties->Release();
if (pIDBCreateSession)
pIDBCreateSession->Release();
return ret;
}
BOOL BCPSetBulkMode(LPWSTR pszServer, LPTSTR pszQureryOut, char BCPType, LPWSTR pszDataFile) {
HRESULThr;
if (!MakeOLEDBConnect(pszServer))
return false;
hr = g_pIBcpSession->BCPInit(NULL, pszDataFile, NULL, BCP_DIRECTION_OUT ); // bcp init for queryout
if (FAILED(hr)) {
printf("BCP init failed\n");
OLEDBCleanUp();
return false;
}
// setbulkmode
char ColTerm[] = "\t";
char RowTerm[] = "\r\n";
wchar_t wColTerm[] = L"\t";
wchar_t wRowTerm[] = L"\r\n";
BYTE * pColTerm = NULL;
int cbColTerm = NULL;
BYTE * pRowTerm = 0;
int cbRowTerm = 0;
int bulkmode = -1;
if(BCPType == 'c') { // bcp -c
pColTerm = (BYTE*)ColTerm;
pRowTerm = (BYTE*)RowTerm;
cbColTerm = 1;
cbRowTerm = 2;
bulkmode = BCP_OUT_CHARACTER_MODE;
}
else
if(BCPType == 'w') { // bcp -w
pColTerm = (BYTE*)wColTerm;
pRowTerm = (BYTE*)wRowTerm;
cbColTerm = 2;
cbRowTerm = 4;
bulkmode = BCP_OUT_WIDE_CHARACTER_MODE;
}
else
if (BCPType == 'n') // bcp -n
bulkmode = BCP_OUT_NATIVE_MODE;
else
if (BCPType == 'N') // bcp -n
bulkmode = BCP_OUT_NATIVE_TEXT_MODE;
else {
printf("unknown bcp mode\n");
OLEDBCleanUp();
return false;
}
hr = g_pIBcpSession->BCPSetBulkMode(bulkmode, pColTerm, cbColTerm, pRowTerm, cbRowTerm);
if (FAILED(hr)) {
printf("BCPSetBulkMode failed\n");
OLEDBCleanUp();
return false;
}
// set queryout TSQL statement
hr = g_pIBcpSession->BCPControl(BCP_OPTION_HINTS, pszQureryOut);
if (FAILED(hr)) {
printf("BCPControl failed\n");
OLEDBCleanUp();
return false;
}
// bcp copy
DBROWCOUNT nRowsInserted = 0;
hr = g_pIBcpSession->BCPExec(&nRowsInserted);
if (FAILED(hr)) {
printf("BCPExec failed\n");
OLEDBCleanUp();
return false;
}
printf("bcp done\n");
OLEDBCleanUp();
return true;
}
int main() {
BCPSetBulkMode(L"localhost", TEXT("SELECT 'this is a bcp -c test', 1,2") , 'c', L"bcpc.dat");
BCPSetBulkMode(L"localhost", TEXT("SELECT 'this is a bcp -w test', 1,2") , 'w', L"bcpw.dat");
BCPSetBulkMode(L"localhost", TEXT("SELECT 'this is a bcp -c test', 1,2") , 'n', L"bcpn.dat");
BCPSetBulkMode(L"localhost", TEXT("SELECT 'this is a bcp -w test', 1,2") , 'N', L"bcp_N.dat");
}