SQLBulkOperations 函数SQLBulkOperations Function

Conformance
引入的版本:ODBC 3.0 标准符合性:ODBCVersion Introduced: ODBC 3.0 Standards Compliance: ODBC

摘要Summary
SQLBulkOperations执行批量插入和批量书签操作, 包括更新、删除和按书签提取。SQLBulkOperations performs bulk insertions and bulk bookmark operations, including update, delete, and fetch by bookmark.

语法Syntax

  
SQLRETURN SQLBulkOperations(  
     SQLHSTMT       StatementHandle,  
     SQLUSMALLINT   Operation);  

参数Arguments

StatementHandleStatementHandle
送语句句柄。[Input] Statement handle.

运算Operation
送要执行的操作:[Input] Operation to perform:

SQL_ADD SQL_UPDATE_BY_BOOKMARK SQL_DELETE_BY_BOOKMARK SQL_FETCH_BY_BOOKMARKSQL_ADD SQL_UPDATE_BY_BOOKMARK SQL_DELETE_BY_BOOKMARK SQL_FETCH_BY_BOOKMARK

有关详细信息, 请参阅 "注释"。For more information, see "Comments."

返回Returns

SQL_SUCCESS、SQL_SUCCESS_WITH_INFO、SQL_NEED_DATA、SQL_STILL_EXECUTING、SQL_ERROR 或 SQL_INVALID_HANDLE。SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_NEED_DATA, SQL_STILL_EXECUTING, SQL_ERROR, or SQL_INVALID_HANDLE.

诊断Diagnostics

SQLBulkOperations返回 SQL_ERROR 或 SQL_SUCCESS_WITH_INFO 时, 可以通过SQLGetDiagRec 的 HandleType和 SQL_HANDLE_STMT 的句柄调用StatementHandle来获取关联的 SQLSTATE 值 .When SQLBulkOperations returns SQL_ERROR or SQL_SUCCESS_WITH_INFO, an associated SQLSTATE value can be obtained by calling SQLGetDiagRec with a HandleType of SQL_HANDLE_STMT and a Handle of StatementHandle. 下表列出了通常由SQLBulkOperations返回的 SQLSTATE 值, 并对该函数的上下文中的每个值进行了说明:"(DM)" 表示法位于驱动程序管理器返回的 SQLSTATEs 的说明之前。The following table lists the SQLSTATE values typically returned by SQLBulkOperations and explains each one in the context of this function; the notation "(DM)" precedes the descriptions of SQLSTATEs returned by the Driver Manager. 除非另有说明, 否则与每个 SQLSTATE 值相关联的返回代码为 SQL_ERROR。The return code associated with each SQLSTATE value is SQL_ERROR, unless noted otherwise.

对于可以返回 SQL_SUCCESS_WITH_INFO 或 SQL_ERROR 的所有 SQLSTATEs (除了 01xxx SQLSTATEs), 如果在一个或多个 (但不是全部) 行上发生错误, 则将返回 SQL_SUCCESS_WITH_INFO; 如果发生错误, 则返回多行单行操作。For all those SQLSTATEs that can return SQL_SUCCESS_WITH_INFO or SQL_ERROR (except 01xxx SQLSTATEs), SQL_SUCCESS_WITH_INFO is returned if an error occurs on one or more, but not all, rows of a multirow operation, and SQL_ERROR is returned if an error occurs on a single-row operation.

SQLSTATESQLSTATE ErrorError 描述Description
0100001000 一般警告General warning 驱动程序特定的信息性消息。Driver-specific informational message. (函数返回 SQL_SUCCESS_WITH_INFO。)(Function returns SQL_SUCCESS_WITH_INFO.)
0100401004 字符串数据右截断String data right truncation 操作参数为 SQL_FETCH_BY_BOOKMARK, 返回的数据类型为 SQL_C_CHAR 或 SQL_C_BINARY 的列的字符串或二进制数据导致截断非空白字符或非 NULL 二进制数据。The Operation argument was SQL_FETCH_BY_BOOKMARK, and string or binary data returned for a column or columns with a data type of SQL_C_CHAR or SQL_C_BINARY resulted in the truncation of nonblank character or non-NULL binary data.
01S0101S01 行中的错误Error in row 操作参数为 SQL_ADD, 执行该操作时在一行或多行中出现错误, 但至少成功添加了一行。The Operation argument was SQL_ADD, and an error occurred in one or more rows while performing the operation but at least one row was successfully added. (函数返回 SQL_SUCCESS_WITH_INFO。)(Function returns SQL_SUCCESS_WITH_INFO.)

(仅当应用程序使用 ODBC 2 时才引发此错误。x驱动程序。)(This error is raised only when an application is working with an ODBC 2.x driver.)
01S0701S07 小数截断Fractional truncation 操作参数为 SQL_FETCH_BY_BOOKMARK, 应用程序缓冲区的数据类型不是 SQL_C_CHAR 或 SQL_C_BINARY, 而且返回到一列或多列的应用程序缓冲区的数据被截断。The Operation argument was SQL_FETCH_BY_BOOKMARK, the data type of the application buffer was not SQL_C_CHAR or SQL_C_BINARY, and the data returned to application buffers for one or more columns was truncated. (对于数字 C 数据类型, 数值的小数部分被截断。(For numeric C data types, the fractional part of the number was truncated. 对于包含时间部分的时间、时间戳和时间间隔 C 数据类型, 时间的小数部分将被截断。)For time, timestamp, and interval C data types that contain a time component, the fractional portion of the time was truncated.)

(函数返回 SQL_SUCCESS_WITH_INFO。)(Function returns SQL_SUCCESS_WITH_INFO.)
0700607006 受限制的数据类型属性冲突Restricted data type attribute violation 操作参数为 SQL_FETCH_BY_BOOKMARK, 并且在对SQLBindCol的调用中, 结果集中的列的数据值无法转换为TargetType参数指定的数据类型。The Operation argument was SQL_FETCH_BY_BOOKMARK, and the data value of a column in the result set could not be converted to the data type specified by the TargetType argument in the call to SQLBindCol.

操作参数为 SQL_UPDATE_BY_BOOKMARK 或 SQL_ADD, 应用程序缓冲区中的数据值无法转换为结果集中列的数据类型。The Operation argument was SQL_UPDATE_BY_BOOKMARK or SQL_ADD, and the data value in the application buffers could not be converted to the data type of a column in the result set.
0700907009 描述符索引无效Invalid descriptor index 参数操作已 SQL_ADD, 并且列的列号大于结果集中的列数。The argument Operation was SQL_ADD, and a column was bound with a column number greater than the number of columns in the result set.
21S0221S02 派生表的等级与列列表不匹配Degree of derived table does not match column list 参数操作为 SQL_UPDATE_BY_BOOKMARK;由于所有列均为未绑定或只读, 或者绑定长度/指示器缓冲区中的值为 SQL_COLUMN_IGNORE, 因此没有可更新的列。The argument Operation was SQL_UPDATE_BY_BOOKMARK; and no columns were updatable because all columns were either unbound or read-only, or the value in the bound length/indicator buffer was SQL_COLUMN_IGNORE.
2200122001 字符串数据右截断String data right truncation 将字符或二进制值分配到结果集中的列导致截断非空白字符 (对于字符) 或非 null (对于二进制) 字符或字节。The assignment of a character or binary value to a column in the result set resulted in the truncation of nonblank (for characters) or non-null (for binary) characters or bytes.
2200322003 数值超出范围Numeric value out of range 操作参数为 SQL_ADD 或 SQL_UPDATE_BY_BOOKMARK, 并将数值分配给结果集中的列, 导致整个 (而非分数) 数字部分被截断。The Operation argument was SQL_ADD or SQL_UPDATE_BY_BOOKMARK, and the assignment of a numeric value to a column in the result set caused the whole (as opposed to fractional) part of the number to be truncated.

