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


Основные сведения о типах курсоров

Скачать драйвер JDBC

Операции в реляционной базе данных выполняются над множеством строк. Набор строк, возвращаемый инструкцией SELECT, содержит все строки, которые удовлетворяют условиям, указанным в предложении WHERE инструкции. Такой полный набор строк, возвращаемых инструкцией, называется результирующим набором. Приложения не всегда могут эффективно работать с результирующим набором, представляющим единое целое. Им нужен способ, позволяющий обрабатывать одну строку или небольшое их число за один раз. Курсоры являются расширением результирующих наборов, которые предоставляют такой механизм.

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

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

Примечание

Полное описание типов курсоров SQL Server см. в разделе Типы курсоров.

Спецификация JDBC обеспечивает поддержку однопроходных курсоров и прокручиваемых курсоров, которые могут учитывать или не учитывать изменения, выполненные другими заданиями, а также быть доступными только для чтения или допускать обновление. Эта функциональность обеспечивается классом Microsoft JDBC Driver для SQL ServerSQLServerResultSet.

Remarks

Драйвер JDBC поддерживает следующие типы результирующих наборов и курсоров вместе с заданными параметрами поведения.

Тип результирующего набора (курсора) Тип курсора SQL Server Характеристики Выбор метода Режим буферизации
TYPE_FORWARD_ONLY (CONCUR_READ_ONLY) Н/Д Однонаправленный, только для чтения direct переполненные

Приложение выполняет один (однонаправленный) проход по результирующему набору. Такой проход — это поведение по умолчанию, аналогичное поведению курсора TYPE_SS_DIRECT_FORWARD_ONLY. Драйвер считывает весь результирующий набор с сервера в память во время выполнения инструкции.

Тип результирующего набора (курсора) Тип курсора SQL Server Характеристики Выбор метода Режим буферизации
TYPE_FORWARD_ONLY (CONCUR_READ_ONLY) Н/Д Однонаправленный, только для чтения direct adaptive

Приложение выполняет один (однонаправленный) проход по результирующему набору. Работает аналогично курсору TYPE_SS_DIRECT_FORWARD_ONLY. Драйвер считывает строки с сервера по мере того как приложение запрашивает строки, что позволяет снизить загрузку памяти на стороне клиента.

Тип результирующего набора (курсора) Тип курсора SQL Server Характеристики Выбор метода Режим буферизации
TYPE_FORWARD_ONLY (CONCUR_READ_ONLY) Быстрый однопроходный Однонаправленный, только для чтения курсор Н/Д

Приложение должно выполнить один (однонаправленный) проход по результирующему набору, используя серверный курсор. Работает аналогично курсору TYPE_SS_SERVER_CURSOR_FORWARD_ONLY.

Строки извлекаются с сервера блоками, размер которых определяется размером выборки.

Тип результирующего набора (курсора) Тип курсора SQL Server Характеристики Выбор метода Режим буферизации
TYPE_FORWARD_ONLY (CONCUR_UPDATABLE) Динамический (однопроходный) Однопроходный, обновляемый Недоступно Н/Д

Приложение должно выполнить один (однонаправленный) проход по результирующему набору, чтобы обновить одну или несколько строк.

Строки извлекаются с сервера блоками, размер которых определяется размером выборки.

По умолчанию размер выборки фиксируется, когда приложение вызывает метод setFetchSize объекта SQLServerResultSet.

Примечание

Драйвер JDBC предоставляет функцию адаптивной буферизации, которая позволяет получать результаты выполнения инструкций от SQL Server по запросу приложения, а не все сразу. Например, если приложение должно получить данные, которые не могут полностью разместиться в памяти приложения, адаптивная буферизация позволяет клиентскому приложению получать значения в виде потока. По умолчанию в драйвере применяется режим "adaptive". Однако, чтобы включить адаптивную буферизацию для однопроходных обновляемых результирующих наборов, приложение должно явно вызвать метод setResponseBuffering объекта SQLServerStatement, предоставив значение типа String ("adaptive"). Пример кода можно найти в статье Пример обновления большого объема данных.

Тип результирующего набора (курсора) Тип курсора SQL Server Характеристики Выбор метода Режим буферизации
TYPE_SCROLL_INSENSITIVE Статические Прокручиваемый, без поддержки обновления.

Внешние операции обновления, вставки и удаления строк невидимы.
Недоступно Н/Д

Приложению требуется моментальный снимок базы данных. Результирующий набор не поддерживает обновление. Поддерживается только CONCUR_READ_ONLY. Все остальные типы параллелизмы в случае использования с этим типом курсора вызывают исключение.

Строки извлекаются с сервера блоками, размер которых определяется размером выборки.

