Функция SQLSetPos
Соответствие
Представлена версия: соответствие стандартам ODBC 1.0: ODBC
Сводка
SQLSetPos задает положение курсора в наборе строк и позволяет приложению обновлять данные в наборе строк или обновлять или удалять данные в результирующем наборе.
Синтаксис
SQLRETURN SQLSetPos(
SQLHSTMT StatementHandle,
SQLSETPOSIROW RowNumber,
SQLUSMALLINT Operation,
SQLUSMALLINT LockType);
Аргументы
ОператорHandle
[Входные данные] Дескриптор инструкции.
RowNumber
[Входные данные] Позиция строки в наборе строк, на котором выполняется операция, указанная с аргументом operation . Если rowNumber равен 0, операция применяется к каждой строке в наборе строк.
Дополнительные сведения см. в разделе "Комментарии".
Операция
[Входные данные] Операция выполнения:
SQL_POSITION SQL_REFRESH SQL_UPDATE SQL_DELETE
Примечание.
Значение SQL_ADD для аргумента Operation устарело для ODBC 3.x. Драйверы ODBC 3.x должны поддерживать SQL_ADD для обратной совместимости. Эта функция заменена вызовом SQLBulkOperations операцией SQL_ADD. Когда приложение ODBC 3.x работает с драйвером ODBC 2.x, диспетчер драйверов сопоставляет вызов SQLBulkOperations с операцией SQL_ADD с SQLSetPos с операцией SQL_ADD.
Дополнительные сведения см. в разделе "Комментарии".
LockType
[Входные данные] Указывает, как заблокировать строку после выполнения операции, указанной в аргументе операции .
SQL_LOCK_NO_CHANGE SQL_LOCK_EXCLUSIVE SQL_LOCK_UNLOCK
Дополнительные сведения см. в разделе "Комментарии".
Возвраты
SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_NEED_DATA, SQL_STILL_EXECUTING, SQL_ERROR или SQL_INVALID_HANDLE.
Диагностика
Когда SQLSetPos возвращает SQL_ERROR или SQL_SUCCESS_WITH_INFO, связанное значение SQLSTATE может быть получено путем вызова SQLGetDiagRec с помощью HandleType SQL_HANDLE_STMT и handle of StatementHandle. В следующей таблице перечислены значения SQLSTATE, которые обычно возвращаются SQLSetPos и объясняются каждый из них в контексте этой функции. Нотация "(DM)" предшествует описаниям SQLSTATEs, возвращаемым диспетчером драйверов. Возвращаемый код, связанный с каждым значением SQLSTATE, SQL_ERROR, если не указано иное.
Для всех этих SQLSTATEs, которые могут возвращать SQL_SUCCESS_WITH_INFO или SQL_ERROR (кроме 01xxx SQLSTATEs), SQL_SUCCESS_WITH_INFO возвращается, если ошибка возникает в одной или нескольких строках многострочных операций и SQL_ERROR возвращается, если ошибка возникает при однострочной операции.
SQLSTATE | Ошибка | Описание |
---|---|---|
01000 | Общее предупреждение | Информационное сообщение для конкретного драйвера. (Функция возвращает SQL_SUCCESS_WITH_INFO.) |
01001 | Конфликт операций курсора | Аргумент операции был SQL_DELETE или SQL_UPDATE, а строки или несколько строк не были удалены или обновлены. (Дополнительные сведения об обновлениях нескольких строк см. в описании SQL_ATTR_SIMULATE_CURSOR Атрибут в SQLSetStmtAttr.) (функция возвращает SQL_SUCCESS_WITH_INFO.) Аргумент операции был SQL_DELETE или SQL_UPDATE, и операция завершилась ошибкой из-за оптимистичного параллелизма. (Функция возвращает SQL_SUCCESS_WITH_INFO.) |
01004 | Усечение строковых данных | Аргумент операции был SQL_REFRESH, а строковые или двоичные данные, возвращаемые для столбца или столбцов с типом данных SQL_C_CHAR или SQL_C_BINARY, привели к усечению небланковых символов или ненулевых двоичных данных. |
01S01 | Ошибка в строке | Аргумент RowNumber был 0, и произошла ошибка в одной или нескольких строках при выполнении операции, указанной с аргументом операции. (SQL_SUCCESS_WITH_INFO возвращается, если ошибка возникает в одной или нескольких строках многоразовой операции и возвращается SQL_ERROR, если ошибка возникает при однострочной операции.) (Этот SQLSTATE возвращается только в том случае, если SQLSetPos вызывается после SQLExtendedFetch, если драйвер является драйвером ODBC 2.x и библиотекой курсоров не используется.) |
01S07 | Дробное усечение | Аргумент операции был SQL_REFRESH, тип данных буфера приложения не был SQL_C_CHAR или SQL_C_BINARY, а данные, возвращенные в буферы приложений для одного или нескольких столбцов, усечены. Для числовых типов данных дробная часть числа была усечена. Для времени, метки времени и типы данных интервала, содержащие компонент времени, дробная часть времени была усечена. (Функция возвращает SQL_SUCCESS_WITH_INFO.) |
07006 | Нарушение атрибута ограниченного типа данных | Не удалось преобразовать значение данных столбца в результирующем наборе в тип данных, указанный TargetType в вызове SQLBindCol. |
07009 | Недопустимый индекс дескриптора | Операция аргумента была SQL_REFRESH или SQL_UPDATE, и столбец был привязан к числу столбцов больше числа столбцов в результирующем наборе. |
21S02 | Степень производной таблицы не соответствует списку столбцов | Операция аргумента была SQL_UPDATE, и никакие столбцы не обновлялись, так как все столбцы были либо несвязанными, только для чтения, либо значение в буфере привязанной длины или индикатора не было SQL_COLUMN_IGNORE. |
22001 | Строковые данные, правое усечение | Аргумент операции был SQL_UPDATE, а назначение символа или двоичного значения столбцу привело к усечению небланк (для символов) или непустых (для двоичных) символов или байтов. |
22003 | Числовое значение вне диапазона | Операция аргумента была SQL_UPDATE, а назначение числового значения столбцу в результирующем наборе привело ко всей части (в отличие от дробной) части числа, усеченной. Операция аргумента была SQL_REFRESH, и возврат числовое значение для одного или нескольких привязанных столбцов привело бы к потере значительных цифр. |
22007 | Недопустимый формат datetime | Операция аргумента была SQL_UPDATE, а назначение значения даты или метки времени столбцу в результирующем наборе привело к тому, что поле года, месяца или дня выходит за пределы диапазона. Операция аргумента была SQL_REFRESH, и возвращая значение даты или метки времени для одного или нескольких привязанных столбцов, привело бы к тому, что поле года, месяца или дня будет не в диапазоне. |
22008 | Переполнение поля даты и времени | Аргумент операции был SQL_UPDATE, а производительность арифметики даты и времени, отправляемых в столбец в результирующем наборе, привела к полю даты и времени (год, месяц, день, час, минута или второе поле) результата за пределами допустимого диапазона значений поля или недопустимого в соответствии с естественными правилами григорианского календаря для дат и времени. Аргумент операции был SQL_REFRESH, а производительность арифметики datetime для данных, полученных из результируемого набора, привела к полю даты и времени (год, месяц, день, час, минута или второе поле) результата за пределами допустимого диапазона значений поля или недопустимого в соответствии с естественными правилами григорианского календаря для дат и времени. |
22015 | Переполнение поля интервала | Аргумент операции был SQL_UPDATE, а назначение точного числового или интервалного типа C в тип данных SQL приводило к потере значительных цифр. Аргумент операции был SQL_UPDATE; при назначении типа SQL интервала не было представления значения типа C в типе SQL интервала. Аргумент операции был SQL_REFRESH, и назначение от точного числового или интервалного типа SQL к типу C приводило к потере значительных цифр в главном поле. Аргумент операции был SQL_ REFRESH; при назначении типа C интервала не было представления значения типа SQL в типе C интервала. |
22018 | Недопустимое значение символа для спецификации приведения | Аргумент операции был SQL_REFRESH; тип C был точным или приблизительным числом, датой и интервалом, типом данных SQL столбца был символьный тип данных, а значение в столбце не было допустимым литералом привязанного типа C. Операция аргумента была SQL_UPDATE; тип SQL был точным или приблизительным числом, датой или типом данных интервала; тип C был SQL_C_CHAR; значение в столбце не было допустимым литералом связанного типа SQL. |
23000 | Нарушение ограничений целостности | Операция аргумента была SQL_DELETE или SQL_UPDATE, а ограничение целостности было нарушено. |
24000 | Недопустимое состояние курсора | ОператорHandle находился в состоянии выполнения, но результирующий набор не был связан с оператором StatementHandle. (DM) Курсор был открыт на ОператорHandle, но SQLFetch или SQLFetchScroll не был вызван. Курсор был открыт на ОператорHandle, а sqlFetch или SQLFetchScroll был вызван, но курсор был размещен до начала результирующий набор или после окончания результирующий набор. Операция аргумента была SQL_DELETE, SQL_REFRESH или SQL_UPDATE, а курсор был размещен до начала результирующий набор или после окончания результирующий набор. |
40001 | Сбой сериализации | Транзакция была откатена из-за взаимоблокировки ресурсов с другой транзакцией. |
40003 | Неизвестное завершение инструкции | Связанное соединение завершилось сбоем во время выполнения этой функции, и состояние транзакции невозможно определить. |
42 000 | Синтаксическая ошибка или нарушение доступа | Драйвер не смог заблокировать строку по мере необходимости для выполнения операции, запрошенной в операции аргумента. Драйвер не смог заблокировать строку, как запрошено в аргументе LockType. |
44000 | Нарушение параметра WITH CHECK OPTION | Аргумент операции был SQL_UPDATE, и обновление было выполнено в просматриваемой таблице или таблице, полученной из просматриваемой таблицы, созданной путем указания WITH CHECK OPTION, таким образом, что одна или несколько строк, затронутых обновлением, больше не будут присутствовать в просматриваемой таблице. |
HY000 | Общая ошибка | Произошла ошибка, для которой не было определенного SQLSTATE и для которого не было определено значение SQLSTATE для конкретной реализации. Сообщение об ошибке, возвращаемое SQLGetDiagRec в буфере *MessageText , описывает ошибку и ее причину. |
HY001 | Ошибка выделения памяти | Драйверу не удалось выделить память, необходимую для поддержки выполнения или завершения функции. |
HY008 | Операция отменена | Асинхронная обработка была включена для ОператораHandle. Функция была вызвана и до завершения выполнения, SQLCancel или SQLCancelHandle была вызвана в операторе StatementHandle, а затем функция была вызвана снова на ОператорHandle. Функция была вызвана и до завершения выполнения SQLCancel или SQLCancelHandle была вызвана оператором StatementHandle из другого потока в многопотоковом приложении. |
HY010 | Ошибка последовательности функций | (DM) Асинхронно выполняющаяся функция была вызвана для дескриптора соединения, связанного с ОператоромHandle. Эта асинхронная функция по-прежнему выполнялась при вызове функции SQLSetPos. (DM) Указанный оператор StatementHandle не находился в состоянии выполнения. Функция была вызвана без первого вызова SQLExecDirect, SQLExecute или функции каталога. (DM) асинхронно выполняющаяся функция (не эта) была вызвана для StatementHandle и по-прежнему выполнялась при вызове этой функции. (DM) SQLExecute, SQLExecDirect, SQLBulkOperations или SQLSetPos были вызваны для ОператораHandle и возвращены SQL_NEED_DATA. Эта функция была вызвана до отправки данных для всех параметров выполнения или столбцов. (DM) Драйвер был драйвером ODBC 2.x , и SQLSetPos был вызван для ОператораHandle после вызова SQLFetch . |
HY011 | Атрибут не может быть задан сейчас | (DM) Драйвер был драйвером ODBC 2.x; был задан атрибут инструкции SQL_ATTR_ROW_STATUS_PTR; затем sqlSetPos был вызван до вызова SQLFetch, SQLFetchScroll или SQLExtendedFetchFetch. |
HY013 | Ошибка управления памятью | Не удалось обработать вызов функции, так как к базовым объектам памяти не удалось получить доступ, возможно, из-за низкой памяти. |
HY090 | Недопустимая длина строки или буфера | Аргумент операции был SQL_UPDATE, значение данных было пустым указателем, а длина столбца не равна 0, SQL_DATA_AT_EXEC, SQL_COLUMN_IGNORE, SQL_NULL_DATA или меньше или равно SQL_LEN_DATA_AT_EXEC_OFFSET. Аргумент операции был SQL_UPDATE; значение данных не было пустым указателем; тип данных 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". |
HY092 | Недопустимый идентификатор атрибута | (DM) Значение, указанное для аргумента операции , было недопустимым. (DM) Значение, указанное для аргумента LockType , было недопустимым. Аргумент операции был SQL_UPDATE или SQL_DELETE, а атрибут инструкции SQL_ATTR_CONCURRENCY был SQL_ATTR_CONCUR_READ_ONLY. |
HY107 | Значение строки вне диапазона | Значение, указанное для аргумента RowNumber , больше числа строк в наборе строк. |
HY109 | Недопустимое положение курсора | Курсор, связанный с оператором StatementHandle , был определен как только для пересылки, поэтому курсор не может быть расположен в наборе строк. См. описание атрибута SQL_ATTR_CURSOR_TYPE в SQLSetStmtAttr. Аргумент операции был SQL_UPDATE, SQL_DELETE или SQL_REFRESH, а строка, определяемая аргументом RowNumber, была удалена или не была возвращена. (DM) Аргумент RowNumber был 0, и аргумент операции был SQL_POSITION. SQLSetPos был вызван после вызова SQLBulkOperations и до вызова SQLFetchScroll или SQLFetch . |
HY117 | Подключение приостановлено из-за неизвестного состояния транзакции. Разрешены только функции отключения и только для чтения. | (DM) Дополнительные сведения о приостановленном состоянии см. в статье SQLEndTran Function. |
HYC00 | Необязательный компонент не реализован | Драйвер или источник данных не поддерживает операцию, запрошенную в аргументе операции или аргументе LockType . |
HYT00 | Время ожидания истекло. | Срок ожидания запроса истек, прежде чем источник данных вернул результирующий набор. Период времени ожидания задается через SQLSetStmtAttr с атрибутом SQL_ATTR_QUERY_TIMEOUT. |
HYT01 | Время ожидания для подключения истекло | Срок ожидания подключения истек до того, как источник данных ответил на запрос. Период времени ожидания подключения задается через SQLSetConnectAttr SQL_ATTR_CONNECTION_TIMEOUT. |
IM001 | Драйвер не поддерживает эту функцию | (DM) Драйвер, связанный с StatementHandle , не поддерживает функцию. |
IM017 | Опрос отключен в асинхронном режиме уведомлений | При использовании модели уведомлений опрос отключается. |
IM018 | SQLCompleteAsync не был вызван для выполнения предыдущей асинхронной операции с этим дескриптором. | Если предыдущий вызов функции дескриптора возвращает SQL_STILL_EXECUTING и если включен режим уведомлений, sqlCompleteAsync должен вызываться на дескрипторе для выполнения последующей обработки и завершения операции. |
Комментарии
Внимание
Сведения об инструкции о том, что SQLSetPos можно вызывать и что необходимо сделать для совместимости с приложениями ODBC 2.x , см. в разделе "Блокировать курсоры", " Прокручиваемые курсоры" и "Обратная совместимость".
Аргумент RowNumber
Аргумент RowNumber указывает количество строк в наборе строк, для которого выполняется операция, указанная аргументом operation . Если rowNumber равен 0, операция применяется к каждой строке в наборе строк. RowNumber должен быть значением от 0 до числа строк в наборе строк.
Примечание.
На языке C массивы основаны на 0, а аргумент RowNumber — 1. Например, чтобы обновить пятую строку набора строк, приложение изменяет буферы наборов строк в индексе массива 4, но указывает число строк 5.
Все операции поместите курсор на строку, указанную в RowNumber. Для следующих операций требуется положение курсора:
Позиционированные инструкции обновления и удаления.
Вызовы SQLGetData.
Вызовы SQLSetPos с параметрами SQL_DELETE, SQL_REFRESH и SQL_UPDATE.
Например, если RowNumber имеет значение 2 для вызова SQLSetPos с операцией SQL_DELETE, курсор размещается во второй строке набора строк, и эта строка удаляется. Запись в массиве состояния строки реализации (указываемая атрибутом оператора SQL_ATTR_ROW_STATUS_PTR) для второй строки изменяется на SQL_ROW_DELETED.
Приложение может указать позицию курсора при вызове SQLSetPos. Как правило, он вызывает SQLSetPos с операцией SQL_POSITION или SQL_REFRESH для размещения курсора перед выполнением инструкции с размещением или удалением или вызовом SQLGetData.
Аргумент операции
Аргумент операции поддерживает следующие операции. Чтобы определить, какие параметры поддерживаются источником данных, приложение вызывает SQLGetInfo с типом сведений SQL_DYNAMIC_CURSOR_ATTRIBUTES1, SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1, SQL_KEYSET_CURSOR_ATTRIBUTES1 или SQL_STATIC_CURSOR_ATTRIBUTES1 (в зависимости от типа курсора).
Операция аргумент |
Операция |
---|---|
SQL_POSITION | Драйвер помещает курсор в строку, указанную строкой RowNumber. Содержимое массива состояния строки, на который указывает атрибут инструкции SQL_ATTR_ROW_OPERATION_PTR, игнорируется для операции SQL_POSITION. |
SQL_REFRESH | Драйвер помещает курсор в строку, указанную строкой RowNumber , и обновляет данные в буферах набора строк для этой строки. Дополнительные сведения о том, как драйвер возвращает данные в буферах набора строк, см. в описаниях привязки строк и столбцов в SQLBindCol. SQLSetPos с операцией SQL_REFRESH обновляет состояние и содержимое строк в текущем наборе строк. Это включает обновление закладок. Так как данные в буферах обновляются, но не возвращаются, членство в наборе строк исправлено. Это отличается от обновления, выполняемого вызовом SQLFetchScroll с помощью FetchOrientation SQL_FETCH_RELATIVE и RowNumber равным 0, который возвращает набор строк из результирующий набор, чтобы он отображал добавленные данные и удалять удаленные данные, если эти операции поддерживаются драйвером и курсором. Успешное обновление с помощью SQLSetPos не изменит состояние строки SQL_ROW_DELETED. Удаленные строки в наборе строк будут по-прежнему помечены как удаленные до следующего получения. Строки исчезают при следующем выборке, если курсор поддерживает упаковку (в которой последующий sqlFetch или SQLFetchScroll не возвращает удаленные строки). Добавленные строки не отображаются при выполнении обновления с помощью SQLSetPos . Это поведение отличается от SQLFetchScroll с FetchType SQL_FETCH_RELATIVE и rowNumber равно 0, которое также обновляет текущий набор строк, но будет отображать добавленные записи или пакеты удаленных записей, если эти операции поддерживаются курсором. Успешное обновление с помощью SQLSetPos изменит состояние строки SQL_ROW_ADDED на SQL_ROW_SUCCESS (если массив состояния строки существует). Успешное обновление с помощью SQLSetPos изменит состояние строки SQL_ROW_UPDATED на новое состояние строки (если массив состояния строки существует). Если ошибка возникает в операции SQLSetPos в строке, состояние строки устанавливается SQL_ROW_ERROR (если массив состояния строки существует). Для курсора, открытого с помощью атрибута инструкции SQL_ATTR_CONCURRENCY SQL_CONCUR_ROWVER или SQL_CONCUR_VALUES, обновление с помощью SQLSetPos может обновить оптимистические значения параллелизма, используемые источником данных для обнаружения изменения строки. В этом случае версии строк или значения, используемые для обеспечения параллелизма курсоров, обновляются всякий раз, когда буферы набора строк обновляются с сервера. Это происходит для каждой обновляемой строки. Содержимое массива состояния строки, на который указывает атрибут инструкции SQL_ATTR_ROW_OPERATION_PTR, игнорируется для операции SQL_REFRESH. |
SQL_UPDATE | Драйвер помещает курсор в строку, указанную строкой RowNumber , и обновляет базовую строку данных со значениями в буферах набора строк ( аргумент TargetValuePtr в SQLBindCol). Он извлекает длину данных из буферов длины или индикатора ( аргумент StrLen_or_IndPtr в SQLBindCol). Если длина любого столбца SQL_COLUMN_IGNORE, столбец не обновляется. После обновления строки драйвер изменяет соответствующий элемент массива состояния строки на SQL_ROW_UPDATED или SQL_ROW_SUCCESS_WITH_INFO (если существует массив состояния строки). Это определяется драйвером, что такое поведение, если SQLSetPos с аргументом операции SQL_UPDATE вызывается на курсоре, содержающем повторяющиеся столбцы. Драйвер может возвращать определяемый драйвером SQLSTATE, обновлять первый столбец, отображаемый в результирующем наборе, или выполнять другое поведение, определенное драйвером. Массив операций строк, на который указывает атрибут инструкции SQL_ATTR_ROW_OPERATION_PTR, можно использовать для указания, что строка в текущем наборе строк должна игнорироваться во время массового обновления. Дополнительные сведения см. в разделе "Массивы состояний и операций" далее в этой ссылке на функцию. |
SQL_DELETE | Драйвер помещает курсор в строку, указанную строкой RowNumber , и удаляет базовую строку данных. Он изменяет соответствующий элемент массива состояния строки на SQL_ROW_DELETED. После удаления строки следующие недопустимы для строки: позиционированные инструкции обновления и удаления, вызовы SQLGetData и вызовы SQLSetPos с набором операций, кроме SQL_POSITION. Для драйверов, поддерживающих упаковку, строка удаляется из курсора при получении новых данных из источника данных. Остается ли строка видимой, зависит от типа курсора. Например, удаленные строки видны статическим и управляемым набором ключей курсорам, но невидимым динамическим курсорам. Массив операций строк, на который указывает атрибут инструкции SQL_ATTR_ROW_OPERATION_PTR, можно использовать для указания того, что во время массового удаления следует игнорировать строку в текущем наборе строк. Дополнительные сведения см. в разделе "Массивы состояний и операций" далее в этой ссылке на функцию. |
Аргумент LockType
Аргумент LockType предоставляет способ управления параллелизмом приложений. В большинстве случаев источники данных, поддерживающие уровни параллелизма и транзакции, поддерживают только SQL_LOCK_NO_CHANGE значение аргумента LockType . Аргумент LockType обычно используется только для поддержки на основе файлов.
Аргумент LockType указывает состояние блокировки строки после выполнения SQLSetPos . Если драйвер не может заблокировать строку для выполнения запрошенной операции или выполнения аргумента LockType , он возвращает SQL_ERROR и SQLSTATE 42000 (ошибка синтаксиса или нарушение доступа).
Хотя аргумент LockType указан для одной инструкции, блокировка предоставляет одинаковые привилегии всем операторам подключения. В частности, блокировка, полученная одним оператором подключения, может быть разблокирована другой инструкцией в том же соединении.
Строка, заблокированная через SQLSetPos, остается заблокированной до тех пор, пока приложение не вызовет SQLSetPos для строки с параметром LockType, установленным для SQL_LOCK_UNLOCK, или пока приложение не вызовет SQLFreeHandle для инструкции или SQLFreeStmt с параметром SQL_CLOSE. Для драйвера, поддерживающего транзакции, строка, заблокированная через SQLSetPos , разблокируется при вызове SQLEndTran фиксации или отката транзакции в соединении (если курсор закрывается при фиксации или откате транзакции, как указано в SQL_CURSOR_COMMIT_BEHAVIOR и SQL_CURSOR_ROLLBACK_BEHAVIOR типах информации, возвращаемых SQLGetInfo).
Аргумент LockType поддерживает следующие типы блокировок. Чтобы определить, какие блокировки поддерживаются источником данных, приложение вызывает SQLGetInfo с SQL_DYNAMIC_CURSOR_ATTRIBUTES1, SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1, SQL_KEYSET_CURSOR_ATTRIBUTES1 или тип информации SQL_STATIC_CURSOR_ATTRIBUTES1 (в зависимости от типа курсора).
Аргумент LockType | Тип блокировки |
---|---|
SQL_LOCK_NO_CHANGE | Драйвер или источник данных гарантирует, что строка находится в том же заблокированном или разблокированном состоянии, что и до вызова SQLSetPos . Это значение LockType позволяет источникам данных, которые не поддерживают явную блокировку на уровне строк, чтобы использовать любую блокировку, необходимую текущим уровням параллелизма и изоляции транзакций. |
SQL_LOCK_EXCLUSIVE | Драйвер или источник данных блокирует строку исключительно. Оператор по другому подключению или другому приложению не может использоваться для получения каких-либо блокировок строки. |
SQL_LOCK_UNLOCK | Драйвер или источник данных разблокирует строку. |
Если драйвер поддерживает SQL_LOCK_EXCLUSIVE, но не поддерживает SQL_LOCK_UNLOCK, строка, заблокированная, остается заблокированной до тех пор, пока не будет выполняться один из вызовов функции, описанных в предыдущем абзаце.
Если драйвер поддерживает SQL_LOCK_EXCLUSIVE, но не поддерживает SQL_LOCK_UNLOCK, строка, заблокированная, останется заблокированной, пока приложение не вызовет SQLFreeHandle для инструкции или SQLFreeStmt с параметром SQL_CLOSE. Если драйвер поддерживает транзакции и закрывает курсор при фиксации или откате транзакции, приложение вызывает SQLEndTran.
Для операций обновления и удаления в SQLSetPos приложение использует аргумент LockType следующим образом:
Чтобы гарантировать, что строка не изменяется после получения, приложение вызывает SQLSetPos с набором операций SQL_REFRESH и LockType , для которого задано значение SQL_LOCK_EXCLUSIVE.
Если приложению задано значение LockType для SQL_LOCK_NO_CHANGE, драйвер гарантирует, что операция обновления или удаления будет выполнена успешно, только если приложение, указанное SQL_CONCUR_LOCK для атрибута инструкции SQL_ATTR_CONCURRENCY.
Если приложение указывает SQL_CONCUR_ROWVER или SQL_CONCUR_VALUES для атрибута инструкции SQL_ATTR_CONCURRENCY, драйвер сравнивает версии строк или значения и отклоняет операцию, если строка изменилась после получения строки.
Если приложение указывает SQL_CONCUR_READ_ONLY для атрибута инструкции SQL_ATTR_CONCURRENCY, драйвер отклоняет любую операцию обновления или удаления.
Дополнительные сведения об атрибуте инструкции SQL_ATTR_CONCURRENCY см. в разделе SQLSetStmtAttr.
Массивы состояний и операций
При вызове SQLSetPos используются следующие массивы состояния и операций:
Массив состояния строки (как указано в поле SQL_DESC_ARRAY_STATUS_PTR в IRD и атрибуте оператора SQL_ATTR_ROW_STATUS_ARRAY) содержит значения состояния для каждой строки данных в наборе строк. Драйвер задает значения состояния в этом массиве после вызова SQLFetch, SQLFetchScroll, SQLBulkOperations или SQLSetPos. Этот массив указывает на атрибут оператора SQL_ATTR_ROW_STATUS_PTR.
Массив операций строк (как указано на поле SQL_DESC_ARRAY_STATUS_PTR в ARD и атрибуте оператора SQL_ATTR_ROW_OPERATION_ARRAY) содержит значение для каждой строки в наборе строк, указывающее, игнорируется ли вызов SQLSetPos для массовой операции. Каждый элемент в массиве имеет значение SQL_ROW_PROCEED (по умолчанию) или SQL_ROW_IGNORE. Этот массив указывает на атрибут оператора SQL_ATTR_ROW_OPERATION_PTR.
Количество элементов в массивах состояния и операций должно совпадать с количеством строк в наборе строк (как определено атрибутом оператора SQL_ATTR_ROW_ARRAY_SIZE).
Сведения о массиве состояния строки см. в разделе SQLFetch. Дополнительные сведения о массиве операций строк см. в разделе "Игнорировать строку в массовой операции" далее в этом разделе.
Использование SQLSetPos
Прежде чем приложение вызывает SQLSetPos, он должен выполнить следующую последовательность действий:
Если приложение вызовет SQLSetPos с набором операций для SQL_UPDATE, вызовите SQLBindCol (или SQLSetDescRec) для каждого столбца, чтобы указать тип данных и привязать буферы для данных и длины столбца.
Если приложение вызовет SQLSetPos с набором операций SQL_DELETE или SQL_UPDATE, вызовите SQLColAttribute, чтобы убедиться, что столбцы, которые необходимо удалить или обновить, обновляются.
Вызовите SQLExecDirect, SQLExecute или функцию каталога, чтобы создать результирующий набор.
Вызовите SQLFetch или SQLFetchScroll , чтобы получить данные.
Дополнительные сведения об использовании SQLSetPos см. в разделе "Обновление данных с помощью SQLSetPos".
Удаление данных с помощью SQLSetPos
Чтобы удалить данные с помощью SQLSetPos, приложение вызывает SQLSetPos с RowNumber, для которых задано число строк для удаления и операции, для которых задано значение SQL_DELETE.
После удаления данных драйвер изменяет значение в массиве состояния строки реализации на SQL_ROW_DELETED (или SQL_ROW_ERROR).
Обновление данных с помощью SQLSetPos
Приложение может передать значение столбца в привязанном буфере данных или с одним или несколькими вызовами SQLPutData. Столбцы, данные которых передаются с помощью SQLPutData, называются столбцами данных при выполнении. Они обычно используются для отправки данных для столбцов SQL_LONGVARBINARY и SQL_LONGVARCHAR и могут быть смешанными с другими столбцами.
Чтобы обновить данные с помощью SQLSetPos, приложение:
Помещает значения в буферы данных и длины или индикатора, привязанные к SQLBindCol:
Для обычных столбцов приложение помещает новое значение столбца в буфер *TargetValuePtr и длину этого значения в буфер *StrLen_or_IndPtr . Если строка не должна быть обновлена, приложение помещает SQL_ROW_IGNORE в элемент этой строки массива операций строки.
Для столбцов данных во время выполнения приложение помещает определяемое приложением значение, например номер столбца, в буфер *TargetValuePtr . Значение можно использовать позже для идентификации столбца.
Приложение помещает результат макроса SQL_LEN_DATA_AT_EXEC(length) в буфер *StrLen_or_IndPtr . Если тип данных SQL столбца SQL_LONGVARBINARY, SQL_LONGVARCHAR или длинный тип данных для конкретного источника данных, а драйвер возвращает значение "Y" для типа сведений SQL_NEED_LONG_DATA_LEN в SQLGetInfo, длина — это количество байтов данных, отправляемых для параметра; в противном случае оно должно быть неотрицательное значение и игнорируется.
Вызывает SQLSetPos с аргументом операции, заданным для SQL_UPDATE для обновления строки данных.
Если нет столбцов данных во время выполнения, процесс завершается.
Если есть столбцы данных во время выполнения, функция возвращает SQL_NEED_DATA и переходит к шагу 3.
Вызывает SQLParamData , чтобы получить адрес буфера *TargetValuePtr для первого столбца обработки данных во время выполнения. SQLParamData возвращает SQL_NEED_DATA. Приложение извлекает определенное приложением значение из буфера *TargetValuePtr .
Примечание.
Несмотря на то, что параметры во время выполнения аналогичны столбцам во время выполнения, значение, возвращаемое SQLParamData , отличается для каждого.
Примечание.
Параметры выполнения данных — это параметры в инструкции SQL, для которой данные будут отправляться с SQLPutData при выполнении инструкции с помощью SQLExecDirect или SQLExecute. Они привязаны к SQLBindParameter или задают дескрипторы с помощью SQLSetDescRec. Значение, возвращаемое SQLParamData , является 32-разрядным значением, передаваемым в SQLBindParameter в аргументе ParameterValuePtr .
Примечание.
Столбцы данных во время выполнения — это столбцы в наборе строк, для которого данные будут отправляться с помощью SQLPutData при обновлении строки с помощью SQLSetPos. Они привязаны к SQLBindCol. Значение, возвращаемое SQLParamData , — это адрес строки в буфере *TargetValuePtr , который обрабатывается.
Вызывает SQLPutData один или несколько раз для отправки данных для столбца. Требуется несколько вызовов, если все значения данных не могут быть возвращены в буфере *TargetValuePtr, указанном в SQLPutData; несколько вызовов SQLPutData для одного столбца разрешены только при отправке символьных данных C в столбец с символом, двоичным или конкретным типом данных источника данных или при отправке двоичных данных C в столбец с символом, двоичный или конкретный тип данных источника данных.
Вызывает SQLParamData еще раз, чтобы сообщить о том, что все данные отправлены для столбца.
Если есть больше столбцов данных во время выполнения, SQLParamData возвращает SQL_NEED_DATA и адрес буфера TargetValuePtr для обработки следующего столбца данных во время выполнения. Приложение повторяет шаги 4 и 5.
Если нет дополнительных столбцов данных во время выполнения, процесс завершается. Если инструкция выполнена успешно, SQLParamData возвращает SQL_SUCCESS или SQL_SUCCESS_WITH_INFO; если выполнение завершилось сбоем, возвращается SQL_ERROR. На этом этапе SQLParamData может возвращать любой SQLSTATE, который может быть возвращен SQLSetPos.
Если данные были обновлены, драйвер изменяет значение в массиве состояния строки реализации для соответствующей строки на SQL_ROW_UPDATED.
Если операция отменена или возникает ошибка в SQLParamData или SQLPutData, после того как SQLSetPos возвращает SQL_NEED_DATA и перед отправкой данных для всех столбцов выполнения данных, приложение может вызывать только SQLCancel, SQLGetDiagField, SQLGetDiagRec, SQLGetFunctions, SQLParamData или SQLPutData для инструкции или соединение, связанное с инструкцией. Если она вызывает любую другую функцию для инструкции или соединение, связанное с инструкцией, функция возвращает SQL_ERROR и SQLSTATE HY010 (ошибка последовательности функций).
Если приложение вызывает SQLCancel , пока драйвер по-прежнему нуждается в данных для столбцов выполнения, драйвер отменяет операцию. Затем приложение может снова вызвать SQLSetPos ; отмена не влияет на состояние курсора или текущее положение курсора.
Если в списке SELECT спецификации запроса, связанной с курсором, содержится несколько ссылок на один столбец, создается ошибка или драйвер игнорирует повторяющиеся ссылки и выполняет запрошенные операции, определяемые драйвером.
Выполнение массовых операций
Если аргумент RowNumber равен 0, драйвер выполняет операцию, указанную в аргументе операции для каждой строки в наборе строк, которая имеет значение SQL_ROW_PROCEED в поле в массиве операций строк, на который указывает атрибут инструкции SQL_ATTR_ROW_OPERATION_PTR. Это допустимое значение аргумента RowNumber для аргумента операции SQL_DELETE, SQL_REFRESH или SQL_UPDATE, но не SQL_POSITION. SQLSetPos с операцией SQL_POSITION и номером RowNumber , равным 0, возвращает SQLSTATE HY109 (недопустимое положение курсора).
Если возникает ошибка, относящаяся ко всему набору строк, например SQLSTATE HYT00 (истекло время ожидания), драйвер возвращает SQL_ERROR и соответствующее значение SQLSTATE. Содержимое буферов набора строк не определено, а положение курсора не изменяется.
Если возникает ошибка, относящаяся к одной строке, драйвер:
Задает элемент для строки в массиве состояния строки, на который указывает атрибут оператора SQL_ATTR_ROW_STATUS_PTR значение SQL_ROW_ERROR.
Публикует один или несколько дополнительных SQLSTATEs для ошибки в очереди ошибок и задает поле SQL_DIAG_ROW_NUMBER в структуре диагностических данных.
После обработки ошибки или предупреждения драйвер завершает операцию для оставшихся строк в наборе строк, он возвращает SQL_SUCCESS_WITH_INFO. Таким образом, для каждой строки, возвращающей ошибку, очередь ошибок содержит ноль или более дополнительных SQLSTATEs. Если драйвер останавливает операцию после обработки ошибки или предупреждения, он возвращает SQL_ERROR.
Если драйвер возвращает предупреждения, такие как SQLSTATE 01004 (усеченные данные), он возвращает предупреждения, которые применяются ко всему набору строк или неизвестным строкам в наборе строк перед возвратом сведений об ошибке, применяемых к определенным строкам. Он возвращает предупреждения для определенных строк вместе с другими сведениями об ошибках этих строк.
Если значение RowNumber равно 0, а операция — SQL_UPDATE, SQL_REFRESH или SQL_DELETE, число строк, на которые работает SQLSetPos , указывает атрибут инструкции SQL_ATTR_ROWS_FETCHED_PTR.
Если значение RowNumber равно 0, а операция SQL_DELETE, SQL_REFRESH или SQL_UPDATE, текущая строка после операции совпадает с текущей строкой перед операцией.
Игнорировать строку в массовой операции
Массив операций строк можно использовать для указания того, что строка в текущем наборе строк должна игнорироваться во время массовой операции с помощью SQLSetPos. Чтобы направить драйвер, чтобы игнорировать одну или несколько строк во время массовой операции, приложение должно выполнить следующие действия:
Вызовите SQLSetStmtAttr , чтобы задать атрибут инструкции SQL_ATTR_ROW_OPERATION_PTR, чтобы указать массив SQLUSMALLINTs. Это поле также можно задать, вызвав SQLSetDescField , чтобы задать поле заголовка SQL_DESC_ARRAY_STATUS_PTR ARD, которое требует, чтобы приложение получите дескриптор дескриптора.
Задайте каждому элементу массива операций строк одно из двух значений:
SQL_ROW_IGNORE, чтобы указать, что строка исключена для массовой операции.
SQL_ROW_PROCEED, чтобы указать, что строка включена в массовую операцию. (Это значение по умолчанию.)
Вызовите SQLSetPos для выполнения массовой операции.
Следующие правила применяются к массиву операций строк:
SQL_ROW_IGNORE и SQL_ROW_PROCEED влияют только на массовые операции с помощью SQLSetPos с операцией SQL_DELETE или SQL_UPDATE. Они не влияют на вызовы SQLSetPos с операцией SQL_REFRESH или SQL_POSITION.
Указатель по умолчанию имеет значение NULL.
Если указатель имеет значение NULL, все строки обновляются так же, как если бы для всех элементов было задано значение SQL_ROW_PROCEED.
Установка элемента на SQL_ROW_PROCEED не гарантирует, что операция будет выполняться в этой конкретной строке. Например, если определенная строка в наборе строк имеет состояние SQL_ROW_ERROR, драйвер может не сможет обновить такую строку независимо от того, указано ли приложение SQL_ROW_PROCEED. Приложение должно всегда проверять массив состояния строки, чтобы узнать, выполнена ли операция успешно.
SQL_ROW_PROCEED определяется как 0 в файле заголовка. Приложение может инициализировать массив операций строк до 0, чтобы обработать все строки.
Если для выполнения операции массового обновления или удаления в массиве операций строк задано значение SQL_ROW_IGNORE " n", то после вызова вызова SQLSetPos n-строка в наборе строк остается неизменной после вызова SQLSetPos.
Приложение должно автоматически задать для SQL_ROW_IGNORE столбец только для чтения.
Игнорировать столбец в массовой операции
Чтобы избежать ненужных диагностика обработки, созданных путем попыток обновления одного или нескольких столбцов только для чтения, приложение может задать значение в буфере привязанной длины или индикатора для SQL_COLUMN_IGNORE. Дополнительные сведения см. в разделе SQLBindCol.
Пример кода
В следующем примере приложение позволяет пользователю просматривать таблицу ORDERS и обновлять состояние заказа. Курсор управляется набором ключей с размером набора строк 20 и использует элемент управления оптимистичным параллелизмом для сравнения версий строк. После получения каждого набора строк приложение выводит его и позволяет пользователю выбирать и обновлять состояние заказа. Приложение использует SQLSetPos для размещения курсора в выбранной строке и выполняет размещенное обновление строки. (Обработка ошибок опущена для ясности.)
#define ROWS 20
#define STATUS_LEN 6
SQLCHAR szStatus[ROWS][STATUS_LEN], szReply[3];
SQLINTEGER cbStatus[ROWS], cbOrderID;
SQLUSMALLINT rgfRowStatus[ROWS];
SQLUINTEGER sOrderID, crow = ROWS, irow;
SQLHSTMT hstmtS, hstmtU;
SQLSetStmtAttr(hstmtS, SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_ROWVER, 0);
SQLSetStmtAttr(hstmtS, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_KEYSET_DRIVEN, 0);
SQLSetStmtAttr(hstmtS, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) ROWS, 0);
SQLSetStmtAttr(hstmtS, SQL_ATTR_ROW_STATUS_PTR, (SQLPOINTER) rgfRowStatus, 0);
SQLSetCursorName(hstmtS, "C1", SQL_NTS);
SQLExecDirect(hstmtS, "SELECT ORDERID, STATUS FROM ORDERS ", SQL_NTS);
SQLBindCol(hstmtS, 1, SQL_C_ULONG, &sOrderID, 0, &cbOrderID);
SQLBindCol(hstmtS, 2, SQL_C_CHAR, szStatus, STATUS_LEN, &cbStatus);
while ((retcode == SQLFetchScroll(hstmtS, SQL_FETCH_NEXT, 0)) != SQL_ERROR) {
if (retcode == SQL_NO_DATA_FOUND)
break;
for (irow = 0; irow < crow; irow++) {
if (rgfRowStatus[irow] != SQL_ROW_DELETED)
printf("%2d %5d %*s\n", irow+1, sOrderID, NAME_LEN-1, szStatus[irow]);
}
while (TRUE) {
printf("\nRow number to update?");
gets_s(szReply, 3);
irow = atoi(szReply);
if (irow > 0 && irow <= crow) {
printf("\nNew status?");
gets_s(szStatus[irow-1], (ROWS * STATUS_LEN));
SQLSetPos(hstmtS, irow, SQL_POSITION, SQL_LOCK_NO_CHANGE);
SQLPrepare(hstmtU,
"UPDATE ORDERS SET STATUS=? WHERE CURRENT OF C1", SQL_NTS);
SQLBindParameter(hstmtU, 1, SQL_PARAM_INPUT,
SQL_C_CHAR, SQL_CHAR,
STATUS_LEN, 0, szStatus[irow], 0, NULL);
SQLExecute(hstmtU);
} else if (irow == 0) {
break;
}
}
}
Дополнительные примеры см. в разделе "Позиционированные обновления" и "Удаление инструкций " и "Обновление строк" в наборе строк с помощью SQLSetPos.
Связанные функции
Сведения | Смотрите |
---|---|
Привязка буфера к столбцу в результирующем наборе | Функция SQLBindCol |
Выполнение массовых операций, не связанных с положением курсора блока | Функция SQLBulkOperations |
Отмена обработки инструкций | Функция SQLCancel |
Получение блока данных или прокрутка результирующий набор | Функция SQLFetchScroll |
Получение одного поля дескриптора | Функция SQLGetDescField |
Получение нескольких полей дескриптора | Функция SQLGetDescRec |
Задание одного поля дескриптора | Функция SQLSetDescField |
Задание нескольких полей дескриптора | Функция SQLSetDescRec |
Задание атрибута инструкции | Функция SQLSetStmtAttr |