参数操作已 SQL_FETCH_BY_BOOKMARK, 返回一个或多个绑定列的数值将导致有效位丢失。The argument Operation was SQL_FETCH_BY_BOOKMARK, and returning the numeric value for one or more bound columns would have caused a loss of significant digits.
2200722007 Datetime 格式无效Invalid datetime format 操作参数为 SQL_ADD 或 SQL_UPDATE_BY_BOOKMARK, 并将日期或时间戳值分配给结果集中的列导致年、月或日字段超出范围。The Operation argument was SQL_ADD or SQL_UPDATE_BY_BOOKMARK, and the assignment of a date or timestamp value to a column in the result set caused the year, month, or day field to be out of range.

参数操作已 SQL_FETCH_BY_BOOKMARK, 返回一个或多个绑定列的日期或时间戳值将导致年、月或日字段超出范围。The argument Operation was SQL_FETCH_BY_BOOKMARK, and returning the date or timestamp value for one or more bound columns would have caused the year, month, or day field to be out of range.
2200822008 日期/时间字段溢出Date/time field overflow 操作参数为 SQL_ADD 或 SQL_UPDATE_BY_BOOKMARK, 并且对要发送到结果集中的列的数据进行 datetime 算法的性能导致了结果的日期时间字段 (年、月、日、小时、分钟或秒字段)超出了字段的允许值范围, 或根据公历的 datetime 自然规则无效。The Operation argument was SQL_ADD or SQL_UPDATE_BY_BOOKMARK, and the performance of datetime arithmetic on data being sent to a column in the result set resulted in a datetime field (the year, month, day, hour, minute, or second field) of the result falling outside the permissible range of values for the field or being invalid based on the Gregorian calendar's natural rules for datetimes.

操作参数为 SQL_FETCH_BY_BOOKMARK, 而从结果集检索的数据的 datetime 算法的性能导致了日期时间字段 (年、月、日、小时、分钟或秒字段)字段的允许值范围, 或基于公历的 datetime 自然规则无效。The Operation argument was SQL_FETCH_BY_BOOKMARK, and the performance of datetime arithmetic on data being retrieved from the result set resulted in a datetime field (the year, month, day, hour, minute, or second field) of the result falling outside the permissible range of values for the field or being invalid based on the Gregorian calendar's natural rules for datetimes.
2201522015 间隔字段溢出Interval field overflow 操作参数为 SQL_ADD 或 SQL_UPDATE_BY_BOOKMARK, 并将精确数字或间隔 C 类型分配给时间间隔 SQL 数据类型导致了有效位丢失。The Operation argument was SQL_ADD or SQL_UPDATE_BY_BOOKMARK, and the assignment of an exact numeric or interval C type to an interval SQL data type caused a loss of significant digits.

操作参数为 SQL_ADD 或 SQL_UPDATE_BY_BOOKMARK;当分配给某个间隔 SQL 类型时, interval SQL 类型中不存在 C 类型的值的表示形式。The Operation argument was SQL_ADD or SQL_UPDATE_BY_BOOKMARK; when assigning to an interval SQL type, there was no representation of the value of the C type in the interval SQL type.

操作参数为 SQL_FETCH_BY_BOOKMARK, 并从精确数值或间隔 SQL 类型赋值到 interval C 类型, 导致前导字段的有效位丢失。The Operation argument was SQL_FETCH_BY_BOOKMARK, and assigning from an exact numeric or interval SQL type to an interval C type caused a loss of significant digits in the leading field.

操作参数为 SQL_FETCH_BY_BOOKMARK;当分配到某个时间间隔 C 类型时, 在 "C #" 类型的 "SQL 类型" 值中没有表示形式。The Operation argument was SQL_FETCH_BY_BOOKMARK; when assigning to an interval C type, there was no representation of the value of the SQL type in the interval C type.
2201822018 转换规范的字符值无效Invalid character value for cast specification 操作参数为 SQL_FETCH_BY_BOOKMARK;C 类型是精确或近似数字、日期时间或间隔数据类型;列的 SQL 类型是字符数据类型;列中的值不是绑定 C 类型的有效文本。The Operation argument was SQL_FETCH_BY_BOOKMARK; the C type was an exact or approximate numeric, a datetime, or an interval data type; the SQL type of the column was a character data type; and the value in the column was not a valid literal of the bound C type.

参数操作是 SQL_ADD 或 SQL_UPDATE_BY_BOOKMARK;SQL 类型是精确或近似的数字、日期时间或时间间隔数据类型;C 类型为 SQL_C_CHAR;列中的值不是绑定的 SQL 类型的有效文本。The argument Operation was SQL_ADD or SQL_UPDATE_BY_BOOKMARK; the SQL type was an exact or approximate numeric, a datetime, or an interval data type; the C type was SQL_C_CHAR; and the value in the column was not a valid literal of the bound SQL type.
2300023000 完整性约束冲突Integrity constraint violation 操作参数为 SQL_ADD、SQL_DELETE_BY_BOOKMARK 或 SQL_UPDATE_BY_BOOKMARK, 违反了完整性约束。The Operation argument was SQL_ADD, SQL_DELETE_BY_BOOKMARK, or SQL_UPDATE_BY_BOOKMARK, and an integrity constraint was violated.

操作参数为 SQL_ADD, 但未绑定的列定义为 not NULL 且没有默认值。The Operation argument was SQL_ADD, and a column that was not bound is defined as NOT NULL and has no default.

操作参数为 SQL_ADD, 在绑定的StrLen_or_IndPtr缓冲区中指定的长度为 SQL_COLUMN_IGNORE, 列没有默认值。The Operation argument was SQL_ADD, the length specified in the bound StrLen_or_IndPtr buffer was SQL_COLUMN_IGNORE, and the column did not have a default value.
2400024000 无效的游标状态Invalid cursor state StatementHandle处于已执行状态, 但没有与StatementHandle关联的结果集。The StatementHandle was in an executed state, but no result set was associated with the StatementHandle.
4000140001 序列化失败Serialization failure 由于另一个事务发生资源死锁, 事务已回滚。The transaction was rolled back because of a resource deadlock with another transaction.
4000340003 语句完成情况未知Statement completion unknown 在执行此函数的过程中关联的连接失败, 无法确定事务的状态。The associated connection failed during the execution of this function, and the state of the transaction cannot be determined.
4200042000 语法错误或访问冲突Syntax error or access violation 驱动程序无法根据需要锁定行以执行操作参数中请求的操作。The driver was unable to lock the row as needed to perform the operation requested in the Operation argument.
4400044000 WITH CHECK OPTION 冲突WITH CHECK OPTION violation 操作参数为 SQL_ADD 或 SQL_UPDATE_BY_BOOKMARK, 并对通过指定WITH CHECK OPTION创建的已查看表 (或从已查看表派生的表) 执行了插入或更新操作, 在这种情况下, 一个或多个行受 insert 或 update 影响的不会再出现在查看的表中。The Operation argument was SQL_ADD or SQL_UPDATE_BY_BOOKMARK, and the insert or update was performed on a viewed table (or a table derived from the viewed table) that was created by specifying WITH CHECK OPTION, in such a way that one or more rows affected by the insert or update will no longer be present in the viewed table.
HY000HY000 一般错误General error 发生了一个错误, 该错误没有特定的 SQLSTATE, 没有为其定义实现特定的 SQLSTATE。An error occurred for which there was no specific SQLSTATE and for which no implementation-specific SQLSTATE was defined. MessageText 缓冲区中的 SQLGetDiagRec返回的错误消息描述了错误及其原因。 *The error message returned by SQLGetDiagRec in the *MessageText buffer describes the error and its cause.
HY001HY001 内存分配错误Memory allocation error 驱动程序无法分配支持执行或完成此函数所需的内存。The driver was unable to allocate memory required to support execution or completion of the function.
HY008HY008 操作已取消Operation canceled 已为StatementHandle启用异步处理。Asynchronous processing was enabled for the StatementHandle. 函数被调用, 在完成执行之前, 在StatementHandle上调用了SQLCancelSQLCancelHandleThe function was called, and before it completed execution, SQLCancel or SQLCancelHandle was called on the StatementHandle. 然后, 在StatementHandle上再次调用该函数。Then the function was called again on the StatementHandle.