Тип результирующего набора (курсора) Тип курсора SQL Server Характеристики Выбор метода Режим буферизации
TYPE_SCROLL_SENSITIVE (CONCUR_READ_ONLY) Keyset Прокручиваемый, только для чтения. Внешние обновления строки являются видимыми, а операции удаления отображаются как отсутствующие данные.

Внешние операции вставки строк невидимы.
Недоступно Н/Д

Приложению должны быть видимы только измененные данные для существующих строк.

Строки извлекаются с сервера блоками, размер которых определяется размером выборки.

Тип результирующего набора (курсора) Тип курсора SQL Server Характеристики Выбор метода Режим буферизации
TYPE_SCROLL_SENSITIVE (CONCUR_UPDATABLE, CONCUR_SS_SCROLL_LOCKS, CONCUR_SS_OPTIMISTIC_CC, CONCUR_SS_OPTIMISTIC_CCVAL) Keyset Прокручиваемый, обновляемый.

Внешние и внутренние операции обновления строк являются видимыми, а операции удаления отображаются как отсутствующие данные. Операции вставки невидимы.
Недоступно Н/Д

Приложение может изменять данные в существующих строках с помощью объекта ResultSet. Приложению также должны быть видимы изменения в строках, выполненные другими пользователями вне объекта ResultSet.

Строки извлекаются с сервера блоками, размер которых определяется размером выборки.

Тип результирующего набора (курсора) Тип курсора SQL Server Характеристики Выбор метода Режим буферизации
TYPE_SS_DIRECT_FORWARD_ONLY Н/Д Однонаправленный, только для чтения Н/Д Полная или адаптивная

Целое значение = 2003. Предоставляет клиентский курсор только для чтения с полной буферизацией. Серверный курсор не создается.

Поддерживается только тип параллелизма CONCUR_READ_ONLY. Все остальные типы параллелизмы в случае использования с этим типом курсора вызывают исключение.

Тип результирующего набора (курсора) Тип курсора SQL Server Характеристики Выбор метода Режим буферизации
TYPE_SS_SERVER_CURSOR_FORWARD_ONLY Быстрый однопроходный Однонаправленный Недоступно Н/Д

Целое значение = 2004. Быстрый режим, доступ ко всем данным осуществляется с помощью серверного курсора. В случае использования с типом параллелизма CONCUR_UPDATABLE возможно обновление.

Строки извлекаются с сервера блоками, размер которых определяется размером выборки.

Чтобы включить адаптивную буферизацию в этом случае, приложение должно явно вызвать метод setResponseBuffering объекта SQLServerStatement, указав значение типа String ("adaptive" ). Пример кода можно найти в статье Пример обновления большого объема данных.

Тип результирующего набора (курсора) Тип курсора SQL Server Характеристики Выбор метода Режим буферизации
TYPE_SS_SCROLL_STATIC Статические Не отражает обновления, выполненные другими пользователями. Недоступно Н/Д

Целое значение = 1004. Приложению требуется моментальный снимок базы данных. Это синоним SQL Server для типа JDBC TYPE_SCROLL_INSENSITIVE, который имеет те же параметры параллелизма по умолчанию.

Строки извлекаются с сервера блоками, размер которых определяется размером выборки.

Тип результирующего набора (курсора) Тип курсора SQL Server Характеристики Выбор метода Режим буферизации
TYPE_SS_SCROLL_KEYSET (CONCUR_READ_ONLY) Keyset Прокручиваемый, только для чтения. Внешние обновления строки являются видимыми, а операции удаления отображаются как отсутствующие данные.

Внешние операции вставки строк невидимы.
Недоступно Н/Д

Целое значение = 1005. Приложению должны быть видимы только измененные данные для существующих строк. Это синоним SQL Server для типа JDBC TYPE_SCROLL_SENSITIVE, который имеет те же параметры параллелизма по умолчанию.

Строки извлекаются с сервера блоками, размер которых определяется размером выборки.

Тип результирующего набора (курсора) Тип курсора SQL Server Характеристики Выбор метода Режим буферизации
TYPE_SS_SCROLL_KEYSET (CONCUR_UPDATABLE, CONCUR_SS_SCROLL_LOCKS, CONCUR_SS_OPTIMISTIC_CC, CONCUR_SS_OPTIMISTIC_CCVAL) Keyset Прокручиваемый, обновляемый.

Внешние и внутренние операции обновления строк являются видимыми, а операции удаления отображаются как отсутствующие данные. Операции вставки невидимы.
Недоступно Н/Д

Целое значение = 1005. Приложение должно изменять данные, или для него должны быть видимыми измененные данные для существующих строк. Это синоним SQL Server для типа JDBC TYPE_SCROLL_SENSITIVE, который имеет те же параметры параллелизма по умолчанию.

