Функция SQLBulkOperations

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

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

Syntax

  
SQLRETURN SQLBulkOperations(  
     SQLHSTMT       StatementHandle,  
     SQLUSMALLINT   Operation);  

Arguments

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

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

SQL_ADD SQL_UPDATE_BY_BOOKMARK SQL_DELETE_BY_BOOKMARK SQL_FETCH_BY_BOOKMARK

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

Returns

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

Diagnostics

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

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

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

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

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

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

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

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

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

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

Аргумент Operation был SQL_FETCH_BY_BOOKMARK, и назначение из точного числового или интервального 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-типа.
23000 Нарушение ограничений целостности Аргумент Operation был SQL_ADD, SQL_DELETE_BY_BOOKMARK или SQL_UPDATE_BY_BOOKMARK, и было нарушено ограничение целостности.

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

Аргумент Operation был SQL_ADD, длина, указанная в bound StrLen_or_IndPtr буфере, была SQL_COLUMN_IGNORE, и столбец не имел значения по умолчанию.
24000 Недопустимое состояние курсора StatementHandle находился в выполненном состоянии, но ни один набор результатов не был связан с StatementHandle.
40001 Сбой сериализации Транзакция была откатена из-за взаимоблокировки ресурсов с другой транзакцией.
40003 Неизвестное завершение инструкции Связанное соединение завершилось сбоем во время выполнения этой функции, и состояние транзакции невозможно определить.
42000 Синтаксическая ошибка или нарушение доступа Драйвер не мог заблокировать строку по мере необходимости для выполнения операции, запрошенной в аргументе Operation .
44000 Нарушение параметра WITH CHECK OPTION Аргумент Operation был SQL_ADD или SQL_UPDATE_BY_BOOKMARK, а вставка или обновление выполнялось в просмотренной таблице (или таблице, полученной из просмотренной таблицы), созданной путём указания С ОПЦИЕЙ ПРОВЕРИТЬ, таким образом, что одна или несколько строк, затронутых вставкой или обновлением, больше не будут присутствовать в просмотренной таблице.
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. Эта функция была вызвана до отправки данных для всех параметров выполнения или столбцов.

(ДМ) Водитель был ODBC 2. x driver и SQLBulkOperations вызывались для StatementHandle до вызова SQLFetchScroll или SQLFetch .

(DM) SQLBulkOperations был вызван после того, как SQLExtendedFetch был вызван на StatementHandle.
HY011 Атрибут не может быть задан сейчас (ДМ) Водитель был ODBC 2. x driver и атрибут оператора 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».

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

Аргумент Operation был SQL_ADD, SQL_UPDATE_BY_BOOKMARK или SQL_DELETE_BY_BOOKMARK, а атрибут оператора SQL_ATTR_CONCURRENCY был настроен на SQL_CONCUR_READ_ONLY.

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

Comments

Предостережение

Для получения информации о том, какие операторы утверждают , 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.

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

Для получения дополнительной информации о том, как использовать 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 должен быть нулевой указателем.

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

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

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

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

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

Поведение определяется драйвером, если SQLBulkOperations с аргументом Operation 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 должен быть нулевым указателем.

  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 с аргументом Operation равным 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 должен быть нулевым указателем.

  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 должен быть нулевым указателем.

  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(длина) в буфер *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 для следующего столбца data-at-execution, который нужно обрабатывать. Приложение повторяет шаги 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 строк данных. Затем пользователь подсказывает о действии. Для снижения сетевого трафика примерный буфер обновляется, удаляет и вставляется локально в связанные массивы, но с смещением за пределами данных строк. Когда пользователь выбирает отправку обновлений, удалений и вставок в источник данных, код правильно устанавливает смещение связей и вызывает 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