函数被调用, 在完成执行之前, 从多线程应用程序中的另一个线程调用StatementHandle上的SQLCancelSQLCancelHandleThe function was called, and before it completed execution, SQLCancel or SQLCancelHandle was called on the StatementHandle from a different thread in a multithread application.
HY010HY010 函数序列错误Function sequence error (DM) 为与StatementHandle关联的连接句柄调用了异步执行的函数。(DM) An asynchronously executing function was called for the connection handle that is associated with the StatementHandle. 调用SQLBulkOperations函数时, 此异步函数仍在执行。This asynchronous function was still executing when the SQLBulkOperations function was called.

(DM) 为StatementHandle调用了SQLExecuteSQLExecDirectSQLMoreResults , 并返回了 SQL_PARAM_DATA_AVAILABLE。(DM) SQLExecute, SQLExecDirect, or SQLMoreResults was called for the StatementHandle and returned SQL_PARAM_DATA_AVAILABLE. 在检索所有流式处理参数的数据之前调用此函数。This function was called before data was retrieved for all streamed parameters.

(DM) 指定的StatementHandle未处于执行状态。(DM) The specified StatementHandle was not in an executed state. 调用函数时, 无需先调用SQLExecDirectSQLExecute或 catalog 函数。The function was called without first calling SQLExecDirect, SQLExecute, or a catalog function.

(DM) 为StatementHandle调用了异步执行的函数 (而不是此函数), 并且在调用此函数时仍在执行。(DM) An asynchronously executing function (not this one) was called for the StatementHandle and was still executing when this function was called.

(DM) 为StatementHandle调用了SQLExecuteSQLExecDirectSQLSetPos , 并返回了 SQL_NEED_DATA。(DM) SQLExecute, SQLExecDirect, or SQLSetPos was called for the StatementHandle and returned SQL_NEED_DATA. 在为所有执行时数据参数或列发送数据之前, 将调用此函数。This function was called before data was sent for all data-at-execution parameters or columns.

(DM) 驱动程序是一个 ODBC 2。在调用SQLFetchScrollSQLFetch之前, 对StatementHandle调用了x驱动程序和SQLBulkOperations(DM) The driver was an ODBC 2.x driver, and SQLBulkOperations was called for a StatementHandle before SQLFetchScroll or SQLFetch was called.

(DM) 在对StatementHandle调用SQLExtendedFetch后调用SQLBulkOperations(DM) SQLBulkOperations was called after SQLExtendedFetch was called on the StatementHandle.
HY011HY011 现在无法设置属性Attribute cannot be set now (DM) 驱动程序是一个 ODBC 2。x驱动程序, 并且在调用SQLFetchSQLFetchScrollSQLBulkOperations之间设置了 SQL_ATTR_ROW_STATUS_PTR 语句特性。(DM) The driver was an ODBC 2.x driver, and the SQL_ATTR_ROW_STATUS_PTR statement attribute was set between calls to SQLFetch or SQLFetchScroll and SQLBulkOperations.
HY013HY013 内存管理错误Memory management error 未能处理函数调用, 原因可能是由于内存不足而无法访问基础内存对象。The function call could not be processed because the underlying memory objects could not be accessed, possibly because of low memory conditions.
HY090HY090 字符串或缓冲区长度无效Invalid string or buffer length 操作参数为 SQL_ADD 或 SQL_UPDATE_BY_BOOKMARK;数据值不是 null 指针;C 数据类型为 SQL_C_BINARY 或 SQL_C_CHAR;列长度值小于 0, 但不等于 SQL_DATA_AT_EXEC、SQL_COLUMN_IGNORE、SQL_NTS 或 SQL_NULL_DATA, 或者小于或等于 SQL_LEN_DATA_AT_EXEC_OFFSET。The Operation argument was SQL_ADD or SQL_UPDATE_BY_BOOKMARK; a data value was not a null pointer; the C data type was SQL_C_BINARY or SQL_C_CHAR; and the column length value was less than 0, but not equal to SQL_DATA_AT_EXEC, SQL_COLUMN_IGNORE, SQL_NTS, or SQL_NULL_DATA, or less than or equal to SQL_LEN_DATA_AT_EXEC_OFFSET.

长度/指示器缓冲区中的值为 SQL_DATA_AT_EXEC;SQL 类型为 SQL_LONGVARCHAR、SQL_LONGVARBINARY 或 long 特定于数据源的数据类型;SQLGetInfo中的 SQL_NEED_LONG_DATA_LEN 信息类型为 "Y"。The value in a length/indicator buffer was SQL_DATA_AT_EXEC; the SQL type was either SQL_LONGVARCHAR, SQL_LONGVARBINARY, or a long data source-specific data type; and the SQL_NEED_LONG_DATA_LEN information type in SQLGetInfo was "Y".

操作参数为 SQL_ADD, SQL_ATTR_USE_BOOKMARK 语句特性设置为 SQL_UB_VARIABLE, 列0绑定到长度不等于此结果集的书签最大长度的缓冲区。The Operation argument was SQL_ADD, the SQL_ATTR_USE_BOOKMARK statement attribute was set to SQL_UB_VARIABLE, and column 0 was bound to a buffer whose length was not equal to the maximum length for the bookmark for this result set. (此长度在 IRD 的 SQL_DESC_OCTET_LENGTH 字段中提供, 可以通过调用SQLDescribeColSQLColAttributeSQLGetDescField获取。)(This length is available in the SQL_DESC_OCTET_LENGTH field of the IRD and can be obtained by calling SQLDescribeCol, SQLColAttribute, or SQLGetDescField.)
HY092HY092 无效的属性标识符Invalid attribute identifier (DM) 为操作参数指定的值无效。(DM) The value specified for the Operation argument was invalid.

操作参数为 SQL_ADD、SQL_UPDATE_BY_BOOKMARK 或 SQL_DELETE_BY_BOOKMARK, SQL_ATTR_CONCURRENCY 语句特性设置为 SQL_CONCUR_READ_ONLY。The Operation argument was SQL_ADD, SQL_UPDATE_BY_BOOKMARK, or SQL_DELETE_BY_BOOKMARK, and the SQL_ATTR_CONCURRENCY statement attribute was set to SQL_CONCUR_READ_ONLY.