Строки извлекаются с сервера блоками, размер которых определяется размером выборки.

Тип результирующего набора (курсора) Тип курсора SQL Server Характеристики Выбор метода Режим буферизации
TYPE_SS_SCROLL_DYNAMIC (CONCUR_READ_ONLY) Динамический Прокручиваемый, только для чтения.

Внешние операции обновления и вставки строк являются видимыми, а операции удаления представляются как временно отсутствующие данные в текущем буфере выборки.
Недоступно Н/Д

Целое значение = 1006. Приложению должны быть видимы измененные данные для существующих строк, а также вставленные и обновленные строки за время существования курсора.

Строки извлекаются с сервера блоками, размер которых определяется размером выборки.

Тип результирующего набора (курсора) Тип курсора SQL Server Характеристики Выбор метода Режим буферизации
TYPE_SS_SCROLL_DYNAMIC (CONCUR_UPDATABLE, CONCUR_SS_SCROLL_LOCKS, CONCUR_SS_OPTIMISTIC_CC, CONCUR_SS_OPTIMISTIC_CCVAL) Динамический Прокручиваемый, обновляемый.

Внешние и внутренние операции обновления и вставки строк являются видимыми, а операции удаления представляются как временно отсутствующие данные в текущем буфере выборки.
Недоступно Н/Д

Целое значение = 1006. Приложение может изменять данные для существующих строк, а также вставлять и удалять строки с помощью объекта ResultSet. Приложению также должны быть видимы изменения в строках, операции вставки и удаления, выполненные другими пользователями вне объекта ResultSet.

Строки извлекаются с сервера блоками, размер которых определяется размером выборки.

Позиционирование курсоров

Курсоры TYPE_FORWARD_ONLY, TYPE_SS_DIRECT_FORWARD_ONLY и TYPE_SS_SERVER_CURSOR_FORWARD_ONLY поддерживают только метод позиционирования next.

Курсор TYPE_SS_SCROLL_DYNAMIC не поддерживает методы absolute и getRow. Действие метода absolute можно приблизительно заменить сочетанием вызова методов first и relative для динамических курсоров.

Метод getRow поддерживается только курсорами TYPE_FORWARD_ONLY, TYPE_SS_DIRECT_FORWARD_ONLY, TYPE_SS_SERVER_CURSOR_FORWARD_ONLY, TYPE_SS_SCROLL_KEYSET и TYPE_SS_SCROLL_STATIC. Метод getRow для всех типов однопроходных курсоров возвращает количество строк, считанных в курсоре на данный момент.

Примечание

Если приложение выполняет неподдерживаемый вызов позиционирования курсора или неподдерживаемый вызов метода getRow, возникает исключение с сообщением "Запрошенная операция не поддерживается с этим типом курсора".

Доступ к удаленным строкам предоставляется только курсорами TYPE_SS_SCROLL_KEYSET и эквивалентными курсорами TYPE_SCROLL_SENSITIVE. Если курсор позиционируется в удаленной строке, то значения столбцов недоступны, а метод rowDeleted возвращает значение True. Вызовы метода get<Type> приводят к созданию исключения с сообщением "Не удается получить значение из удаленной строки". Удаленные строки нельзя обновлять. Если вызвать метод update<Type> для удаленной строки, создается исключение с сообщением "Не удается обновить удаленную строку". Курсор TYPE_SS_SCROLL_DYNAMIC работает аналогичным образом, пока не выходит за пределы текущего буфера выборки.

Однопроходные и динамические курсоры предоставляют доступ к удаленным строкам аналогичным образом, но только при условии, что курсоры остаются доступными в буфере выборки. Для однопроходных курсоров такое поведение реализуется довольно просто. Для динамических курсоров ситуация усложняется в случае, когда размер выборки превышает 1. Приложение может перемещать курсор в обоих направлениях в пределах окна, заданного буфером выборки, однако удаленная строка будет исчезать, когда курсор будет покидать исходный буфер выборки, в котором была обновлена строка. Если временно удаленные строки не должны отображаться приложению, использующему динамические курсоры, следует использовать относительную выборку (0).

Если значения ключа для строки курсора TYPE_SS_SCROLL_KEYSET или TYPE_SCROLL_SENSITIVE обновляются с помощью курсора, то строка сохраняет исходную позицию в результирующем наборе независимо от того, отвечает ли обновленная строка условиям выборки курсора. Если строка обновляется вне курсора, то удаленная строка будет выводиться в исходной позиции строки, однако будет видна в курсоре только в том случае, если там ранее присутствовала другая строка с новыми значениями ключа, но затем была удалена.

