9
правок
Изменения
Курсоры
,Добавление статьи по теме "Курсоры" для курса "Базы данных".
{{Определение
|definition =
'''Курсор''' — способ перебора результатов запроса, позволяющий достать из результата запроса множество строк.}}
Курсор можно рассматривать как итератор, специфичный для баз данных.
== Объявление курсора ==
=== Синтаксис ===
<font color = blue>declare <font color = red>имя<font color = green> -- объявление курсора с именем </font>
{<font color = black>sensitive<font color = gray>|</font>insensitive<font color = gray>|</font>asensitive</font>}<font color = green> -- чувствительность курсора</font>
[[<font color = black>no</font>] <font color = black>scroll</font>]</font><font color = green> -- возможность ходить произвольным образом по данным вперед и назад (default - no scroll) </font>
cursor select<font color = gray>...</font><font color = green> -- запрос данных, по которым будет ходить курсор</font>
<font color = red>[</font> for <font color = red>{</font>read <font color = black>only</font><font color = gray>|</font>update <font color = red>[</font>of <font color = red>столбцы]}]</font></font><font color = gray>;</font> <font color = green> -- права на чтение(дефолтное право) или на обновление (всей таблицы или выбранных столбцов)</font>
=== Чувствительность курсора ===
Данные из курсора обрабатываются по одной строке, во время таких итераций можно поменять данные самой таблицы, по которой построен текущий курсор. В зависимости от желаемого поведения в таких случаях можно выбрать разную чувствительность курсора.
* <tex>\mathtt{sensitive}</tex> - курсор, чувствительный к изменениям. Измененные данные можно будет увидеть в курсоре, если эти данные еще не были пройдены. Иначе, если изменённые данные были просмотрены в прошлом, то они не обновятся. Итерация по реальным данным.
* <tex>\mathtt{insensitive}</tex> - курсор фиксированных данных. Данные зафиксированы на момент открытия курсора. Никакие изменения данных не будут отображены через курсор. Итерация по временной копии таблицы.
* <tex>\mathtt{asensitive}</tex> - курсор, наиболее предпочтительный для данной СУБД. Связано с различными способами реализациями СУБД: для одних легче реализуем sensitive cursor, а для других - insensitive. В данном случае сама СУБД данных будет решать, какую чувствительность курсора использовать.
Если данные во время использования курсора меняться не будут, то чувствительность курсора не важна.
===Примеры===
Взятие курсора на чтение для студентов, упорядоченных по идентификатору:
<font color = blue>declare <font color = black>SCursor</font> cursor
select <font color = gray>*</font> from <font color = black>Students</font>
order by <font color = black>SId</font><font color = gray>;</font></font>
Взятие курсора с правом на изменение поля SName для студентов группы M3439:
<font color = blue>declare <font color = black>SCursor</font> cursor
select <font color = gray>*</font> from <font color = black>Students</font> where <font color = black>GId</font> <font color = gray>=</font> <font color = green>'M3439'</font>
for update of <font color = black>SName</font><font color = gray>;</font></font>
==Открытие и закрытие==
Объявление курсора говорит о намерении получения данных. Реальная выборка в момент объявления не производится. Она происходит в момент открытия курсора. Если курсор ''insensitive'', то в момент открытия фиксируются данные, которые попадут в курсор.
С курсором ассоциируются ресурсы, поэтому их необходимо закрывать. При выходе из блока, в котором был объявлен курсор, он будет автоматически закрыт. При повторном открытии курсора произойдет повторная инициализация, влекущая новое прочтение данных для ''insensitive'' курсора.
=== Синтаксис ===
<font color = blue>open</font> <font color = red>курсор</font><font color = gray>;</font>
<font color = blue>close</font> <font color = red>курсор</font><font color = gray>;</font>
== Получение данных ==
=== Синтаксис ===
<font color = blue>fetch
<font color = red>[</font>next</font><font color = gray>|</font>prior<font color = gray>|</font>last<font color = gray>|</font>first<font color = gray>|</font>absolute n<font color = gray>|</font>relative n<font color = red>]
курсор</font> <font color = blue>into </font><font color = red>переменные</font><font color = gray>;</font>
==== Описание команд ====
* <tex>\mathtt{next}</tex>next - получение следующей записи (доступно по умолчанию, все команды ниже доступны только для ''scroll'' курсора)
* <tex>\mathtt{prior}</tex> - предыдущая запись
* <tex>\mathtt{last}</tex> - последняя запись
* <tex>\mathtt{first}</tex> - первая запись
* <tex>\mathtt{absolute n}</tex> - получить запись с номером n от начала
* <tex>\mathtt{relative n}</tex> - запись с номером n, нумерация с текущей позиции (n может быть отрицательным, в этом случае движение назад)
=== Отсутствие данных ===
Если данные закончились, либо при помощи команд был осуществлен невалидный переход, то случится событие '''not found'''
=== Пример ===
<font color = blue>fetch </font><font color = black>SCursor <font color = blue>into </font>Sid<font color = gray>,</font> FirstName<font color = gray>,</font> LastName<font color = gray>;</font></font>
Для получения всех данных из курсора, можно создать цикл, предварительно создав обработчик ошибок на '''not found''', в котором выйдем из цикла, когда все элементы будут обработаны.
== Позиционированные изменения ==
Изменение или удаление ровно одной строчки, которую последней выдал курсор.
=== Синтаксис ===
<font color = blue>update <font color = red>таблица</font> set <font color = red>что</font> where current of <font color = red>курсор</font><font color = gray>;</font></font>
<font color = blue>delete from <font color = red>таблица</font> where current of <font color = red>курсор</font><font color = gray>;</font></font>
===Пример применения курсора===
<font color = blue>if <font color = black>FirstName</font> <font color = gray>=</font> <font color = green>'Иван'</font> then
delete from <font color = black>Students</font> where current of <font color = black>SCursor</font><font color = gray>;</font>
end if<font color = gray>;</font>
== Пример применения курсора ==
create procedure <font color = black>updateNameStat<font color = gray>(</font>name<font color = gray>)</font></font>
begin
declare <font color = black>cnt int</font> default <font color = darkgreen>0</font><font color = gray>;</font>
declare exit <font color = black>handler</font> for <font color = black>sqlstate</font> not <font color = black>found</font> begin
insert into <font color = black>Stats <font color = gray>(</font>Name, Cnt<font color = gray>)</font></font> values <font color = black><font color = gray>(</font>name, cnt<font color = gray>)</font><font color = gray>;</font></font>
end<font color = gray>;</font>
declare <font color = black>SCursor</font> cursor
select <font color = black>FirstName</font> from <font color = black>Students</font><font color = gray>;</font>
open <font color = black>SCursor</font><font color = gray>;</font>
loop
declare <font color = black>sname varchar<font color = gray>(</font><font color = darkgreen>20</font><font color = gray>)</font><font color = gray>;</font></font>
fetch <font color = black>SCursor</font> into <font color = black>sname</font><font color = gray>;</font>
if <font color = black>name <font color = gray>=</font> sname</font> then set <font color = black>cnt <font color = gray>=</font> cnt + <font color = darkgreen>1</font></font><font color = gray>;</font> end if<font color = gray>;</font>
end loop<font color = gray>;</font>
end<font color = gray>;</font> </font>
==Особенности курсоров==
Курсоры, описанные в данной статье, являются '''внутренними'''. Они существуют внутри базы данных, используются, в том числе для взаимодействия между различными частями базы данных при планировании.
===Внешние курсоры===
Результат запроса к базе данных может быть слишком велик и стать виной нехватки памяти как на стороне клиента, так и на стороны сервера, увеличить нагрузку на сеть. Поэтому наружу данные выдаются в виде внешнего курсора. После исполнения команды select выдается внешний курсор на данные, аналогично внешний курсор выдается при возврате результат из хранимой процедуры.
===Размер выборки===
Может быть указан для внешнего курсора каким-либо образом (в количестве записей либо в объеме данных).
При выдаче курсора приходит метаинформация о курсоре и первая порция данных, размер которой мы указали. Для получения последующих порций данных необходимо обращаться к серверу. В конце сервер сообщит о том, что данные закончились, автоматически освободит ресурсы.
Возникают альтернативы:
* Малый размер выборки — много повторных обращений.
* Большой размер выборки — требуется много памяти.
Выдача курсора приводит к расходу ресурсов сервера (память, блокировки и так далее). Поэтому внешний курсор стоит закрыть как можно раньше.
|definition =
'''Курсор''' — способ перебора результатов запроса, позволяющий достать из результата запроса множество строк.}}
Курсор можно рассматривать как итератор, специфичный для баз данных.
== Объявление курсора ==
=== Синтаксис ===
<font color = blue>declare <font color = red>имя<font color = green> -- объявление курсора с именем </font>
{<font color = black>sensitive<font color = gray>|</font>insensitive<font color = gray>|</font>asensitive</font>}<font color = green> -- чувствительность курсора</font>
[[<font color = black>no</font>] <font color = black>scroll</font>]</font><font color = green> -- возможность ходить произвольным образом по данным вперед и назад (default - no scroll) </font>
cursor select<font color = gray>...</font><font color = green> -- запрос данных, по которым будет ходить курсор</font>
<font color = red>[</font> for <font color = red>{</font>read <font color = black>only</font><font color = gray>|</font>update <font color = red>[</font>of <font color = red>столбцы]}]</font></font><font color = gray>;</font> <font color = green> -- права на чтение(дефолтное право) или на обновление (всей таблицы или выбранных столбцов)</font>
=== Чувствительность курсора ===
Данные из курсора обрабатываются по одной строке, во время таких итераций можно поменять данные самой таблицы, по которой построен текущий курсор. В зависимости от желаемого поведения в таких случаях можно выбрать разную чувствительность курсора.
* <tex>\mathtt{sensitive}</tex> - курсор, чувствительный к изменениям. Измененные данные можно будет увидеть в курсоре, если эти данные еще не были пройдены. Иначе, если изменённые данные были просмотрены в прошлом, то они не обновятся. Итерация по реальным данным.
* <tex>\mathtt{insensitive}</tex> - курсор фиксированных данных. Данные зафиксированы на момент открытия курсора. Никакие изменения данных не будут отображены через курсор. Итерация по временной копии таблицы.
* <tex>\mathtt{asensitive}</tex> - курсор, наиболее предпочтительный для данной СУБД. Связано с различными способами реализациями СУБД: для одних легче реализуем sensitive cursor, а для других - insensitive. В данном случае сама СУБД данных будет решать, какую чувствительность курсора использовать.
Если данные во время использования курсора меняться не будут, то чувствительность курсора не важна.
===Примеры===
Взятие курсора на чтение для студентов, упорядоченных по идентификатору:
<font color = blue>declare <font color = black>SCursor</font> cursor
select <font color = gray>*</font> from <font color = black>Students</font>
order by <font color = black>SId</font><font color = gray>;</font></font>
Взятие курсора с правом на изменение поля SName для студентов группы M3439:
<font color = blue>declare <font color = black>SCursor</font> cursor
select <font color = gray>*</font> from <font color = black>Students</font> where <font color = black>GId</font> <font color = gray>=</font> <font color = green>'M3439'</font>
for update of <font color = black>SName</font><font color = gray>;</font></font>
==Открытие и закрытие==
Объявление курсора говорит о намерении получения данных. Реальная выборка в момент объявления не производится. Она происходит в момент открытия курсора. Если курсор ''insensitive'', то в момент открытия фиксируются данные, которые попадут в курсор.
С курсором ассоциируются ресурсы, поэтому их необходимо закрывать. При выходе из блока, в котором был объявлен курсор, он будет автоматически закрыт. При повторном открытии курсора произойдет повторная инициализация, влекущая новое прочтение данных для ''insensitive'' курсора.
=== Синтаксис ===
<font color = blue>open</font> <font color = red>курсор</font><font color = gray>;</font>
<font color = blue>close</font> <font color = red>курсор</font><font color = gray>;</font>
== Получение данных ==
=== Синтаксис ===
<font color = blue>fetch
<font color = red>[</font>next</font><font color = gray>|</font>prior<font color = gray>|</font>last<font color = gray>|</font>first<font color = gray>|</font>absolute n<font color = gray>|</font>relative n<font color = red>]
курсор</font> <font color = blue>into </font><font color = red>переменные</font><font color = gray>;</font>
==== Описание команд ====
* <tex>\mathtt{next}</tex>next - получение следующей записи (доступно по умолчанию, все команды ниже доступны только для ''scroll'' курсора)
* <tex>\mathtt{prior}</tex> - предыдущая запись
* <tex>\mathtt{last}</tex> - последняя запись
* <tex>\mathtt{first}</tex> - первая запись
* <tex>\mathtt{absolute n}</tex> - получить запись с номером n от начала
* <tex>\mathtt{relative n}</tex> - запись с номером n, нумерация с текущей позиции (n может быть отрицательным, в этом случае движение назад)
=== Отсутствие данных ===
Если данные закончились, либо при помощи команд был осуществлен невалидный переход, то случится событие '''not found'''
=== Пример ===
<font color = blue>fetch </font><font color = black>SCursor <font color = blue>into </font>Sid<font color = gray>,</font> FirstName<font color = gray>,</font> LastName<font color = gray>;</font></font>
Для получения всех данных из курсора, можно создать цикл, предварительно создав обработчик ошибок на '''not found''', в котором выйдем из цикла, когда все элементы будут обработаны.
== Позиционированные изменения ==
Изменение или удаление ровно одной строчки, которую последней выдал курсор.
=== Синтаксис ===
<font color = blue>update <font color = red>таблица</font> set <font color = red>что</font> where current of <font color = red>курсор</font><font color = gray>;</font></font>
<font color = blue>delete from <font color = red>таблица</font> where current of <font color = red>курсор</font><font color = gray>;</font></font>
===Пример применения курсора===
<font color = blue>if <font color = black>FirstName</font> <font color = gray>=</font> <font color = green>'Иван'</font> then
delete from <font color = black>Students</font> where current of <font color = black>SCursor</font><font color = gray>;</font>
end if<font color = gray>;</font>
== Пример применения курсора ==
create procedure <font color = black>updateNameStat<font color = gray>(</font>name<font color = gray>)</font></font>
begin
declare <font color = black>cnt int</font> default <font color = darkgreen>0</font><font color = gray>;</font>
declare exit <font color = black>handler</font> for <font color = black>sqlstate</font> not <font color = black>found</font> begin
insert into <font color = black>Stats <font color = gray>(</font>Name, Cnt<font color = gray>)</font></font> values <font color = black><font color = gray>(</font>name, cnt<font color = gray>)</font><font color = gray>;</font></font>
end<font color = gray>;</font>
declare <font color = black>SCursor</font> cursor
select <font color = black>FirstName</font> from <font color = black>Students</font><font color = gray>;</font>
open <font color = black>SCursor</font><font color = gray>;</font>
loop
declare <font color = black>sname varchar<font color = gray>(</font><font color = darkgreen>20</font><font color = gray>)</font><font color = gray>;</font></font>
fetch <font color = black>SCursor</font> into <font color = black>sname</font><font color = gray>;</font>
if <font color = black>name <font color = gray>=</font> sname</font> then set <font color = black>cnt <font color = gray>=</font> cnt + <font color = darkgreen>1</font></font><font color = gray>;</font> end if<font color = gray>;</font>
end loop<font color = gray>;</font>
end<font color = gray>;</font> </font>
==Особенности курсоров==
Курсоры, описанные в данной статье, являются '''внутренними'''. Они существуют внутри базы данных, используются, в том числе для взаимодействия между различными частями базы данных при планировании.
===Внешние курсоры===
Результат запроса к базе данных может быть слишком велик и стать виной нехватки памяти как на стороне клиента, так и на стороны сервера, увеличить нагрузку на сеть. Поэтому наружу данные выдаются в виде внешнего курсора. После исполнения команды select выдается внешний курсор на данные, аналогично внешний курсор выдается при возврате результат из хранимой процедуры.
===Размер выборки===
Может быть указан для внешнего курсора каким-либо образом (в количестве записей либо в объеме данных).
При выдаче курсора приходит метаинформация о курсоре и первая порция данных, размер которой мы указали. Для получения последующих порций данных необходимо обращаться к серверу. В конце сервер сообщит о том, что данные закончились, автоматически освободит ресурсы.
Возникают альтернативы:
* Малый размер выборки — много повторных обращений.
* Большой размер выборки — требуется много памяти.
Выдача курсора приводит к расходу ресурсов сервера (память, блокировки и так далее). Поэтому внешний курсор стоит закрыть как можно раньше.