Поделиться через


Функция SQLBulkOperations

Соответствия
Представлена версия: соответствие стандартам ODBC 3.0: ODBC

Сводка
SQLBulkOperations выполняет массовые вставки и операции массовой закладки, включая обновление, удаление и получение по закладке.

Синтаксис

  
SQLRETURN SQLBulkOperations(  
     SQLHSTMT       StatementHandle,  
     SQLUSMALLINT   Operation);  

Аргументы

ОператорHandle
[Входные данные] Дескриптор инструкции.

Операция
[Входные данные] Операция выполнения:

SQL_ADD SQL_UPDATE_BY_BOOKMARK SQL_DELETE_BY_BOOKMARK SQL_FETCH_BY_BOOKMARK

Дополнительные сведения см. в разделе "Комментарии".

Возвраты

SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_NEED_DATA, SQL_STILL_EXECUTING, SQL_ERROR или SQL_INVALID_HANDLE.

Диагностика

Когда SQLBulkOperations возвращает SQL_ERROR или SQL_SUCCESS_WITH_INFO, связанное значение SQLSTATE можно получить путем вызова SQLGetDiagRec с handleType SQL_HANDLE_STMT и дескриптором инструкцииHandle. В следующей таблице перечислены значения SQLSTATE, которые обычно возвращаются SQLBulkOperations и объясняются каждый из них в контексте этой функции. Нотация "(DM)" предшествует описаниям SQLSTATEs, возвращаемых диспетчером драйверов. Возвращаемый код, связанный с каждым значением SQLSTATE, SQL_ERROR, если не указано иное.

Для всех этих SQLSTATEs, которые могут возвращать SQL_SUCCESS_WITH_INFO или SQL_ERROR (кроме 01xxx SQLSTATEs), SQL_SUCCESS_WITH_INFO возвращается, если ошибка возникает в одной или нескольких строках многострочных операций и SQL_ERROR возвращается, если ошибка возникает при однострочной операции.

SQLSTATE Error Description
01000 Общее предупреждение Информационное сообщение для конкретного драйвера. (Функция возвращает SQL_SUCCESS_WITH_INFO.)
01004 Усечение строковых данных Аргумент операции был SQL_FETCH_BY_BOOKMARK, а строковые или двоичные данные, возвращаемые для столбца или столбцов с типом данных SQL_C_CHAR или SQL_C_BINARY, привели к усечению небланковых символов или ненулевых двоичных данных.
01S01 Ошибка в строке Аргумент операции был SQL_ADD, и произошла ошибка в одной или нескольких строках при выполнении операции, но по крайней мере одна строка была успешно добавлена. (Функция возвращает SQL_SUCCESS_WITH_INFO.)

(Эта ошибка возникает только в том случае, если приложение работает с ODBC 2.x driver.)
01S07 Дробное усечение Аргумент операции был SQL_FETCH_BY_BOOKMARK, тип данных буфера приложения не был SQL_C_CHAR или SQL_C_BINARY, а данные, возвращенные в буферы приложений для одного или нескольких столбцов, усечены. (Для числовых типов данных C дробная часть числа была усечена. Для времени, метки времени и типы данных C интервала, содержащие компонент времени, дробная часть времени была усечена.)

(Функция возвращает SQL_SUCCESS_WITH_INFO.)
07006 Нарушение атрибута ограниченного типа данных Аргумент операции был SQL_FETCH_BY_BOOKMARK, а значение данных столбца в результирующем наборе невозможно преобразовать в тип данных, указанный аргументом TargetType в вызове SQLBindCol.

