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。NULL pData 表示将使用 bcp_moretext 将长数据值成块发送到 SQL Server。仅当与用户绑定字段对应的列为 BLOB 列时,用户才应将 pData 设置为 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 值结束的空字符串构成一个字节(终止符字节自身),请将 cbTerm 设置为 1。例如,若要指示 szName 中的字符串以 Null 值结束,并且应使用该终止符指示长度,请执行以下代码:

    bcp_bind(hdbc, szName, 0,
       SQL_VARLEN_DATA, "", 1,
       SQLCHARACTER, 2)
    

    该示例的非终止形式可以指示已将 szName 变量中的 15 个字符复制到绑定表的第二列:

    bcp_bind(hdbc, szName, 0, 15, 
       NULL, 0, SQLCHARACTER, 2)
    

    大容量复制 API 根据需要执行 Unicode 到 MBCS 的字符转换。确保终止符字节字符串和字节字符串的长度均已正确设置。例如,若要指示 szName 中的字符串为 Unicode 宽字符串且由 Unicode Null 终止符值终止,请执行以下代码:

    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 参数使用 sqlncli.h 中的 SQL Server 数据类型标记进行枚举,而不是 ODBC C 数据类型枚举器。例如,您可以使用特定于 SQL Server 的 SQLINT2 类型指定一个两个字节的整数:ODBC 类型的 SQL_C_SHORT。

    SQL Server 2005 引入了在 eDataType 参数中对 SQLXML 和 SQLUDT 数据类型标记的支持。

  • idxServerCol
    数据复制的目标数据库表中的列的序号位置。表中的第一列为列 1。列的序号位置通过 SQLColumns 报告。

返回值

SUCCEED 或 FAIL。

注释

使用 bcp_bind 将程序变量中的数据快速有效地复制到 SQL Server 的表中。

在调用此方法或任何其他大容量复制函数之前,请首先调用 bcp_init。调用 bcp_init 设置要进行大容量复制的 SQL Server 目标表。当调用 bcp_init,以便与 bcp_bindbcp_sendrow 配合使用时,指示数据文件的 bcp_initszDataFile 参数将设置为 NULL;bcp_initeDirection 参数设置为 DB_IN。

对要向其复制数据的 SQL Server 表中的每个列单独执行 bcp_bind 调用。执行必需的 bcp_bind 调用之后,调用 bcp_sendrow 将程序变量中的数据行发送到 SQL Server。

当希望 SQL Server 提交收到的行时,请调用 bcp_batch。例如,每插入 1000 行调用一次 bcp_batch,或以任何其他时间间隔为单位。

当没有要插入的行时,请调用 bcp_done。该操作失败将导致错误。

使用 bcp_control 指定的控制参数设置对 bcp_bind 行传输不起任何作用。

如果某列的 pData 设置为 NULL(因为将通过调用 bcp_moretext 来提供该列的值),那么,必须绑定 eDataType 设置为 SQLTEXT、SQLNTEXT、SQLXML、SQLUDT、SQLCHARACTER、SQLVARCHAR、SQLVARBINARY、SQLBINARY、SQLNCHAR 或 SQLIMAGE 的任何后续列,将 pData 设置为 NULL,并且还必须通过调用 bcp_moretext 来提供这些列的值。

对于新的大值类型(如 varchar(max)、varbinary(max) 或 nvarchar(max)),您可以在 eDataType 参数中使用 SQLCHARACTER、SQLVARCHAR、SQLVARBINARY、SQLBINARY 和 SQLNCHAR 作为类型指示符。

如果 cbTerm 不为 0,则所有值(1、2、4 或 8)均对前缀 (cbIndicator) 有效。在这种情况下,SQL Server Native Client 将搜索终止符,计算终止符的数据长度 (i),并将 cbData 设置为 i 和前缀值中的较小值。

如果 cbTerm 为 0 且 cbIndicator(前缀)不为 0,cbIndicator 必须为 8。此 8 个字节的前缀可以采用以下值:

  • 0xFFFFFFFFFFFFFFFF 表示字段为 Null 值。

  • 0xFFFFFFFFFFFFFFFE 被视为特殊前缀值,用于有效地向服务器成块发送数据。带有此特殊前缀的数据的格式为:

  • <SPECIAL_PREFIX> <零个或多个 DATA CHUNKS> <ZERO_CHUNK>,其中:

  • SPECIAL_PREFIX 为 0xFFFFFFFFFFFFFFFE

  • DATA_CHUNK 是包含块区长度的 4 个字节的前缀,后跟在该 4 个字节的前缀中指定其长度的实际数据。

  • ZERO_CHUNK 是全部由零组成的 4 个字节的值 (00000000),指示数据结束。

  • 任何其他有效的 8 个字节的长度均被视为常规数据长度。

使用 bcp_bind 时调用 bcp_columns 将导致错误。

bcp_bind 对日期和时间增强功能的支持

有关日期/时间类型的 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);

请参阅

参考