Для динамических курсоров обновленные строки будут сохранять свои позиции в буфере выборки, пока курсор не покинет окно, определенное буфером выборки. Обновленные строки могут позже появляться в других позициях в результирующем наборе или полностью исчезать. Приложения, которые должны избегать временной потери согласованности в результирующем наборе, должны использовать размер выборки 1 (по умолчанию используется 8 строк для параллелизма CONCUR_SS_SCROLL_LOCKS и 128 строк для остальных режимов параллелизма).

Преобразование курсоров

Иногда SQL Server может реализовать тип курсора, отличный от запрошенного. Это называется неявным преобразованием курсора (или ухудшением курсора).

В SQL Server 2000 (8.x) при обновлении данных с использованием результирующего набора с параметрами ResultSet.TYPE_SCROLL_SENSITIVE и ResultSet.CONCUR_UPDATABLE создается исключение с сообщением "Этот курсор имеет тип READ ONLY". Это исключение создается, так как SQL Server 2000 (8.x) выполнил неявное преобразование курсора для этого результирующего набора и не вернул запрошенный обновляемый курсор.

Существует два возможных решения этой проблемы.

  • Убедитесь, что базовая таблица содержит первичный ключ.
  • Для создания инструкции используйте SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC вместо ResultSet.TYPE_SCROLL_SENSITIVE.

Обновление курсоров

Обновления на месте поддерживаются для курсоров, если тип курсора и тип параллелизма поддерживают обновления. Если курсор не размещен в обновляемой строке в результирующем наборе (не удалось вызвать метод get<Type>), вызов метода update<Type> вызовет исключение с сообщением "В результирующем наборе отсутствует текущая строка". Спецификация JDBC указывает, что исключение возникает при вызове метода update для столбца курсора CONCUR_READ_ONLY. В ситуациях, когда строка недоступна для обновления, например из-за конфликта оптимистичного параллелизма в случае конкурирующих операций обновления или удаления, исключение может не создаваться до вызова метода insertRow, updateRow или deleteRow.

После вызова метода update<Type> доступ к столбцу с помощью get<Type> будет невозможен до вызова updateRow или cancelRowUpdates. Такое поведение позволяет избежать проблем, когда столбец обновляется с использованием типа, который отличается от типа, возвращаемого сервером, а последующие вызовы метода считывания могут привести к преобразованиям типа на клиентской стороне, которые дают неточные результаты. Вызовы get<Type> создают исключение с сообщением "Доступ к обновляемым столбцам невозможен до вызова метода updateRow() или cancelRowUpdates()".

Примечание

Если метод updateRow вызван, когда столбцы не обновлены, драйвер JDBC вызывает исключение с сообщением "Метод updateRow() вызван, когда столбцы не обновлены".

После вызова метода moveToInsertRow исключение будет создаваться в случае вызова для результирующего набора любого метода, кроме методов get<Type>, update<Type>, insertRow и методов позиционирования курсора (включая moveToCurrentRow). Метод moveToInsertRow фактически переводит результирующий набор в режим вставки, а методы позиционирования курсора отменяют режим вставки. Вызовы относительного позиционирования курсора перемещают курсор относительно позиции, в которой он находился перед вызовом moveToInsertRow. После вызова позиционирования курсора ожидаемая позиция назначения становится новой позицией курсора.

Если вызов позиционирования курсора, выполненный в режиме вставки, не завершается успешно, то позицией курсора после сбоя вызова будет исходная позиция курсора до вызова метода moveToInsetRow. Если метод insertRow завершается сбоем, то курсор остается в строке вставки в режиме вставки.

Столбцы в строке вставке первоначально находятся в неинициализированном состоянии. Вызовы метода update<Type> устанавливают инициализированное состояние столбца. Вызов метода get<Type> для неинициализированного столбца приводит к созданию исключения. Вызов метода insertRow возвращает все столбцы в строке вставки в неинициализированное состояние.

Если в момент вызова метода insertRow какие-либо столбцы не инициализированы, то вставляется значение по умолчанию для столбца. Если значение по умолчанию отсутствует, но столбец допускает значение NULL, то вставляется значение NULL. Если отсутствует значение по умолчанию, и столбец не допускает значения NULL, то сервер возвращает ошибку, и создается исключение.

Примечание

Вызовы метода getRow в режиме вставки возвращают значение 0.

Драйвер JDBC не поддерживает позиционированные операции обновления и удаления. В соответствии со спецификацией JDBC метод setCursorName не имеет эффекта, и в случае вызова метода getCursorName создается исключение.

Статические курсоры и курсоры, доступные только для чтения, никогда не поддерживают обновление.

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

См. также раздел

Управление результирующими наборами с помощью JDBC Driver