Аргумент операции был SQL_UPDATE_BY_BOOKMARK или SQL_ADD, а значение данных в буферах приложения невозможно преобразовать в тип данных столбца в результирующем наборе.
07009 Недопустимый индекс дескриптора Операция аргумента была SQL_ADD, и столбец был привязан к числу столбцов больше числа столбцов в результирующем наборе.
21S02 Степень производной таблицы не соответствует списку столбцов Операция аргумента была SQL_UPDATE_BY_BOOKMARK; и столбцы не обновлялись, так как все столбцы были либо несвязанными, либо только для чтения, либо значение в буфере привязанной длины или индикатора SQL_COLUMN_IGNORE.
22001 Усечение строковых данных Назначение символа или двоичного значения столбцу в результирующем наборе привело к усечению небланк (для символов) или непустых (для двоичных) символов или байтов.
22003 Числовое значение вне диапазона Аргумент операции был SQL_ADD или SQL_UPDATE_BY_BOOKMARK, а назначение числового значения столбцу в результирующем наборе привело к усечению всей части (в отличие от дробной) части числа.

Операция аргумента была SQL_FETCH_BY_BOOKMARK, и возврат числовое значение для одного или нескольких привязанных столбцов привело бы к потере значительных цифр.
22007 Недопустимый формат datetime Аргумент операции был SQL_ADD или SQL_UPDATE_BY_BOOKMARK, а назначение значения даты или метки времени столбцу в результирующем наборе привело к тому, что поле года, месяца или дня не должно быть диапазоном.

Операция аргумента была SQL_FETCH_BY_BOOKMARK, и возвращая значение метки даты или времени для одного или нескольких привязанных столбцов, привело бы к тому, что поле года, месяца или дня будет не в диапазоне.
22008 Переполнение поля даты и времени Аргумент операции был SQL_ADD или SQL_UPDATE_BY_BOOKMARK, а производительность арифметики даты и времени, отправляемых в столбец в результирующем наборе, привела к полю даты и времени (год, месяц, день, минута или второе поле) результата, падающего за пределы допустимого диапазона значений поля или недопустимого в соответствии с естественными правилами григорианского календаря для дат и времени.

Аргумент операции был SQL_FETCH_BY_BOOKMARK, а производительность арифметики даты и времени, извлекаемых из результируемого набора данных, привела к полю даты и времени (год, месяц, день, час, минута или второе поле) результата, падающего за пределы допустимого диапазона значений поля или недопустимого в соответствии с естественными правилами григорианского календаря для дат и времени.
22015 Переполнение поля интервала Аргумент операции был SQL_ADD или SQL_UPDATE_BY_BOOKMARK, а назначение точного числового или интервалного типа C к типу данных SQL интервала вызвало потерю значительных цифр.

Аргумент операции был SQL_ADD или SQL_UPDATE_BY_BOOKMARK; при назначении типу SQL интервала не было представления значения типа C в типе SQL интервала.

Аргумент операции был SQL_FETCH_BY_BOOKMARK, и назначение от точного числового или интервала SQL типа SQL к типу интервала C привело к потере значительных цифр в главном поле.

Аргумент операции был SQL_FETCH_BY_BOOKMARK; при назначении типа C интервала не было представления значения типа SQL в типе C интервала.
22018 Недопустимое значение символа для спецификации приведения Аргумент операции был SQL_FETCH_BY_BOOKMARK; тип C был точным или приблизительным числом, датой или типом данных интервала; типом данных SQL столбца был символьный тип данных, а значение в столбце не было допустимым литералом привязанного типа C.

Операция аргумента была SQL_ADD или SQL_UPDATE_BY_BOOKMARK; тип SQL был точным или приблизительным числом, датой или типом данных интервала; тип C был SQL_C_CHAR; а значение в столбце не было допустимым литералом связанного типа SQL.
23 000 Нарушение ограничений целостности Аргумент операции был SQL_ADD, SQL_DELETE_BY_BOOKMARK или SQL_UPDATE_BY_BOOKMARK, а ограничение целостности было нарушено.

Аргумент операции был SQL_ADD, а столбец, который не был привязан, определен как NOT NULL и не имеет значения по умолчанию.