操作参数为 SQL_DELETE_BY_BOOKMARK、SQL_FETCH_BY_BOOKMARK 或 SQL_UPDATE_BY_BOOKMARK, 书签列未绑定或 SQL_ATTR_USE_BOOKMARKS 语句特性设置为 SQL_UB_OFF。The Operation argument was SQL_DELETE_BY_BOOKMARK, SQL_FETCH_BY_BOOKMARK, or SQL_UPDATE_BY_BOOKMARK, and the bookmark column was not bound or the SQL_ATTR_USE_BOOKMARKS statement attribute was set to SQL_UB_OFF.
HY117HY117 由于未知的事务状态, 连接被挂起。Connection is suspended due to unknown transaction state. 仅允许断开连接和只读函数。Only disconnect and read-only functions are allowed. (DM) 有关挂起状态的详细信息, 请参阅SQLEndTran 函数(DM) For more information about suspended state, see SQLEndTran Function.
HYC00HYC00 未实现的可选功能Optional feature not implemented 驱动程序或数据源不支持操作参数中请求的操作。The driver or data source does not support the operation requested in the Operation argument.
HYT00HYT00 超时时间已到Timeout expired 在数据源返回结果集之前, 查询超时期限已过期。The query timeout period expired before the data source returned the result set. 超时期限通过SQLSetStmtAttr属性参数设置为 SQL_ATTR_QUERY_TIMEOUT。The timeout period is set through SQLSetStmtAttr with an Attribute argument of SQL_ATTR_QUERY_TIMEOUT.
HYT01HYT01 连接超时已过期Connection timeout expired 连接超时期限在数据源响应请求之前过期。The connection timeout period expired before the data source responded to the request. 连接超时期限通过SQLSetConnectAttr、SQL_ATTR_CONNECTION_TIMEOUT 设置。The connection timeout period is set through SQLSetConnectAttr, SQL_ATTR_CONNECTION_TIMEOUT.
IM001IM001 驱动程序不支持此功能Driver does not support this function (DM) 与StatementHandle关联的驱动程序不支持该函数。(DM) The driver associated with the StatementHandle does not support the function.
IM017IM017 在异步通知模式下禁用轮询Polling is disabled in asynchronous notification mode 无论何时使用通知模型, 都将禁用轮询。Whenever the notification model is used, polling is disabled.
IM018IM018 尚未调用SQLCompleteAsync来完成此句柄上先前的异步操作。SQLCompleteAsync has not been called to complete the previous asynchronous operation on this handle. 如果句柄上的上一个函数调用返回 SQL_STILL_EXECUTING, 并且如果启用了通知模式, 则必须在句柄上调用SQLCompleteAsync , 才能执行后处理并完成操作。If the previous function call on the handle returns SQL_STILL_EXECUTING and if notification mode is enabled, SQLCompleteAsync must be called on the handle to do post-processing and complete the operation.

注释Comments

注意

有关可在其中调用的语句状态SQLBulkOperations以及与 ODBC 2 兼容的必须执行的操作的信息。x应用程序, 请参阅附录 G 中的块游标、可滚动游标和后向兼容性部分:向后兼容的驱动程序准则。For information about what statement states SQLBulkOperations can be called in and what it must do for compatibility with ODBC 2.x applications, see the Block Cursors, Scrollable Cursors, and Backward Compatibility section in Appendix G: Driver Guidelines for Backward Compatibility.

应用程序使用SQLBulkOperations对与当前查询对应的基表或视图执行以下操作:An application uses SQLBulkOperations to perform the following operations on the base table or view that corresponds to the current query:

  • 添加新行。Add new rows.

  • 更新一组行, 其中每行由书签标识。Update a set of rows where each row is identified by a bookmark.

  • 删除一组行, 其中每行由书签标识。Delete a set of rows where each row is identified by a bookmark.

  • 提取一组行, 其中每行由书签标识。Fetch a set of rows where each row is identified by a bookmark.

调用SQLBulkOperations后, 不定义块光标位置。After a call to SQLBulkOperations, the block cursor position is undefined. 应用程序必须调用SQLFetchScroll来设置光标位置。The application has to call SQLFetchScroll to set the cursor position. 应用程序应仅使用 SQL_FETCH_FIRST、SQL_FETCH_LAST、SQL_FETCH_ABSOLUTE 或 SQL_FETCH_BOOKMARK 的FetchOrientation参数调用SQLFetchScrollAn application should call SQLFetchScroll only with a FetchOrientation argument of SQL_FETCH_FIRST, SQL_FETCH_LAST, SQL_FETCH_ABSOLUTE, or SQL_FETCH_BOOKMARK. 如果应用程序使用 SQL_FETCH_PRIOR、SQL_FETCH_NEXT 或 SQL_FETCH_RELATIVE 的FetchOrientation参数调用SQLFetchSQLFetchScroll , 则游标位置未定义。The cursor position is undefined if the application calls SQLFetch or SQLFetchScroll with a FetchOrientation argument of SQL_FETCH_PRIOR, SQL_FETCH_NEXT, or SQL_FETCH_RELATIVE.

通过将对SQLBindCol的调用中指定的列长度/指示器缓冲区设置为 SQL_COLUMN_IGNORE, 可以在通过调用SQLBulkOperations执行的批量操作中忽略列。A column can be ignored in bulk operations performed by a call to SQLBulkOperations by setting the column length/indicator buffer specified in the call to SQLBindCol, to SQL_COLUMN_IGNORE.

应用程序在调用SQLBulkOperations时不需要设置 SQL_ATTR_ROW_OPERATION_PTR 语句特性, 因为在对此函数执行大容量操作时, 不能忽略行。It is not necessary for the application to set the SQL_ATTR_ROW_OPERATION_PTR statement attribute when it calls SQLBulkOperations because rows cannot be ignored when performing bulk operations with this function.

SQL_ATTR_ROWS_FETCHED_PTR 语句属性所指向的缓冲区包含受对SQLBulkOperations的调用影响的行数。The buffer pointed to by the SQL_ATTR_ROWS_FETCHED_PTR statement attribute contains the number of rows affected by a call to SQLBulkOperations.

Operation参数为 SQL_ADD 或 SQL_UPDATE_BY_BOOKMARK, 并且与游标关联的查询规范的选择列表包含对同一列的多个引用时, 无论是生成错误还是驱动程序将忽略重复的引用并执行所请求的操作。When the Operation argument is SQL_ADD or SQL_UPDATE_BY_BOOKMARK and the select-list of the query specification associated with the cursor contains more than one reference to the same column, it is driver-defined whether an error is generated or the driver ignores the duplicated references and performs the requested operations.

有关如何使用SQLBulkOperations的详细信息, 请参阅使用 SQLBulkOperations 更新数据For more information about how to use SQLBulkOperations, see Updating Data with SQLBulkOperations.

执行大容量插入Performing Bulk Inserts

若要使用SQLBulkOperations插入数据, 应用程序需要执行以下一系列步骤:To insert data with SQLBulkOperations, an application performs the following sequence of steps:

  1. 执行返回结果集的查询。Executes a query that returns a result set.

  2. 将 SQL_ATTR_ROW_ARRAY_SIZE 语句特性设置为要插入的行数。Sets the SQL_ATTR_ROW_ARRAY_SIZE statement attribute to the number of rows that it wants to insert.

  3. 调用SQLBindCol绑定要插入的数据。Calls SQLBindCol to bind the data that it wants to insert. 数据绑定到大小等于 SQL_ATTR_ROW_ARRAY_SIZE 值的数组。The data is bound to an array with a size equal to the value of SQL_ATTR_ROW_ARRAY_SIZE.

    备注

    SQL_ATTR_ROW_STATUS_PTR 语句特性指向的数组大小应等于 SQL_ATTR_ROW_ARRAY_SIZE, 否则 SQL_ATTR_ROW_STATUS_PTR 应为 null 指针。The size of the array pointed to by the SQL_ATTR_ROW_STATUS_PTR statement attribute should either be equal to SQL_ATTR_ROW_ARRAY_SIZE or SQL_ATTR_ROW_STATUS_PTR should be a null pointer.

  4. 调用SQLBulkOperations(StatementHandle, SQL_ADD) 以执行插入。Calls SQLBulkOperations(StatementHandle, SQL_ADD) to perform the insertion.

  5. 如果应用程序已设置 SQL_ATTR_ROW_STATUS_PTR 语句特性, 则它可以检查此数组以查看操作的结果。If the application has set the SQL_ATTR_ROW_STATUS_PTR statement attribute, it can inspect this array to see the result of the operation.

