bcp_bind
SQL Server 2005 に一括コピーするために、プログラム変数からテーブル列にデータをバインドします。
構文
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 による行の転送に影響しません。
varchar(max)、varbinary(max)、nvarchar(max) など、サイズの大きな値をとる新しいデータ型の場合、eDataType パラメータで型を表すインジケータとして SQLCHARACTER、SQLVARCHAR、SQLVARBINARY、SQLBINARY、および SQLNCHAR を使用し、cbIndicator パラメータでプレフィックスのサイズを 8 にすることができます。bcp_bind 関数では、max 型の列に対応するフィールドにプレフィックスが指定されている場合、プレフィックスを 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 を呼び出すと、エラーが発生します。
例
// 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, strlen(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 and carry on.
break;
}
}
// Terminate the bulk copy operation.
if ((nRowsProcessed = bcp_done(hdbc)) == -1)
{
printf("Bulk-copy unsuccessful.\n");
return;
}
printf("%ld rows copied.\n", nRowsProcessed);
// Carry on.