Аргумент операции был SQL_ADD, длина, указанная в привязанном буфере StrLen_or_IndPtr, была SQL_COLUMN_IGNORE, и столбец не имеет значения по умолчанию.
24000 Недопустимое состояние курсора ОператорHandle находился в состоянии выполнения, но результирующий набор не был связан с оператором StatementHandle.
40001 Сбой сериализации Транзакция была откатена из-за взаимоблокировки ресурсов с другой транзакцией.
40003 Неизвестное завершение инструкции Связанное соединение завершилось сбоем во время выполнения этой функции, и состояние транзакции невозможно определить.
42 000 Синтаксическая ошибка или нарушение доступа Драйвер не смог заблокировать строку по мере необходимости, чтобы выполнить операцию, запрошенную в аргументе операции .
44000 Нарушение параметра WITH CHECK OPTION Аргумент операции был SQL_ADD или SQL_UPDATE_BY_BOOKMARK, а вставка или обновление выполнялась в просматриваемой таблице (или таблице, производной от просматриваемой таблицы), созданной путем указания WITH CHECK OPTION, таким образом, чтобы одна или несколько строк, затронутых вставкой или обновлением, больше не присутствовали в просматриваемой таблице.
HY000 Общая ошибка Произошла ошибка, для которой не было определенного SQLSTATE и для которого не было определено значение SQLSTATE для конкретной реализации. Сообщение об ошибке, возвращаемое SQLGetDiagRec в буфере *MessageText , описывает ошибку и ее причину.
HY001 Ошибка выделения памяти Драйверу не удалось выделить память, необходимую для поддержки выполнения или завершения функции.
HY008 Операция отменена Асинхронная обработка была включена для ОператораHandle. Функция была вызвана и до завершения выполнения, SQLCancel или SQLCancelHandle была вызвана на ОператорHandle. Затем функция снова была вызвана на ОператорHandle.

Функция была вызвана и до завершения выполнения SQLCancel или SQLCancelHandle была вызвана оператором StatementHandle из другого потока в многопотоковом приложении.
HY010 Ошибка последовательности функций (DM) Асинхронно выполняющаяся функция была вызвана для дескриптора соединения, связанного с ОператоромHandle. Эта асинхронная функция по-прежнему выполнялась при вызове функции SQLBulkOperations .

(DM) SQLExecute, SQLExecDirect или SQLMoreResults был вызван для ОператораHandle и возвращен SQL_PARAM_DATA_AVAILABLE. Эта функция была вызвана до получения данных для всех потоковых параметров.

(DM) Указанный оператор StatementHandle не находился в состоянии выполнения. Функция была вызвана без первого вызова SQLExecDirect, SQLExecute или функции каталога.

(DM) асинхронно выполняющаяся функция (не эта) была вызвана для StatementHandle и по-прежнему выполнялась при вызове этой функции.

(DM) SQLExecute, SQLExecDirect или SQLSetPos был вызван для StatementHandle и возвращен SQL_NEED_DATA. Эта функция была вызвана до отправки данных для всех параметров выполнения или столбцов.

(DM) Драйвер был ODBC 2.драйвер x и SQLBulkOperations были вызваны для оператора StatementHandle до вызова SQLFetchScroll или SQLFetch .

(DM) SQLBulkOperations был вызван после вызова SQLExtendedFetch в StatementHandle.
HY011 Атрибут не может быть задан сейчас (DM) Драйвер был ODBC 2.Драйвер x и атрибут инструкции SQL_ATTR_ROW_STATUS_PTR был задан между вызовами SQLFetch или SQLFetchScroll и SQLBulkOperations.
HY013 Ошибка управления памятью Не удалось обработать вызов функции, так как к базовым объектам памяти не удалось получить доступ, возможно, из-за низкой памяти.
HY090 Недопустимая длина строки или буфера Аргумент операции был SQL_ADD или SQL_UPDATE_BY_BOOKMARK; значение данных не было пустым указателем; тип данных 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.

Значение в буфере длины или индикатора было SQL_DATA_AT_EXEC; Тип SQL был либо SQL_LONGVARCHAR, SQL_LONGVARBINARY, либо длинный тип данных для конкретного источника данных; и тип сведений SQL_NEED_LONG_DATA_LEN в SQLGetInfo — "Y".