如果应用程序在调用带有 SQL_ADD操作参数的SQLBulkOperations之前绑定列 0, 则驱动程序将使用新插入行的书签值更新绑定列0缓冲区。If an application binds column 0 before it calls SQLBulkOperations with an Operation argument of SQL_ADD, the driver will update the bound column 0 buffers with the bookmark values for the newly inserted row. 为此, 应用程序必须先将 SQL_ATTR_USE_BOOKMARKS 语句属性设置为 SQL_UB_VARIABLE, 然后再执行该语句。For this to occur, the application must have set the SQL_ATTR_USE_BOOKMARKS statement attribute to SQL_UB_VARIABLE before executing the statement. (这不适用于 ODBC 2。x驱动程序。)(This does not work with an ODBC 2.x driver.)

使用对 SQLParamData 和 SQLPutData 的调用, 可以通过 SQLBulkOperations 将长数据添加到部分。Long data can be added in parts by SQLBulkOperations, by using calls to SQLParamData and SQLPutData. 有关详细信息, 请参阅本函数引用后面的 "为大容量插入和更新提供长数据"。For more information, see "Providing Long Data for Bulk Inserts and Updates" later in this function reference.

应用程序不需要在调用 SQLBulkOperations 之前调用SQLFetchSQLFETCHSCROLL (对 ODBC 2 的访问除外)。x驱动程序;请参阅向后兼容性和标准符合性)。It is not necessary for the application to call SQLFetch or SQLFetchScroll before it calls SQLBulkOperations (except when going against an ODBC 2.x driver; see Backward Compatibility and Standards Compliance).

如果具有 SQL_ADD 的操作参数的SQLBulkOperations调用了包含重复列的游标, 则此行为是由驱动程序定义的。The behavior is driver-defined if SQLBulkOperations, with an Operation argument of SQL_ADD, is called on a cursor that contains duplicate columns. 驱动程序可以返回驱动程序定义的 SQLSTATE, 将数据添加到结果集中显示的第一列, 或者执行其他驱动程序定义的行为。The driver can return a driver-defined SQLSTATE, add the data to the first column that appears in the result set, or perform other driver-defined behavior.

使用书签执行批量更新Performing Bulk Updates by Using Bookmarks

若要通过SQLBulkOperations使用书签来执行批量更新, 应用程序需要按顺序执行以下步骤:To perform bulk updates by using bookmarks with SQLBulkOperations, an application performs the following steps in sequence:

  1. 将 SQL_ATTR_USE_BOOKMARKS 语句特性设置为 SQL_UB_VARIABLE。Sets the SQL_ATTR_USE_BOOKMARKS statement attribute to SQL_UB_VARIABLE.

  2. 执行返回结果集的查询。Executes a query that returns a result set.

  3. 将 SQL_ATTR_ROW_ARRAY_SIZE 语句属性设置为它要更新的行数。Sets the SQL_ATTR_ROW_ARRAY_SIZE statement attribute to the number of rows that it wants to update.

  4. 调用SQLBindCol绑定要更新的数据。Calls SQLBindCol to bind the data that it wants to update. 数据绑定到大小等于 SQL_ATTR_ROW_ARRAY_SIZE 值的数组。The data is bound to an array with a size equal to the value of SQL_ATTR_ROW_ARRAY_SIZE. 它还会调用SQLBindCol来绑定列 0 (书签列)。It also calls SQLBindCol to bind column 0 (the bookmark column).

  5. 将要更新的行的书签复制到绑定到列0的数组中。Copies the bookmarks for rows that it is interested in updating into the array bound to column 0.

  6. 更新绑定缓冲区中的数据。Updates the data in the bound buffers.

    备注

    SQL_ATTR_ROW_STATUS_PTR 语句特性指向的数组大小应等于 SQL_ATTR_ROW_ARRAY_SIZE, 否则 SQL_ATTR_ROW_STATUS_PTR 应为 null 指针。The size of the array pointed to by the SQL_ATTR_ROW_STATUS_PTR statement attribute should be equal to SQL_ATTR_ROW_ARRAY_SIZE or SQL_ATTR_ROW_STATUS_PTR should be a null pointer.

  7. 调用SQLBulkOperations(StatementHandle, SQL_UPDATE_BY_BOOKMARK)。Calls SQLBulkOperations(StatementHandle, SQL_UPDATE_BY_BOOKMARK).

    备注

    如果应用程序已设置 SQL_ATTR_ROW_STATUS_PTR 语句特性, 则它可以检查此数组以查看操作的结果。If the application has set the SQL_ATTR_ROW_STATUS_PTR statement attribute, it can inspect this array to see the result of the operation.

  8. (可选) 调用SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK) 将数据提取到绑定应用程序缓冲区, 以验证是否已发生更新。Optionally calls SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK) to fetch data into the bound application buffers to verify that the update has occurred.

  9. 如果数据已更新, 驱动程序会将相应行的行状态数组中的值更改为 SQL_ROW_UPDATED。If data has been updated, the driver changes the value in the row status array for the appropriate rows to SQL_ROW_UPDATED.

通过使用对SQLParamDataSQLPutData的调用, SQLBulkOperations执行的大容量更新可以包含长数据。Bulk updates performed by SQLBulkOperations can include long data by using calls to SQLParamData and SQLPutData. 有关详细信息, 请参阅本函数引用后面的 "为大容量插入和更新提供长数据"。For more information, see "Providing Long Data for Bulk Inserts and Updates" later in this function reference.

如果书签在游标之间保持不变, 则该应用程序在更新书签之前无需调用SQLFetchSQLFetchScrollIf bookmarks persist across cursors, the application does not need to call SQLFetch or SQLFetchScroll before updating by bookmarks. 它可以使用从上一个游标存储的书签。It can use bookmarks that it has stored from a previous cursor. 如果书签不是跨游标保存的, 则应用程序必须调用SQLFetchSQLFetchScroll来检索书签。If bookmarks do not persist across cursors, the application has to call SQLFetch or SQLFetchScroll to retrieve the bookmarks.

如果具有 SQL_UPDATE_BY_BOOKMARK 的操作参数的SQLBulkOperations调用了包含重复列的游标, 则此行为是由驱动程序定义的。The behavior is driver-defined if SQLBulkOperations, with an Operation argument of SQL_UPDATE_BY_BOOKMARK, is called on a cursor that contains duplicate columns. 驱动程序可以返回驱动程序定义的 SQLSTATE, 更新出现在结果集中的第一列, 或者执行其他驱动程序定义的行为。The driver can return a driver-defined SQLSTATE, update the first column that appears in the result set, or perform other driver-defined behavior.

使用书签执行批量提取Performing Bulk Fetches Using Bookmarks

若要在SQLBulkOperations中使用书签执行批量提取, 应用程序需要按顺序执行以下步骤:To perform bulk fetches using bookmarks with SQLBulkOperations, an application performs the following steps in sequence:

  1. 将 SQL_ATTR_USE_BOOKMARKS 语句特性设置为 SQL_UB_VARIABLE。Sets the SQL_ATTR_USE_BOOKMARKS statement attribute to SQL_UB_VARIABLE.

  2. 执行返回结果集的查询。Executes a query that returns a result set.

  3. 将 SQL_ATTR_ROW_ARRAY_SIZE 语句属性设置为它要提取的行数。Sets the SQL_ATTR_ROW_ARRAY_SIZE statement attribute to the number of rows that it wants to fetch.

  4. 调用SQLBindCol绑定要提取的数据。Calls SQLBindCol to bind the data that it wants to fetch. 数据绑定到大小等于 SQL_ATTR_ROW_ARRAY_SIZE 值的数组。The data is bound to an array with a size equal to the value of SQL_ATTR_ROW_ARRAY_SIZE. 它还会调用SQLBindCol来绑定列 0 (书签列)。It also calls SQLBindCol to bind column 0 (the bookmark column).

  5. 将感兴趣的行的书签复制到绑定到列0的数组中。Copies the bookmarks for rows that it is interested in fetching into the array bound to column 0. (这假定应用程序已单独获取书签。)(This assumes that the application has already obtained the bookmarks separately.)

    备注

    SQL_ATTR_ROW_STATUS_PTR 语句特性指向的数组大小应等于 SQL_ATTR_ROW_ARRAY_SIZE, 否则 SQL_ATTR_ROW_STATUS_PTR 应为 null 指针。The size of the array pointed to by the SQL_ATTR_ROW_STATUS_PTR statement attribute should be equal to SQL_ATTR_ROW_ARRAY_SIZE or SQL_ATTR_ROW_STATUS_PTR should be a null pointer.

  6. 调用SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK)。Calls SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK).

  7. 如果应用程序已设置 SQL_ATTR_ROW_STATUS_PTR 语句特性, 则它可以检查此数组以查看操作的结果。If the application has set the SQL_ATTR_ROW_STATUS_PTR statement attribute, it can inspect this array to see the result of the operation.

