В информатике курсор базы данных — это механизм, который позволяет осуществлять обход записей в базе данных. Курсоры облегчают последующую обработку в сочетании с обходом, такую как извлечение, добавление и удаление записей базы данных. Характерная черта курсора базы данных обхода делает курсоры родственными концепции языка программирования итератора .
Курсоры используются программистами баз данных для обработки отдельных строк, возвращаемых запросами системы базы данных . Курсоры позволяют манипулировать целыми наборами результатов одновременно. В этом сценарии курсор позволяет выполнять последовательную обработку строк в наборе результатов.
В процедурах SQL курсор позволяет определить набор результатов (набор строк данных) и выполнить сложную логику построчно. Используя ту же механику, процедура SQL может также определить набор результатов и вернуть его непосредственно вызывающему объекту процедуры SQL или клиентскому приложению.
Курсор можно рассматривать как указатель на одну строку в наборе строк. Курсор может ссылаться только на одну строку за раз, но может перемещаться на другие строки набора результатов по мере необходимости.
Чтобы использовать курсоры в процедурах SQL, необходимо сделать следующее:
Для работы с курсорами необходимо использовать следующие операторы SQL
В этом разделе описываются способы, которыми стандарт SQL:2003 определяет, как использовать курсоры в приложениях во встроенном SQL. Не все привязки приложений для систем реляционных баз данных придерживаются этого стандарта, а некоторые (например, CLI или JDBC ) используют другой интерфейс.
Программист делает курсор известным СУБД , используя оператор DECLARE
... CURSOR
и присваивая курсору (обязательное) имя:
ОБЪЯВИТЬ cursor_name КУРСОР — ЭТО ВЫБРАТЬ ... ИЗ ...
Прежде чем код сможет получить доступ к данным, он должен открыть курсор с помощью OPEN
оператора. Сразу после успешного открытия курсор располагается перед первой строкой в наборе результатов.
ОТКРЫТЬ имя_курсора
Приложения размещают курсоры на определенной строке в результирующем наборе с помощью FETCH
оператора. Операция выборки передает данные строки в приложение.
ВЫБРАТЬ имя_курсора В ...
После того как приложение обработало все доступные строки или операция выборки должна быть размещена на несуществующей строке (сравните прокручиваемые курсоры ниже), СУБД возвращает SQLSTATE «02000» (обычно сопровождаемое SQLCODE +100), чтобы указать на конец набора результатов.
Последний шаг включает закрытие курсора с помощью CLOSE
оператора:
ЗАКРЫТЬ имя_курсора
После закрытия курсора программа может открыть его снова, что подразумевает, что СУБД повторно оценивает тот же запрос или другой запрос и создает новый набор результатов.
Программисты могут объявлять курсоры прокручиваемыми или не прокручиваемыми. Прокручиваемость указывает направление, в котором может двигаться курсор.
С непрокручиваемым (или только вперед ) курсором вы можете FETCH
каждую строку максимум один раз, и курсор автоматически переместится на следующую строку. После того, как вы извлечете последнюю строку, если вы извлечете снова, вы поместите курсор после последней строки и получите следующий код: SQLSTATE 02000 (SQLCODE +100)
.
Программа может разместить прокручиваемый курсор в любом месте набора результатов с помощью FETCH
оператора SQL. При объявлении курсора необходимо указать ключевое слово SCROLL. Значение по умолчанию — NO SCROLL
, хотя различные языковые привязки, такие как JDBC, могут применять другое значение по умолчанию.
ОБЪЯВИТЬ cursor_name чувствительность ПРОКРУТИТЬ КУРСОР ДЛЯ ВЫБОРА ... ИЗ ...
Целевое положение прокручиваемого курсора может быть указано относительно (от текущего положения курсора) или абсолютно (от начала набора результатов).
ВЫБРАТЬ [СЛЕДУЮЩИЙ | ПРЕДЫДУЩИЙ | ПЕРВЫЙ | ПОСЛЕДНИЙ ] ИЗ cursor_name
ВЫБРАТЬ АБСОЛЮТНОЕ n ИЗ cursor_name
ВЫБРАТЬ ОТНОСИТЕЛЬНЫЙ n ИЗ cursor_name ;
Прокручиваемые курсоры потенциально могут обращаться к одной и той же строке в наборе результатов несколько раз. Таким образом, изменения данных (операции вставки, обновления, удаления) из других транзакций могут повлиять на набор результатов. Курсор может быть ЧУВСТВИТЕЛЬНЫМ или НЕЧУВСТВИТЕЛЬНЫМ к таким изменениям данных. Чувствительный курсор улавливает изменения данных, влияющие на набор результатов курсора, а нечувствительный курсор — нет. Кроме того, курсор может быть НЕЧУВСТВИТЕЛЬНЫМ, и в этом случае СУБД пытается применить чувствительность в максимально возможной степени.
Курсоры обычно автоматически закрываются в конце транзакции, т. е. когда происходит COMMIT или ROLLBACK (или неявное завершение транзакции). Это поведение можно изменить, если курсор объявлен с помощью предложения WITH HOLD (по умолчанию WITHOUT HOLD). Удерживаемый курсор остается открытым при COMMIT и закрывается при ROLLBACK. (Некоторые СУБД отклоняются от этого стандартного поведения и также сохраняют удерживаемые курсоры открытыми при ROLLBACK.)
ОБЪЯВИТЬ cursor_name КУРСОР С УДЕРЖАНИЕМ ДЛЯ ВЫБОРА .... ИЗ ....
Когда происходит COMMIT, удерживаемый курсор позиционируется перед следующей строкой. Таким образом, позиционированный оператор UPDATE или позиционированный оператор DELETE будут успешными только после того, как операция FETCH будет выполнена первой в транзакции.
Обратите внимание, что JDBC определяет курсоры как удерживаемые по умолчанию. Это сделано потому, что JDBC также активирует автоматическую фиксацию по умолчанию.
Курсоры могут использоваться не только для извлечения данных из СУБД в приложение, но и для идентификации строки в таблице, которую необходимо обновить или удалить. Стандарт SQL:2003 определяет для этой цели позиционируемые операторы обновления и удаления SQL. Такие операторы не используют обычное предложение WHERE с предикатами. Вместо этого курсор идентифицирует строку. Курсор должен быть открыт и уже позиционирован на строке с помощью FETCH
оператора.
ОБНОВЛЕНИЕ table_name НАБОР ... ГДЕ ТЕКУЩИЙ ИЗ cursor_name
УДАЛИТЬ ИЗ table_name ГДЕ ТЕКУЩИЙ OF cursor_name
Курсор должен работать с обновляемым результирующим набором для успешного выполнения позиционированного оператора обновления или удаления. В противном случае СУБД не будет знать, как применить изменения данных к базовым таблицам, на которые ссылается курсор.
Использование курсоров в распределенных транзакциях ( средах X/Open XA ), которые контролируются с помощью монитора транзакций, ничем не отличается от курсоров в нераспределенных транзакциях.
Однако при использовании удерживаемых курсоров следует быть внимательным. Соединения могут использоваться разными приложениями. Таким образом, после завершения и фиксации транзакции последующая транзакция (выполняемая в другом приложении) может унаследовать существующие удерживаемые курсоры. Поэтому разработчик приложения должен знать об этой ситуации.
Язык XQuery позволяет создавать курсоры с помощью функции subsequence() .
Формат:
пусть $ displayed-sequence := subsequence ( $ result , $ start , $ item-count )
Где $ result — результат начального запроса XQuery, $start — номер элемента для начала, а $item-count — количество элементов для возврата.
Эквивалентно это можно сделать и с помощью предиката:
пусть $ отображаемая-последовательность := $ результат [ $ начало до $ конец ]
Где $end
конечная последовательность?
Полные примеры см.XQuery/Поиск,Пейджинг и сортировка#Пейджинг в Wikibooks.
Следующая информация может отличаться в зависимости от конкретной системы базы данных.
Извлечение строки из курсора может каждый раз приводить к сетевому циклу . Это использует гораздо большую пропускную способность сети, чем обычно требуется для выполнения одного оператора SQL, например DELETE. Повторные сетевые циклы могут значительно снизить скорость операции с использованием курсора. Некоторые СУБД пытаются уменьшить этот эффект, используя блочную выборку. Блочная выборка подразумевает, что несколько строк отправляются вместе с сервера клиенту. Клиент сохраняет целый блок строк в локальном буфере и извлекает строки оттуда, пока этот буфер не будет исчерпан.
Курсоры выделяют ресурсы на сервере, такие как блокировки , пакеты, процессы и временное хранилище. Например, Microsoft SQL Server реализует курсоры, создавая временную таблицу и заполняя ее набором результатов запроса. Если курсор не закрыт должным образом ( deallocated ), ресурсы не будут освобождены, пока не будет закрыт сам сеанс SQL (соединение). Такая трата ресурсов на сервере может привести к снижению производительности и сбоям.
ТАБЛИЦА СОТРУДНИКОВ
SQL > desc EMPLOYEES_DETAILS ; Имя Null? Тип --------------- -------- ------------ EMPLOYEE_ID NOT NULL NUMBER(6) FIRST_NAME VARCHAR2(20) LAST_NAME NOT NULL VARCHAR2(25) EMAIL NOT NULL VARCHAR2(30) PHONE_NUMBER VARCHAR2(20) HIRE_DATE NOT NULL DATE JOB_ID NOT NULL VARCHAR2(10) SALARY NUMBER(8,2) COMMISSION_PCT NUMBER(2,2) MANAGER_ID NUMBER(6) DEPARTMENT_ID NUMBER(4)
ОБРАЗЕЦ КУРСОРА, ИЗВЕСТНЫЙ КАК EE СОЗДАТЬ ИЛИ ЗАМЕНИТЬ ПРОЦЕДУРУ EE КАК НАЧАТЬ DECLARE v_employeeID EMPLOYEES_DETAILS . EMPLOYEE_ID %TYPE ; v_FirstName EMPLOYEES_DETAILS . FIRST_NAME %TYPE ; v_LASTName EMPLOYEES_DETAILS . LAST_NAME %TYPE ; v_JOB_ID EMPLOYEES_DETAILS . JOB_ID %TYPE := 'IT_PROG' ; Курсор c_EMPLOYEES_DETAILS IS SELECT EMPLOYEE_ID , FIRST_NAME , LAST_NAME FROM EMPLOYEES_DETAILS WHERE JOB_ID = 'v_JOB_ID' ; НАЧАТЬ ОТКРЫТЬ c_EMPLOYEES_DETAILS ; ПЕТЛЯВЫБРАТЬ c_EMPLOYEES_DETAILS В v_employeeID , v_FirstName , v_LASTName ; DBMS_OUTPUT.put_line ( v_employeeID ) ; DBMS_OUTPUT.put_line ( v_FirstName ) ; DBMS_OUTPUT.put_line ( v_LASTName ) ;ВЫХОД , КОГДА c_EMPLOYEES_DETAILS %NOTFOUND ; КОНЕЦ ЦИКЛА ; ЗАКРЫТЬ c_EMPLOYEES_DETAILS ; КОНЕЦ ; КОНЕЦ ;