Аргумент операции был SQL_ADD, для атрибута инструкции SQL_ATTR_USE_BOOKMARK задано значение SQL_UB_VARIABLE, а столбец 0 привязан к буферу, длина которого не равна максимальной длине закладки для этого результирующий набор. (Эта длина доступна в поле SQL_DESC_OCTET_LENGTH IRD и может быть получена путем вызова.SQLDescribeCol, SQLColAttribute или SQLGetDescField.)
HY092 Недопустимый идентификатор атрибута (DM) Значение, указанное для аргумента операции , было недопустимым.

Аргумент операции был SQL_ADD, SQL_UPDATE_BY_BOOKMARK или SQL_DELETE_BY_BOOKMARK, а для атрибута инструкции SQL_ATTR_CONCURRENCY задано значение SQL_CONCUR_READ_ONLY.

Аргумент операции был SQL_DELETE_BY_BOOKMARK, SQL_FETCH_BY_BOOKMARK или SQL_UPDATE_BY_BOOKMARK, а столбец закладки не привязан или атрибут инструкции SQL_ATTR_USE_BOOKMARKS был задан для SQL_UB_OFF.
HY117 Подключение приостановлено из-за неизвестного состояния транзакции. Разрешены только функции отключения и только для чтения. (DM) Дополнительные сведения о приостановленном состоянии см. в статье SQLEndTran Function.
HYC00 Необязательный компонент не реализован Драйвер или источник данных не поддерживает операцию, запрошенную в аргументе операции .
HYT00 Время ожидания истекло. Срок ожидания запроса истек, прежде чем источник данных вернул результирующий набор. Период времени ожидания задается через SQLSetStmtAttr с аргументом атрибута SQL_ATTR_QUERY_TIMEOUT.
HYT01 Время ожидания для подключения истекло Срок ожидания подключения истек до того, как источник данных ответил на запрос. Период времени ожидания подключения задается через SQLSetConnectAttr SQL_ATTR_CONNECTION_TIMEOUT.
IM001 Драйвер не поддерживает эту функцию (DM) Драйвер, связанный с StatementHandle , не поддерживает функцию.
IM017 Опрос отключен в асинхронном режиме уведомлений При использовании модели уведомлений опрос отключается.
IM018 SQLCompleteAsync не был вызван для выполнения предыдущей асинхронной операции с этим дескриптором. Если предыдущий вызов функции дескриптора возвращает SQL_STILL_EXECUTING и если включен режим уведомлений, sqlCompleteAsync должен вызываться на дескрипторе для выполнения последующей обработки и завершения операции.

Комментарии

Внимание

Сведения о том, в какой инструкции можно вызвать SQLBulkOperations и что необходимо сделать для совместимости с ODBC 2.Приложения x см. в разделе " Блок-курсоры", "Прокручиваемые курсоры" и "Обратная совместимость " в приложении G. Рекомендации по драйверам для обеспечения обратной совместимости.

Приложение использует SQLBulkOperations для выполнения следующих операций в базовой таблице или представлении, соответствующего текущему запросу:

  • Добавление новых строк.

  • Обновите набор строк, в которых каждая строка определяется закладкой.

  • Удалите набор строк, в которых каждая строка определяется закладкой.

  • Извлекает набор строк, в которых каждая строка определяется закладкой.

После вызова SQLBulkOperations позиция курсора блока не определена. Приложению необходимо вызвать SQLFetchScroll , чтобы задать положение курсора. Приложение должно вызывать SQLFetchScroll только с аргументом FetchOrientation SQL_FETCH_FIRST, SQL_FETCH_LAST, SQL_FETCH_ABSOLUTE или SQL_FETCH_BOOKMARK. Позиция курсора не определена, если приложение вызывает SQLFetch или SQLFetchScroll с аргументом FetchOrientation SQL_FETCH_PRIOR, SQL_FETCH_NEXT или SQL_FETCH_RELATIVE.