如果书签在游标之间保持不变, 则在提取书签之前, 应用程序无需调用SQLFetchSQLFetchScrollIf bookmarks persist across cursors, the application does not need to call SQLFetch or SQLFetchScroll before fetching by bookmarks. 它可以使用从上一个游标存储的书签。It can use bookmarks that it has stored from a previous cursor. 如果书签不是跨游标保存的, 则应用程序必须调用SQLFetchSQLFetchScroll一次来检索书签。If bookmarks do not persist across cursors, the application has to call SQLFetch or SQLFetchScroll one time to retrieve the bookmarks.

使用书签执行批量删除Performing Bulk Deletes Using Bookmarks

若要在SQLBulkOperations中使用书签执行批量删除, 应用程序将按顺序执行以下步骤:To perform bulk deletes using bookmarks with SQLBulkOperations, an application performs the following steps in sequence:

  1. 将 SQL_ATTR_USE_BOOKMARKS 语句特性设置为 SQL_UB_VARIABLE。Sets the SQL_ATTR_USE_BOOKMARKS statement attribute to SQL_UB_VARIABLE.

  2. 执行返回结果集的查询。Executes a query that returns a result set.

  3. 将 SQL_ATTR_ROW_ARRAY_SIZE 语句特性设置为要删除的行数。Sets the SQL_ATTR_ROW_ARRAY_SIZE statement attribute to the number of rows that it wants to delete.

  4. 调用SQLBindCol绑定列 0 (书签列)。Calls SQLBindCol to bind column 0 (the bookmark column).

  5. 将要删除的行的书签复制到绑定到列0的数组中。Copies the bookmarks for rows that it is interested in deleting into the array bound to column 0.

    备注

    SQL_ATTR_ROW_STATUS_PTR 语句特性指向的数组大小应等于 SQL_ATTR_ROW_ARRAY_SIZE, 否则 SQL_ATTR_ROW_STATUS_PTR 应为 null 指针。The size of the array pointed to by the SQL_ATTR_ROW_STATUS_PTR statement attribute should be equal to SQL_ATTR_ROW_ARRAY_SIZE or SQL_ATTR_ROW_STATUS_PTR should be a null pointer.

  6. 调用SQLBulkOperations(StatementHandle, SQL_DELETE_BY_BOOKMARK)。Calls SQLBulkOperations(StatementHandle, SQL_DELETE_BY_BOOKMARK).

  7. 如果应用程序已设置 SQL_ATTR_ROW_STATUS_PTR 语句特性, 则它可以检查此数组以查看操作的结果。If the application has set the SQL_ATTR_ROW_STATUS_PTR statement attribute, it can inspect this array to see the result of the operation.

如果书签在游标之间保持不变, 则在删除书签之前, 应用程序无需调用SQLFetchSQLFetchScrollIf bookmarks persist across cursors, the application does not have to call SQLFetch or SQLFetchScroll before deleting by bookmarks. 它可以使用从上一个游标存储的书签。It can use bookmarks that it has stored from a previous cursor. 如果书签不是跨游标保存的, 则应用程序必须调用SQLFetchSQLFetchScroll一次来检索书签。If bookmarks do not persist across cursors, the application has to call SQLFetch or SQLFetchScroll one time to retrieve the bookmarks.

为大容量插入和更新提供长数据Providing Long Data for Bulk Inserts and Updates

可以为大容量插入和通过调用SQLBulkOperations执行的更新提供长数据。Long data can be provided for bulk inserts and updates performed by calls to SQLBulkOperations. 若要插入或更新长数据, 应用程序将执行以下步骤, 以及本主题前面的 "执行批量插入" 和 "使用书签执行批量更新" 部分中描述的步骤。To insert or update long data, an application performs the following steps in addition to the steps described in the "Performing Bulk Inserts" and "Performing Bulk Updates Using Bookmarks" sections earlier in this topic.

  1. 当它通过使用SQLBindCol绑定数据时, 应用程序会将 * 应用程序定义的值 (如列号) 放置在 TargetValuePtr 缓冲区中, 以执行执行时数据列。When it binds the data by using SQLBindCol, the application places an application-defined value, such as the column number, in the *TargetValuePtr buffer for data-at-execution columns. 稍后可使用该值来识别列。The value can be used later to identify the column.

    应用程序将 SQL_LEN_DATA_AT_EXEC (length) 宏的结果放入 *StrLen_or_IndPtr缓冲区。The application places the result of the SQL_LEN_DATA_AT_EXEC(length) macro in the *StrLen_or_IndPtr buffer. 如果列的 SQL 数据类型为 SQL_LONGVARBINARY、SQL_LONGVARCHAR 或 long 特定于数据源的数据类型, 并且驱动程序为SQLGetInfo中的 SQL_NEED_LONG_DATA_LEN 信息类型返回 "Y", 则length是数据的字节数。为参数发送;否则, 它必须为非负值并且将被忽略。If the SQL data type of the column is SQL_LONGVARBINARY, SQL_LONGVARCHAR, or a long data source-specific data type and the driver returns "Y" for the SQL_NEED_LONG_DATA_LEN information type in SQLGetInfo, length is the number of bytes of data to be sent for the parameter; otherwise, it must be a nonnegative value and is ignored.

  2. 当调用SQLBulkOperations时, 如果存在执行时数据列, 则该函数将返回 SQL_NEED_DATA 并继续执行后面的步骤3。When SQLBulkOperations is called, if there are data-at-execution columns, the function returns SQL_NEED_DATA and proceeds to step 3, which follows. (如果没有执行时数据列, 则该过程已完成。)(If there are no data-at-execution columns, the process is complete.)

  3. 应用程序调用SQLParamData来检索要处理的第一次执行时数据列的 *TargetValuePtr缓冲区地址。The application calls SQLParamData to retrieve the address of the *TargetValuePtr buffer for the first data-at-execution column to be processed. SQLParamData返回 SQL_NEED_DATA。SQLParamData returns SQL_NEED_DATA. 应用程序从 *TargetValuePtr缓冲区检索应用程序定义的值。The application retrieves the application-defined value from the *TargetValuePtr buffer.

    备注

    尽管执行时数据参数与执行时数据列类似, 但SQLParamData返回的值对于每个都是不同的。Although data-at-execution parameters resemble data-at-execution columns, the value returned by SQLParamData is different for each.

    执行时数据列是行集中的列, 当使用SQLBulkOperations更新或插入行时, 将使用SQLPutData发送数据。Data-at-execution columns are columns in a rowset for which data will be sent with SQLPutData when a row is updated or inserted with SQLBulkOperations. 它们与SQLBindCol绑定在一起。They are bound with SQLBindCol. SQLParamData返回的值是正在处理的 *TargetValuePtr缓冲区中的行的地址。The value returned by SQLParamData is the address of the row in the *TargetValuePtr buffer that is being processed.

  4. 应用程序会调用SQLPutData一次或多次以发送列的数据。The application calls SQLPutData one or more times to send data for the column. 如果在SQLPutData中指定的 *TargetValuePtr缓冲区中无法返回所有数据值, 则需要多个调用; 只有在发送字符 C 数据时才允许对同一列的SQLPutData进行多次调用到具有字符、二进制或数据源特定数据类型的列, 或将二进制 C 数据发送到具有字符、二进制或数据源特定数据类型的列时。More than one call is needed if all the data value cannot be returned in the *TargetValuePtr buffer specified in SQLPutData; multiple calls to SQLPutData for the same column are allowed only when sending character C data to a column with a character, binary, or data source-specific data type or when sending binary C data to a column with a character, binary, or data source-specific data type.

  5. 应用程序再次调用SQLParamData , 以指示已发送列的所有数据。The application calls SQLParamData again to signal that all data has been sent for the column.

    • 如果有多个执行时数据列, SQLParamData将返回 SQL_NEED_DATA, 并为要处理的下一个执行时数据列返回TargetValuePtr缓冲区的地址。If there are more data-at-execution columns, SQLParamData returns SQL_NEED_DATA and the address of the TargetValuePtr buffer for the next data-at-execution column to be processed. 应用程序重复步骤4和5。The application repeats steps 4 and 5.

    • 如果没有其他执行时数据列, 则该过程已完成。If there are no more data-at-execution columns, the process is complete. 如果语句已成功执行, 则SQLParamData将返回 SQL_SUCCESS 或 SQL_SUCCESS_WITH_INFO;如果执行失败, 则返回 SQL_ERROR。If the statement was executed successfully, SQLParamData returns SQL_SUCCESS or SQL_SUCCESS_WITH_INFO; if the execution failed, it returns SQL_ERROR. 此时, SQLParamData可以返回SQLBulkOperations可以返回的任何 SQLSTATE。At this point, SQLParamData can return any SQLSTATE that can be returned by SQLBulkOperations.

