bcp_bind
SQL Server に一括コピーするために、プログラム変数からテーブル列にデータをバインドします。
構文
RETCODE bcp_bind (
HDBC
hdbc
,
LPCBYTE
pData
,
INT
cbIndicator
,
DBINT
cbData
,
LPCBYTE
pTerm
,
INT
cbTerm
,
INT
eDataType
,
INT
idxServerCol
);
引数
hdbc
一括コピーが有効な ODBC 接続ハンドルです。pData
コピーするデータを指すポインターです。eDataType が SQLTEXT、SQLNTEXT、SQLXML、SQLUDT、SQLCHARACTER、SQLVARCHAR、SQLVARBINARY、SQLBINARY、SQLNCHAR、または SQLIMAGE の場合、pData に NULL を指定できます。pData が NULL の場合は、bcp_moretext を使用して、長いデータ値をチャンク単位で SQL Server に送信することを示します。ユーザーがバインドするフィールドに対応する列が BLOB 列の場合は、pData を NULL に設定する必要があります。NULL 以外の場合は bcp_bind が失敗します。データ内にインジケーターが存在する場合、それらのインジケーターはメモリ内ではデータの直前にあります。この場合 pData パラメーターはインジケーター変数を指すので、一括コピーではインジケーターの幅である cbIndicator パラメーターを使用して、ユーザー データのアドレス指定が適切に行われます。
cbIndicator
列のデータに関する長さのインジケーターや NULL インジケーターのバイト単位の長さです。インジケーターの長さの有効値は、0 (インジケーターを使用しない場合)、1、2、4、または 8 です。インジケーターは、メモリ内ではすべてのデータの直前にあります。たとえば、一括コピーを使用して SQL Server テーブルに整数値を挿入するには、次のような構造体の型定義を使用します。typedef struct tagBCPBOUNDINT { int iIndicator; int Value; } BCPBOUNDINT;
この例の場合、pData パラメーターには、構造体の宣言済みのインスタンスのアドレス、つまり、BCPBOUNDINT 構造体の iIndicator メンバーのアドレスを設定することになります。cbIndicator パラメーターには整数のサイズ (sizeof(int)) を設定し、cbData パラメーターにも整数のサイズ (sizeof(int)) を設定します。バインドされる列に NULL 値が含まれている状態で、行をサーバーに一括コピーするには、インスタンスの iIndicator メンバーの値を SQL_NULL_DATA に設定する必要があります。
cbData
プログラム変数内のデータのバイト数です。長さのインジケーター、NULL インジケーター、およびターミネータの長さは含まれません。cbData を SQL_NULL_DATA に設定すると、サーバーにコピーされるすべての行では、列に NULL 値が含まれることを表します。
cbData を SQL_VARLEN_DATA に設定した場合、システムは文字列ターミネータやその他の方法を使用して、コピーされるデータの長さを決定します。
整数などの固定長データ型の場合、データ型によってデータの長さがシステムに示されます。そのため、固定長データ型の場合は、cbData を SQL_VARLEN_DATA にしても、データの長さにしても問題ありません。
SQL Server の文字データ型やバイナリ データ型の場合は、cbData を SQL_VARLEN_DATA、SQL_NULL_DATA、正の値、0 のいずれかにできます。cbData が SQL_VARLEN_DATA の場合、システムでは、長さのインジケーターや NULL インジケーター (存在する場合) またはターミネータ シーケンスを使用してデータの長さを決定します。インジケーターとターミネータ シーケンスの両方を指定した場合、システムでは、コピーされるデータ量が少なくなる方法が使用されます。cbData が SQL_VARLEN_DATA の場合、列のデータ型は SQL Server 文字型またはバイナリ型なので、長さのインジケーターとターミネータ シーケンスをどちらも指定しなかった場合は、システムからエラー メッセージが返されます。
cbData が 0 または正の値の場合、システムは cbData をデータ長として使用します。ただし、cbData に正の値を指定し、長さのインジケーターとターミネータ シーケンスを指定した場合、システムはコピーするデータ量が少なくなる方法を使用してデータ長を決定します。
cbData パラメーターの値はデータのバイト数を表します。文字データが Unicode ワイド文字で表されている場合、cbData パラメーター値が正の値のときは、各文字のサイズ (バイト数) に文字数を掛けた数を表します。
pTerm
このプログラム変数の終了位置をマークするバイト パターンがある場合、そのバイト パターンを指すポインターです。たとえば、通常、ANSI 文字列と MBCS C 文字列には 1 バイトのターミネータ (\0) があります。変数にターミネータがない場合は、pTerm に NULL を設定します。
C NULL ターミネータをプログラム変数のターミネータとして指定する場合、空文字列 ("") を使用できます。NULL 終端の空文字列は 1 バイト (ターミネータのバイト自体) だけで構成されるため、cbTerm に 1 を設定します。たとえば、szName の文字列が NULL 終端であることと、長さを示すためにターミネータを使用する必要があることを示すには、次のコードを使用します。
bcp_bind(hdbc, szName, 0, SQL_VARLEN_DATA, "", 1, SQLCHARACTER, 2)
この例の文字列がターミネータを使用しない形式の場合、バインドされるテーブルの 2 番目の列に szName 変数から 15 文字コピーすることを次のように指定できます。
bcp_bind(hdbc, szName, 0, 15, NULL, 0, SQLCHARACTER, 2)
一括コピー API では、必要に応じて Unicode から MBCS への文字変換が実行されます。ターミネータのバイト文字列とそのバイト文字列の長さの両方を正しく設定してください。たとえば、szName の文字列が、Unicode NULL ターミネータ値で終了する Unicode ワイド文字列であることを指定するには、次のコードを使用します。
bcp_bind(hdbc, szName, 0, SQL_VARLEN_DATA, L"", sizeof(WCHAR), SQLNCHAR, 2)
バインドする SQL Server 列がワイド文字の場合、bcp_sendrow で変換は実行されません。SQL Server 列が MBCS 文字型の場合、データが SQL Server に送信されるときに、ワイド文字がマルチバイト文字に変換されます。
cbTerm
プログラム変数にターミネータがある場合は、そのターミネータを構成するバイト数です。変数にターミネータがない場合は、cbTerm に 0 を設定します。eDataType
プログラム変数の C データ型です。プログラム変数内のデータは、データベース列の型に変換されます。このパラメーターが 0 の場合、変換は実行されません。eDataType パラメーターは、ODBC C データ型の列挙子ではなく、sqlncli.h 内の SQL Server データ型のトークンで列挙されます。たとえば、SQL Server 固有の SQLINT2 型を使用して、ODBC の SQL_C_SHORT 型の 2 バイトの整数を指定できます。
SQL Server 2005 では、eDataType パラメーターでの SQLXML データ型および SQLUDT データ型のトークンのサポートが導入されました。
idxServerCol
データベース テーブル内にある、データのコピー先となる列の序数位置です。テーブル内の最初の列は列 1 です。列の序数位置は SQLColumns で報告されます。
戻り値
SUCCEED または FAIL を返します。
説明
SQL Server では、bcp_bind を使用すると、プログラム変数からテーブルに高速かつ効率的にデータをコピーできます。
この関数や他の一括コピー関数を呼び出す前に、bcp_init を呼び出します。bcp_init を呼び出すと、一括コピーの対象になる SQL Server テーブルが設定されます。bcp_bind や bcp_sendrow で使用するために bcp_init を呼び出すと、データ ファイルを示す bcp_initszDataFile パラメーターが NULL に設定され、bcp_initeDirection パラメーターが DB_IN に設定されます。
コピー先の SQL Server テーブル内にある列ごとに、bcp_bind を個別に呼び出します。必要な bcp_bind 呼び出しを行った後、bcp_sendrow を呼び出してプログラム変数から SQL Server にデータの行を送信します。列の再バインドはサポートされていません。
既に受信した行を SQL Server でコミットするときは、必ず bcp_batch を呼び出します。たとえば、bcp_batch を挿入する 1000 行ごとに呼び出したり、他の任意の間隔で呼び出します。
挿入する行がなくなったら、bcp_done を呼び出します。この操作を行わないと、エラーが発生します。
bcp_control で指定した制御パラメーターの設定は、bcp_bind による行の転送に影響しません。
列の pData が NULL に設定され、値が bcp_moretext の呼び出しにより提供される予定である場合、eDataType が SQLTEXT、SQLNTEXT、SQLXML、SQLUDT、SQLCHARACTER、SQLVARCHAR、SQLVARBINARY、SQLBINARY、SQLNCHAR、SQLIMAGE のいずれかに設定されている後続のすべての列も、NULL に設定された pData にバインドされ、値が bcp_moretext の呼び出しにより提供される必要があります。
varchar(max)、varbinary(max)、nvarchar(max) など、サイズの大きな値をとる新しいデータ型の場合、eDataType パラメーターで型を表すインジケーターとして SQLCHARACTER、SQLVARCHAR、SQLVARBINARY、SQLBINARY、および SQLNCHAR を使用できます。
cbTerm が 0 以外の場合、プレフィックス (cbIndicator) には任意の値 (1、2、4、または 8) を使用できます。この場合、SQL Server Native Client は、ターミネータを検索し、ターミネータを基準とするデータ長を計算して (i)、cbData に i のより小さい値およびプレフィックスの値を設定します。
cbTerm が 0 で、cbIndicator (プレフィックス) が 0 以外の場合、cbIndicator は 8 にする必要があります。8 バイトのプレフィックスでは、次の値を受け取ることができます。
0xFFFFFFFFFFFFFFFF は、フィールドの NULL 値を示します。
0xFFFFFFFFFFFFFFFE は、データをチャンク単位でサーバーに効率的に送信するために使用する特別なプレフィックスの値として処理されます。この特別なプレフィックス値を含むデータは、次のような形式になります。
<SPECIAL_PREFIX> <0 個以上の DATA_CHUNK> <ZERO_CHUNK>。この場合、指定する値は次のとおりです。
SPECIAL_PREFIX には 0xFFFFFFFFFFFFFFFE を指定します。
DATA_CHUNK には、チャンクの長さを含む 4 バイトのプレフィックスを指定し、その後に 4 バイトのプレフィックスで長さを指定した実際のデータを指定します。
ZERO_CHUNK には、データの終了を示す、すべてがゼロの 4 バイトの値 (00000000) を指定します。
その他の有効な 8 バイト長は、通常のデータ長として処理されます。
bcp_bind を使用するときに bcp_columns を呼び出すと、エラーが発生します。
bcp_bind による機能強化された日付と時刻のサポート
date 型または time 型の eDataType パラメーターと共に使用される型の詳細については、「機能強化された日付型と時刻型向けの一括コピーの変更 (OLE DB および ODBC)」を参照してください。
詳細については、「日付/時刻の強化 (ODBC)」を参照してください。
使用例
#include sql.h
#include sqlext.h
#include odbcss.h
// Variables like henv not specified.
HDBC hdbc;
char szCompanyName[MAXNAME];
DBINT idCompany;
DBINT nRowsProcessed;
DBBOOL bMoreData;
char* pTerm = "\t\t";
// Application initiation, get an ODBC environment handle, allocate the
// hdbc, and so on.
...
// Enable bulk copy prior to connecting on allocated hdbc.
SQLSetConnectAttr(hdbc, SQL_COPT_SS_BCP, (SQLPOINTER) SQL_BCP_ON,
SQL_IS_INTEGER);
// Connect to the data source; return on error.
if (!SQL_SUCCEEDED(SQLConnect(hdbc, _T("myDSN"), SQL_NTS,
_T("myUser"), SQL_NTS, _T("myPwd"), SQL_NTS)))
{
// Raise error and return.
return;
}
// Initialize bcp.
if (bcp_init(hdbc, "comdb..accounts_info", NULL, NULL
DB_IN) == FAIL)
{
// Raise error and return.
return;
}
// Bind program variables to table columns.
if (bcp_bind(hdbc, (LPCBYTE) &idCompany, 0, sizeof(DBINT), NULL, 0,
SQLINT4, 1) == FAIL)
{
// Raise error and return.
return;
}
if (bcp_bind(hdbc, (LPCBYTE) szCompanyName, 0, SQL_VARLEN_DATA,
(LPCBYTE) pTerm, strnlen(pTerm, sizeof(pTerm)), SQLCHARACTER, 2) == FAIL)
{
// Raise error and return.
return;
}
while (TRUE)
{
// Retrieve and process program data.
if ((bMoreData = getdata(&idCompany, szCompanyName)) == TRUE)
{
// Send the data.
if (bcp_sendrow(hdbc) == FAIL)
{
// Raise error and return.
return;
}
}
else
{
// Break out of loop.
break;
}
}
// Terminate the bulk copy operation.
if ((nRowsProcessed = bcp_done(hdbc)) == -1)
{
printf_s("Bulk-copy unsuccessful.\n");
return;
}
printf_s("%ld rows copied.\n", nRowsProcessed);