Столбец можно игнорировать в массовых операциях, выполняемых вызовом SQLBulkOperations, задав буфер длины или индикатора столбца, указанный в вызове SQLBindCol, для SQL_COLUMN_IGNORE.

Приложению не нужно задавать атрибут инструкции SQL_ATTR_ROW_OPERATION_PTR при вызове SQLBulkOperations , так как строки нельзя игнорировать при выполнении массовых операций с этой функцией.

Буфер, на который указывает атрибут оператора SQL_ATTR_ROWS_FETCHED_PTR, содержит количество строк, затронутых вызовом SQLBulkOperations.

Если аргумент операции SQL_ADD или SQL_UPDATE_BY_BOOKMARK, а список выбора спецификации запроса, связанной с курсором, содержит несколько ссылок на один столбец, он определяется драйвером, создается ли ошибка или драйвер игнорирует повторяющиеся ссылки и выполняет запрошенные операции.

Дополнительные сведения об использовании SQLBulkOperations см. в разделе "Обновление данных с помощью SQLBulkOperations".

Выполнение массовых вставок

Чтобы вставить данные с помощью SQLBulkOperations, приложение выполняет следующую последовательность действий:

  1. Выполняет запрос, возвращающий результирующий набор.

  2. Задает атрибут инструкции SQL_ATTR_ROW_ARRAY_SIZE число строк, которые требуется вставить.

  3. Вызывает SQLBindCol для привязки данных, которые требуется вставить. Данные привязаны к массиву с размером, равным значению SQL_ATTR_ROW_ARRAY_SIZE.

    Заметка

    Размер массива, на который указывает атрибут оператора SQL_ATTR_ROW_STATUS_PTR, должен быть равным SQL_ATTR_ROW_ARRAY_SIZE или SQL_ATTR_ROW_STATUS_PTR должен быть указателем null.

  4. Вызывает SQLBulkOperations(StatementHandle, SQL_ADD) для выполнения вставки.

  5. Если приложение задало атрибут инструкции SQL_ATTR_ROW_STATUS_PTR, он может проверить этот массив, чтобы увидеть результат операции.

Если приложение привязывает столбец 0 перед вызовом SQLBulkOperations с аргументом операции SQL_ADD, драйвер обновит привязанный столбец 0 со значениями закладки для только что вставленной строки. Для этого приложение должно задать атрибут оператора SQL_ATTR_USE_BOOKMARKS SQL_UB_VARIABLE перед выполнением инструкции. (Это не работает с ODBC 2.x driver.)

Длинные данные можно добавлять в части SQLBulkOperations с помощью вызовов SQLParamData и SQLPutData. Дополнительные сведения см. в разделе "Предоставление длинных данных для массовых вставок и обновлений" далее в этой ссылке на функцию.

Приложению не требуется вызывать SQLFetch или SQLFetchScroll , прежде чем вызывать SQLBulkOperations (за исключением случаев, когда происходит против ODBC 2.x driver; см. раздел "Обратная совместимость и соответствие стандартам").

Поведение определяется драйвером, если SQLBulkOperations с аргументом операции SQL_ADD вызывается на курсоре, содержающем повторяющиеся столбцы. Драйвер может возвращать определяемый драйвером SQLSTATE, добавлять данные в первый столбец, отображаемый в результирующем наборе, или выполнять другое поведение, определяемое драйвером.

Выполнение массовых обновлений с помощью закладок