如果在SQLBulkOperations返回 SQL_NEED_DATA 之后, 在SQLParamDataSQLPutData中发生了该操作, 或者在为所有执行时数据列发送数据之前发生错误, 则应用程序只能调用SQLCancelSQLGetDiagFieldSQLGetDiagRecSQLGetFunctionsSQLParamDataSQLPutData用于语句或与该语句关联的连接。If the operation is canceled or an error occurs in SQLParamData or SQLPutData after SQLBulkOperations returns SQL_NEED_DATA and before data is sent for all data-at-execution columns, the application can call only SQLCancel, SQLGetDiagField, SQLGetDiagRec, SQLGetFunctions, SQLParamData, or SQLPutData for the statement or the connection associated with the statement. 如果它调用语句的任何其他函数或与该语句关联的连接, 则该函数将返回 SQL_ERROR 和 SQLSTATE HY010 (函数序列错误)。If it calls any other function for the statement or the connection associated with the statement, the function returns SQL_ERROR and SQLSTATE HY010 (Function sequence error).

如果应用程序调用SQLCancel , 但驱动程序仍需要数据执行时数据列, 则驱动程序将取消该操作。If the application calls SQLCancel while the driver still needs data for data-at-execution columns, the driver cancels the operation. 然后, 应用程序可以再次调用SQLBulkOperations ;取消不会影响游标状态或当前游标位置。The application can then call SQLBulkOperations again; canceling does not affect the cursor state or the current cursor position.

行状态数组Row Status Array

行状态数组包含行集中的每行数据在调用SQLBulkOperations之后的状态值。The row status array contains status values for each row of data in the rowset after a call to SQLBulkOperations. 在调用SQLFetchSQLFetchScrollSQLSetPosSQLBulkOperations之后, 驱动程序将设置此数组中的状态值。The driver sets the status values in this array after a call to SQLFetch, SQLFetchScroll, SQLSetPos, or SQLBulkOperations. 如果在SQLBulkOperations之前未调用SQLFetchSQLFetchScroll , 则此数组最初由对SQLBulkOperations的调用填充。This array is initially populated by a call to SQLBulkOperations if SQLFetch or SQLFetchScroll has not been called before SQLBulkOperations. 此数组由 SQL_ATTR_ROW_STATUS_PTR 语句特性指向。This array is pointed to by the SQL_ATTR_ROW_STATUS_PTR statement attribute. 行状态数组中的元素数必须等于行集中的行数 (由 SQL_ATTR_ROW_ARRAY_SIZE 语句特性定义)。The number of elements in the row status arrays must equal the number of rows in the rowset (as defined by the SQL_ATTR_ROW_ARRAY_SIZE statement attribute). 有关此行状态数组的信息, 请参阅SQLFetchFor information about this row status array, see SQLFetch.

代码示例Code Example

下面的示例每次从 Customers 表中提取10行数据。The following example fetches 10 rows of data at a time from the Customers table. 然后, 它会提示用户执行要执行的操作。It then prompts the user for an action to take. 为了减少网络流量, 示例缓冲区在绑定数组中本地更新、删除和插入, 但偏移量超过行集数据。To reduce network traffic, the example buffer updates, deletes, and inserts locally in the bound arrays, but at offsets past the rowset data. 当用户选择向数据源发送更新、删除和插入数据时, 代码会相应地设置绑定偏移, 并调用SQLBulkOperationsWhen the user chooses to send updates, deletes, and inserts to the data source, the code sets the binding offset appropriately and calls SQLBulkOperations. 为简单起见, 用户无法缓冲超过10个更新、删除或插入操作。For simplicity, the user cannot buffer more than 10 updates, deletes, or inserts.

// SQLBulkOperations_Function.cpp  
// compile with: ODBC32.lib  
#include <windows.h>  
#include <sqlext.h>  
#include "stdio.h"  
  
#define UPDATE_ROW 100  
#define DELETE_ROW 101  
#define ADD_ROW 102  
#define SEND_TO_DATA_SOURCE 103  
#define UPDATE_OFFSET 10  
#define INSERT_OFFSET 20  
#define DELETE_OFFSET 30  
  
// Define structure for customer data (assume 10 byte maximum bookmark size).  
typedef struct tagCustStruct {  
   SQLCHAR Bookmark[10];  
   SQLINTEGER BookmarkLen;  
   SQLUINTEGER CustomerID;  
   SQLINTEGER CustIDInd;  
   SQLCHAR CompanyName[51];  
   SQLINTEGER NameLenOrInd;  
   SQLCHAR Address[51];  
   SQLINTEGER AddressLenOrInd;  
   SQLCHAR Phone[11];  
   SQLINTEGER PhoneLenOrInd;  
} CustStruct;  
  
// Allocate 40 of these structures. Elements 0-9 are for the current rowset,  
// elements 10-19 are for the buffered updates, elements 20-29 are for  
// the buffered inserts, and elements 30-39 are for the buffered deletes.  
CustStruct CustArray[40];  
SQLUSMALLINT RowStatusArray[10], Action, RowNum, NumUpdates = 0, NumInserts = 0,  
NumDeletes = 0;  
SQLLEN BindOffset = 0;  
SQLRETURN retcode;  
SQLHENV henv = NULL;  
SQLHDBC hdbc = NULL;  
SQLHSTMT hstmt = NULL;  
  