Чтобы выполнить массовые обновления с помощью закладок с SQLBulkOperations, приложение выполняет следующие действия в последовательности:

  1. Задает для атрибута оператора SQL_ATTR_USE_BOOKMARKS значение SQL_UB_VARIABLE.

  2. Выполняет запрос, возвращающий результирующий набор.

  3. Задает атрибут оператора SQL_ATTR_ROW_ARRAY_SIZE число строк, которые требуется обновить.

  4. Вызывает SQLBindCol для привязки данных, которые требуется обновить. Данные привязаны к массиву с размером, равным значению SQL_ATTR_ROW_ARRAY_SIZE. Он также вызывает SQLBindCol для привязки столбца 0 (столбец закладки).

  5. Копирует закладки для строк, которые он заинтересован в обновлении в массиве, привязанном к столбцу 0.

  6. Обновляет данные в привязанных буферах.

    Заметка

    Размер массива, на который указывает атрибут оператора SQL_ATTR_ROW_STATUS_PTR, должен быть равен SQL_ATTR_ROW_ARRAY_SIZE или SQL_ATTR_ROW_STATUS_PTR должен быть указателем null.

  7. Вызывает SQLBulkOperations(StatementHandle, SQL_UPDATE_BY_BOOKMARK).

    Заметка

    Если приложение задало атрибут инструкции SQL_ATTR_ROW_STATUS_PTR, он может проверить этот массив, чтобы увидеть результат операции.

  8. При необходимости вызывает SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK) для получения данных в привязанные буферы приложений, чтобы убедиться, что произошло обновление.

  9. Если данные были обновлены, драйвер изменяет значение в массиве состояния строк для соответствующих строк на SQL_ROW_UPDATED.

Массовые обновления, выполняемые SQLBulkOperations, могут включать длинные данные с помощью вызововSQLParamData и SQLPutData. Дополнительные сведения см. в разделе "Предоставление длинных данных для массовых вставок и обновлений" далее в этой ссылке на функцию.

Если закладки сохраняются на курсорах, приложению не нужно вызывать SQLFetch или SQLFetchScroll перед обновлением по закладкам. Он может использовать закладки, сохраненные из предыдущего курсора. Если закладки не сохраняются между курсорами, приложение должен вызвать SQLFetch или SQLFetchScroll , чтобы получить закладки.

Поведение определяется драйвером, если SQLBulkOperations с аргументом операции SQL_UPDATE_BY_BOOKMARK вызывается на курсоре, содержающем повторяющиеся столбцы. Драйвер может возвращать определяемый драйвером SQLSTATE, обновлять первый столбец, отображаемый в результирующем наборе, или выполнять другое поведение, определяемое драйвером.

Выполнение массовых выборок с помощью закладок

Чтобы выполнить массовые выборки с помощью закладок с SQLBulkOperations, приложение выполняет следующие действия в последовательности:

  1. Задает для атрибута оператора SQL_ATTR_USE_BOOKMARKS значение SQL_UB_VARIABLE.

  2. Выполняет запрос, возвращающий результирующий набор.

  3. Задает атрибут оператора SQL_ATTR_ROW_ARRAY_SIZE число строк, которые требуется получить.

  4. Вызывает SQLBindCol для привязки данных, которые требуется получить. Данные привязаны к массиву с размером, равным значению SQL_ATTR_ROW_ARRAY_SIZE. Он также вызывает SQLBindCol для привязки столбца 0 (столбец закладки).

  5. Копирует закладки для строк, которые он заинтересован в получении в массив, привязанный к столбцу 0. (Предполагается, что приложение уже получило закладки отдельно.)

    Заметка

    Размер массива, на который указывает атрибут оператора SQL_ATTR_ROW_STATUS_PTR, должен быть равен SQL_ATTR_ROW_ARRAY_SIZE или SQL_ATTR_ROW_STATUS_PTR должен быть указателем null.

  6. Вызывает SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK).

  7. Если приложение задало атрибут инструкции SQL_ATTR_ROW_STATUS_PTR, он может проверить этот массив, чтобы увидеть результат операции.

Если закладки сохраняются на курсорах, приложению не нужно вызывать SQLFetch или SQLFetchScroll перед получением закладок по закладкам. Он может использовать закладки, сохраненные из предыдущего курсора. Если закладки не сохраняются между курсорами, приложение должен вызывать SQLFetch или SQLFetchScroll один раз, чтобы получить закладки.