int main() {  
   retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);  
   retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);   
  
   retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);   
   retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);  
  
   retcode = SQLConnect(hdbc, (SQLCHAR*) "Northwind", SQL_NTS, (SQLCHAR*) NULL, 0, NULL, 0);  
   retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);  
  
   // Set the following statement attributes:  
   // SQL_ATTR_CURSOR_TYPE:           Keyset-driven  
   // SQL_ATTR_ROW_BIND_TYPE:         Row-wise  
   // SQL_ATTR_ROW_ARRAY_SIZE:        10  
   // SQL_ATTR_USE_BOOKMARKS:         Use variable-length bookmarks  
   // SQL_ATTR_ROW_STATUS_PTR:        Points to RowStatusArray  
   // SQL_ATTR_ROW_BIND_OFFSET_PTR:   Points to BindOffset  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_KEYSET_DRIVEN, 0);  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_TYPE, (SQLPOINTER)sizeof(CustStruct), 0);  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)10, 0);  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_USE_BOOKMARKS, (SQLPOINTER)SQL_UB_VARIABLE, 0);  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_STATUS_PTR, RowStatusArray, 0);  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_OFFSET_PTR, &BindOffset, 0);  
  
   // Bind arrays to the bookmark, CustomerID, CompanyName, Address, and Phone columns.  
   retcode = SQLBindCol(hstmt, 0, SQL_C_VARBOOKMARK, CustArray[0].Bookmark, sizeof(CustArray[0].Bookmark), &CustArray[0].BookmarkLen);  
   retcode = SQLBindCol(hstmt, 1, SQL_C_ULONG, &CustArray[0].CustomerID, 0, &CustArray[0].CustIDInd);  
   retcode = SQLBindCol(hstmt, 2, SQL_C_CHAR, CustArray[0].CompanyName, sizeof(CustArray[0].CompanyName), &CustArray[0].NameLenOrInd);  
   retcode = SQLBindCol(hstmt, 3, SQL_C_CHAR, CustArray[0].Address, sizeof(CustArray[0].Address), &CustArray[0].AddressLenOrInd);  
   retcode = SQLBindCol(hstmt, 4, SQL_C_CHAR, CustArray[0].Phone, sizeof(CustArray[0].Phone), &CustArray[0].PhoneLenOrInd);  
  
   // Execute a statement to retrieve rows from the Customers table.  
   retcode = SQLExecDirect(hstmt, (SQLCHAR*)"SELECT CustomerID, CompanyName, Address, Phone FROM Customers", SQL_NTS);  
  
   // Fetch and display the first 10 rows.  
   retcode = SQLFetchScroll(hstmt, SQL_FETCH_NEXT, 0);  
   // DisplayCustData(CustArray, 10);  
  
   // Call GetAction to get an action and a row number from the user.  
   // while (GetAction(&Action, &RowNum)) {  
   Action = SQL_FETCH_NEXT;  
   RowNum = 2;  
   switch (Action) {  
      case SQL_FETCH_NEXT:  
      case SQL_FETCH_PRIOR:  
      case SQL_FETCH_FIRST:  
      case SQL_FETCH_LAST:  
      case SQL_FETCH_ABSOLUTE:  
      case SQL_FETCH_RELATIVE:  
         // Fetch and display the requested data.  
         SQLFetchScroll(hstmt, Action, RowNum);  
         // DisplayCustData(CustArray, 10);  
         break;  
  
      case UPDATE_ROW:  
         // Check if we have reached the maximum number of buffered updates.  
         if (NumUpdates < 10) {  
            // Get the new customer data and place it in the next available element of  
            // the buffered updates section of CustArray, copy the bookmark of the row  
            // being updated to the same element, and increment the update counter.  
            // Checking to see we have not already buffered an update for this  
            // row not shown.  
            // GetNewCustData(CustArray, UPDATE_OFFSET + NumUpdates);  
            memcpy(CustArray[UPDATE_OFFSET + NumUpdates].Bookmark,  
               CustArray[RowNum - 1].Bookmark,  
               CustArray[RowNum - 1].BookmarkLen);  
            CustArray[UPDATE_OFFSET + NumUpdates].BookmarkLen =  
               CustArray[RowNum - 1].BookmarkLen;  
            NumUpdates++;  
         } else {  
            printf("Buffers full. Send buffered changes to the data source.");  
         }  
         break;  
      case DELETE_ROW:  
         // Check if we have reached the maximum number of buffered deletes.  
         if (NumDeletes < 10) {  
            // Copy the bookmark of the row being deleted to the next available element  
            // of the buffered deletes section of CustArray and increment the delete  
            // counter. Checking to see we have not already buffered an update for  
            // this row not shown.  
            memcpy(CustArray[DELETE_OFFSET + NumDeletes].Bookmark,  
               CustArray[RowNum - 1].Bookmark,  
               CustArray[RowNum - 1].BookmarkLen);  
  
            CustArray[DELETE_OFFSET + NumDeletes].BookmarkLen =  
               CustArray[RowNum - 1].BookmarkLen;  
  
            NumDeletes++;  
         } else  
            printf("Buffers full. Send buffered changes to the data source.");  
         break;  
  
      case ADD_ROW:  
         // reached maximum number of buffered inserts?  
         if (NumInserts < 10) {  
            // Get the new customer data and place it in the next available element of  
            // the buffered inserts section of CustArray and increment insert counter.  
            // GetNewCustData(CustArray, INSERT_OFFSET + NumInserts);  
            NumInserts++;  
         } else  
            printf("Buffers full. Send buffered changes to the data source.");  
         break;  
  
      case SEND_TO_DATA_SOURCE:  
         // If there are any buffered updates, inserts, or deletes, set the array size  
         // to that number, set the binding offset to use the data in the buffered  
         // update, insert, or delete part of CustArray, and call SQLBulkOperations to  
         // do the updates, inserts, or deletes. Because we will never have more than  
         // 10 updates, inserts, or deletes, we can use the same row status array.  
         if (NumUpdates) {  
            SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumUpdates, 0);  
            BindOffset = UPDATE_OFFSET * sizeof(CustStruct);  
            SQLBulkOperations(hstmt, SQL_UPDATE_BY_BOOKMARK);  
            NumUpdates = 0;  
         }  
  
         if (NumInserts) {  
            SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumInserts, 0);  
            BindOffset = INSERT_OFFSET * sizeof(CustStruct);  
            SQLBulkOperations(hstmt, SQL_ADD);  
            NumInserts = 0;  
         }  
  
         if (NumDeletes) {  
            SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumDeletes, 0);  
            BindOffset = DELETE_OFFSET * sizeof(CustStruct);  
            SQLBulkOperations(hstmt, SQL_DELETE_BY_BOOKMARK);  
            NumDeletes = 0;  
         }  
  
         // If there were any updates, inserts, or deletes, reset the binding offset  
         // and array size to their original values.  
         if (NumUpdates || NumInserts || NumDeletes) {  
            SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)10, 0);  
            BindOffset = 0;  
         }  
         break;  
   }  
   // }  
  
   // Close the cursor.  
   SQLFreeStmt(hstmt, SQL_CLOSE);  
}  
有关信息For information about 请参阅See
将缓冲区绑定到结果集中的列Binding a buffer to a column in a result set SQLBindCol 函数SQLBindCol Function
正在取消语句处理Canceling statement processing SQLCancel 函数SQLCancel Function
提取数据块或滚动结果集Fetching a block of data or scrolling through a result set SQLFetchScroll 函数SQLFetchScroll Function
获取描述符的单个字段Getting a single field of a descriptor SQLGetDescField 函数SQLGetDescField Function
获取描述符的多个字段Getting multiple fields of a descriptor SQLGetDescRec 函数SQLGetDescRec Function
设置描述符的单个字段Setting a single field of a descriptor SQLSetDescField 函数SQLSetDescField Function
设置描述符的多个字段Setting multiple fields of a descriptor SQLSetDescRec 函数SQLSetDescRec Function
定位游标, 刷新行集中的数据, 或更新或删除行集中的数据Positioning the cursor, refreshing data in the rowset, or updating or deleting data in the rowset SQLSetPos 函数SQLSetPos Function
设置语句特性Setting a statement attribute SQLSetStmtAttr 函数SQLSetStmtAttr Function

请参阅See Also

ODBC API 参考 ODBC API Reference
ODBC 头文件ODBC Header Files