Выполнение массовых удалений с помощью закладок

Чтобы выполнить массовые удаления с помощью закладок с SQLBulkOperations, приложение выполняет следующие действия в последовательности:

  1. Задает для атрибута оператора SQL_ATTR_USE_BOOKMARKS значение SQL_UB_VARIABLE.

  2. Выполняет запрос, возвращающий результирующий набор.

  3. Задает атрибут оператора SQL_ATTR_ROW_ARRAY_SIZE число строк, которые требуется удалить.

  4. Вызывает SQLBindCol для привязки столбца 0 (столбец закладки).

  5. Копирует закладки для строк, которые он заинтересован в удалении в массив, привязанный к столбцу 0.

    Заметка

    Размер массива, на который указывает атрибут оператора SQL_ATTR_ROW_STATUS_PTR, должен быть равен SQL_ATTR_ROW_ARRAY_SIZE или SQL_ATTR_ROW_STATUS_PTR должен быть указателем null.

  6. Вызывает SQLBulkOperations(StatementHandle, SQL_DELETE_BY_BOOKMARK).

  7. Если приложение задало атрибут инструкции SQL_ATTR_ROW_STATUS_PTR, он может проверить этот массив, чтобы увидеть результат операции.

Если закладки сохраняются на курсорах, приложению не нужно вызывать SQLFetch или SQLFetchScroll перед удалением закладками. Он может использовать закладки, сохраненные из предыдущего курсора. Если закладки не сохраняются между курсорами, приложение должен вызывать SQLFetch или SQLFetchScroll один раз, чтобы получить закладки.

Предоставление длинных данных для массовых вставок и обновлений

Длинные данные можно предоставлять для массовых вставок и обновлений, выполняемых вызовами SQLBulkOperations. Чтобы вставить или обновить длинные данные, приложение выполняет следующие действия в дополнение к шагам, описанным в разделах "Выполнение массовых вставок" и "Выполнение массовых обновлений с помощью закладок" ранее в этом разделе.

  1. При привязке данных с помощью SQLBindCol приложение помещает определяемое приложением значение, например номер столбца, в буфер *TargetValuePtr для столбцов выполнения данных. Значение можно использовать позже для идентификации столбца.

    Приложение помещает результат макроса SQL_LEN_DATA_AT_EXEC(length) в буфер *StrLen_or_IndPtr. Если тип данных SQL столбца SQL_LONGVARBINARY, SQL_LONGVARCHAR или длинный тип данных для конкретного источника данных, а драйвер возвращает значение "Y" для типа сведений SQL_NEED_LONG_DATA_LEN в SQLGetInfo, длина — это количество байтов данных, отправляемых для параметра; в противном случае оно должно быть нененегтивным значением и игнорируется.

  2. При вызове SQLBulkOperations , если есть столбцы данных во время выполнения, функция возвращает SQL_NEED_DATA и переходит к шагу 3, который следует ниже. (Если нет столбцов данных во время выполнения, процесс завершен.)

  3. Приложение вызывает SQLParamData , чтобы получить адрес буфера *TargetValuePtr для обработки первого столбца данных во время выполнения. SQLParamData возвращает SQL_NEED_DATA. Приложение извлекает определенное приложением значение из буфера *TargetValuePtr .

    Заметка

    Хотя параметры во время выполнения похожи на столбцы данных во время выполнения, значение, возвращаемое SQLParamData , отличается для каждого.

    Столбцы выполнения данных — это столбцы в наборе строк, для которого данные будут отправляться с ПОМОЩЬЮ SQLPutData при обновлении или вставке строки с помощью SQLBulkOperations. Они привязаны к SQLBindCol. Значение, возвращаемое SQLParamData , — это адрес строки в буфере *TargetValuePtr , который обрабатывается.

  4. Приложение вызывает SQLPutData один или несколько раз для отправки данных для столбца. Требуется несколько вызовов, если все значения данных не могут быть возвращены в буфере *TargetValuePtr, указанном в SQLPutData; несколько вызовов SQLPutData для одного столбца разрешены только при отправке символьных данных C в столбец с символом, двоичным или конкретным типом данных источника данных или при отправке двоичных данных C в столбец с символом, двоичный или конкретный тип данных источника данных.

  5. Приложение снова вызывает SQLParamData , чтобы сообщить о том, что все данные отправлены для столбца.

    • Если есть больше столбцов данных во время выполнения, SQLParamData возвращает SQL_NEED_DATA и адрес буфера TargetValuePtr для обработки следующего столбца данных во время выполнения. Приложение повторяет шаги 4 и 5.

    • Если нет дополнительных столбцов данных во время выполнения, процесс завершается. Если инструкция выполнена успешно, SQLParamData возвращает SQL_SUCCESS или SQL_SUCCESS_WITH_INFO; если выполнение завершилось сбоем, возвращается SQL_ERROR. На этом этапе SQLParamData может возвращать любой SQLSTATE, который может быть возвращен SQLBulkOperations.

Если операция отменена или возникает ошибка в SQLParamData или SQLPutData после того, как SQLBulkOperations возвращает SQL_NEED_DATA и перед отправкой данных для всех столбцов выполнения, приложение может вызывать только SQLCancel, SQLGetDiagField, SQLGetDiagRec, SQLGetFunctions, SQLParamData или SQLPutData для инструкции или соединения, связанного с инструкцией. Если она вызывает любую другую функцию для инструкции или соединение, связанное с инструкцией, функция возвращает SQL_ERROR и SQLSTATE HY010 (ошибка последовательности функций).

Если приложение вызывает SQLCancel , пока драйвер по-прежнему нуждается в данных для столбцов выполнения, драйвер отменяет операцию. Затем приложение может снова вызвать SQLBulkOperations ; отмена не влияет на состояние курсора или текущее положение курсора.

Массив статусов строк

Массив состояния строки содержит значения состояния для каждой строки данных в наборе строк после вызова SQLBulkOperations. Драйвер задает значения состояния в этом массиве после вызова SQLFetch, SQLFetchScroll, SQLSetPos или SQLBulkOperations. Этот массив изначально заполняется вызовом SQLBulkOperations , если SQLFetch или SQLFetchScroll не был вызван до SQLBulkOperations. Этот массив указывает на атрибут оператора SQL_ATTR_ROW_STATUS_PTR. Количество элементов в массивах состояния строк должно совпадать с количеством строк в наборе строк (как определено атрибутом оператора SQL_ATTR_ROW_ARRAY_SIZE). Сведения об этом массиве состояния строк см. в разделе SQLFetch.

Пример кода

В следующем примере извлекается 10 строк данных за раз из таблицы Customers. Затем он предложит пользователю выполнить действие. Чтобы уменьшить сетевой трафик, пример обновления буфера, удаления и вставки локально в ограничивающие массивы, но при смещениях после данных набора строк. Когда пользователь выбирает отправку обновлений, удаление и вставку в источник данных, код задает смещение привязки соответствующим образом и вызывает SQLBulkOperations. Для простоты пользователь не может буферизать более 10 обновлений, удаления или вставки.

// 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);  
}  
Сведения Раздел
Привязка буфера к столбцу в результирующем наборе Функция SQLBindCol
Отмена обработки инструкций Функция SQLCancel
Получение блока данных или прокрутка результирующий набор Функция SQLFetchScroll
Получение одного поля дескриптора Функция SQLGetDescField
Получение нескольких полей дескриптора Функция SQLGetDescRec
Задание одного поля дескриптора Функция SQLSetDescField
Задание нескольких полей дескриптора Функция SQLSetDescRec
Размещение курсора, обновление данных в наборе строк или обновление или удаление данных в наборе строк Функция SQLSetPos
Задание атрибута инструкции Функция SQLSetStmtAttr

См. также

Справочник по API ODBC
Файлы заголовков ODBC