Ковалев Язык баз данных SQL
.pdf11. Курсоры
Курсор (current set of records – текущий набор записей) представляет собой объект, позво- ляющий осуществить работу с отдельными строками результирующего запроса.
Использование курсора связано со следующими шагами:
1)declare – объявление курсора,
2)open – открытие курсора,
3)fetch, update, delete – работа с курсором,
4)close – закрытие курсора,
5)deallocate – освобождение курсора.
11.1Объявление курсора
Оператор объявления курсора применительно к его имени имеет следующий вид:
|
|
|
описание курсо- |
ра |
|
|
|
|
|
|
|
declare имя_курсора cursor |
|
[видимость] |
::= [local | global] |
[прокрутка] |
::= [forward_only | scroll] |
[тип] |
::= [static | keyset | dynamic | fast_forward] |
[блокировка] |
::= [read_only | scroll_locks | optimistic] |
|
|
[type_warning] for оператор_select
[for update [of имя_столбца ,..]]
Видимость курсора определяется с помощью ключевых слов local или global, имеющих тот же смысл, что и для временных таблиц.
Параметр прокрутка может принимать одно из значений
1)forward_only – последовательный курсор,
2)scroll – прокручиваемый в обоих направлениях.
Курсор типа static – это статический курсор. Статический курсор делает как бы моментальный снимок данных, задаваемых оператором select, и хранит их в системной базе данных tempdb. Он не чувствует изменений в структуре или в значениях данных таблиц, на которых базируется оператор select. Любые модификации статического курсора отражаются лишь в копии, а не в исходных таблицах. Поэтому он всегда открывается в режиме только для чтения.
Курсор типа keyset – это ключевой курсор. Ключевой курсор копирует в базу tempdb только те столбцы, которые уникально идентифицируют каждую строку результирующего запроса по оператору select. Чтобы иметь возможность объявить ключевой курсор, каждая таблица, вхо- дящая в определение оператора select, должна иметь ключ. Ключевые курсоры могут быть как модифицируемыми, так и только для чтения. Они также могут быть прокручиваемыми или по- следовательными. Членство строк в ключевом курсоре фиксируется на момент объявления кур- сора. Даже если строка удаляется, она по-прежнему остается в курсоре, но SQL Server возвра- щает null-значения для всех столбцов. Изменения значений данных, вносимые в исходные таб- лицы, отражаются в курсоре. Однако изменения значений ключей отражаются в курсоре только в том случае, когда они осуществляются в курсоре, а не в исходных таблицах.
Курсор типа dynamic – это динамический курсор. Динамический курсор ведет себя так, как ес- ли бы при каждом обращении к строке повторно выполнялся оператор select. Динамические
Спецкурс 3 (2010-2011. 5 курс, 9 сем. ПИЭ), 40 с. |
31 |
курсоры отражают изменения, связанные как с членством, так и со значениями исходных дан- ных, независимо от того, сделаны ли эти изменения в курсоре или в исходных таблицах.
Курсор типа fast_forward – это «пожарный» курсор, т.е. курсор быстрого доступа. Пожарный курсор является специальной оптимизированной формой последовательного курсора для чте- ния.
Параметр блокировки может принимать значения
1)read_only – курсор не может вносить никаких изменений в исходные таблицы. Тем не менее, исходные таблицы можно модифицировать с помощью оператора update.
2)scroll_locks – обновления могут быть выполнены только курсором. Другие операторы update выполняться не будут.
3)optimistic – обновления могут быть выполнены как курсором, так и операторами update.
SQL Server автоматически преобразует тип курсора, если объявленный тип курсора не поддер- живается заданным оператором select. При заданной опции type_warning при таком преобразо- вании SQL Server будет посылать предупреждающие сообщения клиенту.
Фраза for update позволяет явно разрешить обновление курсора, а также явно указать столбцы, допускающие обновление.
11.2 Курсорные переменные
Transact-SQL позволяет объявлять курсорные переменные.
Синтаксис объявления может иметь одну из 2х следующих форм.
declare имя_курсора cursor
Форма 1
описание_курсора
declare @имя_переменной cursor set @имя_переменной = имя_курсора
declare @имя_переменной cursor
Форма 2 set @имя_переменной cursor описание_курсора
Форма 1 полезна для создания переменных, которые могут быть назначены различным курсо- рам. Это может потребоваться для создания обобщенных процедур, предназначенных для рабо- ты с различными результирующими запросами.
Объявление курсора в форме 2 не задает его имени и, следовательно, ссылка на курсор может быть осуществлена только через переменную.
11.3 Открытие курсора
Объявление курсора создает объект курсора, но не создает набор записей, которыми курсор бу- дет манипулировать. Сам набор записей курсора создается при открытии курсора с помощью следующего оператора
open [global] имя_или_переменная_курсора
Спецкурс 3 (2010-2011. 5 курс, 9 сем. ПИЭ), 40 с. |
32 |
Ключевое слово global помогает избежать конфликтов имен. А именно, если локальный и гло- бальный курсоры имеют одинаковые имена, то ссылки на курсор будут по умолчанию отнесены к локальному курсору. Поэтому, как и в других подобных случаях, лучше явно указывать клю- чевое слово global, если работа идет с глобальным курсором.
11.4 Закрытие курсора
После использования курсора его необходимо закрыть. Оператор закрытия close освобождает ресурсы, используемые для обслуживания набора записей курсора, а также освобождает блоки- ровки, наложенные на строки.
Синтаксис оператора закрытия курсора:
close [global] имя_или_переменная_курсора
11.5 Освобождение курсора
Последним оператором в последовательности действий по использованию курсора является его освобождение:
deallocate [global] имя_или_переменная_курсора
Однако оператор deallocate удаляет имя или переменную курсора, на не обязательно сам кур- сор. Сам курсор не удаляется до тех пор, пока все ссылающиеся на него имена или переменные не будут удалены.
Рассмотрим пример:
declare curName cursor
описание_курсора open curName
...
declare @curVariable cursor set @curVariable = curName
...
close curName deallocate curName
После освобождения курсора идентификатор curName больше не ассоциируется с набором за- писей курсора. Но поскольку на набор записей курсора еще ссылается переменная @carVariable, то курсор и его набор записей фактически не освобождаются. Если явно не осво- бодить также и курсорную переменную, то курсор будет существовать вплоть до выхода из процедуры, когда курсорная переменная будет неявно освобождена.
11.6 Оператор fetch
Оператор fetch позволяет выбирать строки курсора и записывать их в переменные:
fetch {first | last | next | prior | absolute n | relative n}
Спецкурс 3 (2010-2011. 5 курс, 9 сем. ПИЭ), 40 с. |
33 |
from имя_или_переменная_курсора into @имя_переменной ,..
Оператор fetch absolute n выбирает строку, отстоящую на n строк от начала, если n > 0, или от конца, если n < 0. Оператор fetch relative n выбирает строку, отстоящую на n строк от текущей вперед или назад при n > 0, n < 0 соответственно. Значением n может быть константа или пере- менная.
Список имен переменных должен содержать переменную для каждого столбца курсора. Тип данных переменной должен либо совпадать, либо быть совместимым с типом данных столбца.
Глобальная переменная @@fetch_status содержит информацию о выполнении последнего опе- ратора fetch:
@@fetch_status |
Описание |
0 |
Оператор fetch выполнен успешно |
-1 |
Оператор fetch выполнен неудачно |
-2 |
Выбираемая строка отсутствует |
11.7 Обновление и удаление строк через курсоры
Оператор обновления строки через курсор имеет следующий вид:
update имя_таблицы
set {имя_столбца = новое_значение} ,..
where current of имя_или_переменная_курсора
Это называется позиционным обновлением.
Transact-SQL поддерживает также позиционное удаление:
delete имя_таблицы
where current of имя_или_переменная_курсора
Спецкурс 3 (2010-2011. 5 курс, 9 сем. ПИЭ), 40 с. |
34 |
ПРИЛОЖЕНИЕ
Таблицы |
|
|
|
|
create table |
имя_таблицы |
|
||
( |
|
|
|
|
{ |
имя_столбца |
тип_данных [ null | not null ] |
||
|
[ |
default константное_выражение |
||
|
| |
identity (начальное_значение, шаг_приращения) |
||
|
] |
constraint имя_ограничения |
||
|
[ |
|||
|
|
{ |
primary key [ clustered | nonclustered ] |
|
|
|
| |
unique |
[ clustered | nonclustered ] |
|
|
| |
foreign key references ссылочная_таблица(имя_столбеца) |
|
|
|
|
|
[ on update [ cascade | no action ] ] |
|
|
|
|
[ on delete [ cascade | no action ] ] |
|
|
| |
check (проверочное_ограничение_для_столбца) |
|
|
|
} |
|
|
|
] ,.. |
|
|
|
} ,..
[ , имя_столбца as выражение_вычисляемого_столбца ] … [ , constraint имя_ограничения
{primary key [ clustered | nonclustered ] ({ имя_столбца [asc | desc] } ,..)
| |
unique |
[ clustered | nonclustered ] ({ имя_столбца [asc | desc] } ,..) |
|
| |
foreign key (имя_столбца ,..) references ссылочная_таблица (имя_столбеца ,..) |
||
|
|
[on update |
[ cascade | no action ]] |
|
|
[on delete |
[ cascade | no action ]] |
| |
check (проверочное_ограничение_для_строки) |
||
} |
|
|
|
] ...
)
Индексы
create [unique] { clustered | nonclustered } index имя_индекса
on имя_таблицы ({имя_столбца [asc | desc ]} ,..)
Вставка строк
insert into имя_таблицы [(имя_столбца ,..)] Форма 1 оператор_select
Форма 2
insert into имя_таблицы [(имя_столбца ,..)] values({ default | null | выражение } ,..)
Форма 3
insert into имя_таблицы default values
Спецкурс 3 (2010-2011. 5 курс, 9 сем. ПИЭ), 40 с. |
35 |
Обновление строк
update имя_таблицы
set {имя_столбца = новое_значение} ,.. [from табличный_источник ,..]
[where условие_поиска]
Удаление строк
delete имя_таблицы
[from табличный_источник ,..] [where условие_поиска]
Базовый оператор select
select [all | distinct] [top целое [percent]]
выбираемый_столбец ,..
[from табличный_источник ,..] [where условие_поиска]
[group by [all] выражение_группировки ,..] [having условие_поиска]
Выбираемый столбец
{[имя_или_псевдоним_таблицы.]*
| |
[имя_или_псевдоним_таблицы.]имя_столбца [as псевдоним_столбца] |
|
| |
выражение_вычисляемого_столбца [as |
псевдоним_столбца] |
} |
|
|
Табличный источник |
|
|
{ |
имя_таблицы [as псевдоним_таблицы] |
|
| |
(оператор_select) as псевдоним_таблицы |
|
| |
соединенные_таблицы |
|
} |
|
|
Соединенные таблицы |
|
|
{ |
табличный_источник cross join табличный_источник |
|
| |
табличный_источник тип_соединения |
табличный_источник on условие_поиска |
| |
(соединенные_таблицы) |
|
} |
|
|
Спецкурс 3 (2010-2011. 5 курс, 9 сем. ПИЭ), 40 с. |
36 |
Тип соединения
{inner join
| |
|
left |
[outer] join |
|
|
|
| |
|
right |
[outer] join |
|
|
|
| |
|
full |
[outer] join |
|
|
|
} |
|
|
|
|
|
|
Фраза where |
|
|
|
|||
предикат::= |
|
|
|
|
||
1 |
{ |
выражение |
{< | <= | = | < > | >= | >} |
выражение |
||
2 |
| |
выражение |
[not] between выражение1 and выражение2 |
|||
3 |
| |
выражение |
is [not] null |
|
||
4 |
| |
строковое_выражение [not] like шаблон [escape ‘escape_ символ’] |
||||
5 |
| |
выражение |
[not] in |
(выражение ,..) |
|
|
6 |
| |
выражение |
[not] in |
(подзапрос) |
|
|
7 |
| |
выражение |
{< | <= | = | < > | >= | >} |
{all | any} (подзапрос) |
||
8 |
| |
exists (подзапрос) |
|
|
||
|
} |
|
|
|
|
|
Символы замещения:
1)%
2)_ (подчеркивание).
3){_[символ-символ]_ | _[символ… ]_}
4){_[^символ-символ]_ | _[^символ
Функции агрегирования
1)count(*)
2){count | sum | avg | min | max} ([all | distinct] выражение_над_столбцами)
Операция union и фраза order by
|
|
|
выражение |
select |
|
|
|
|
|
|
|
оператор_select::=
{базовый_оператор_select | (выражение_select)} [ union [all]
{базовый_оператор_select | (выражение_select)}
] ...
[ order by {выражение_сортировки [asc | desc]},..
]
Спецкурс 3 (2010-2011. 5 курс, 9 сем. ПИЭ), 40 с. |
37 |
Хранимые процедуры
create procedure имя_процедуры
[ @имя_параметра тип_данных [= значение_по_умолчанию] [output] ] ,..
as
операторы Вызов хранимой процедуры:
|
exec [@имя_переменной = ] имя_процедуры |
|
Форма 1 |
[ |
аргумент ,.. |
Форма 2 |
| |
{@имя_параметра = аргумент} ,.. |
Форма 3 |
| |
{аргумент ,..}, {@имя_параметра = аргумент} ,.. |
|
] |
|
аргумент ::= {выражение | default | @имя_переменной output}
Скалярные пользовательские функции:
create function имя_функции
(
[ @имя_параметра тип_данных [= значение_по_умолчанию] ] ,..
)
returns тип_данных as
begin
операторы
end
Вызов скалярной пользовательской функции:
имя_функции ([аргумент ,..]) аргумент ::= {выражение | default}
Форма 1 exec @имя_переменной = имя_функции ([аргумент ,..])
Форма 2 exec @имя_переменной = имя_функции {@имя_параметра = аргумент } ,..
Спецкурс 3 (2010-2011. 5 курс, 9 сем. ПИЭ), 40 с. |
38 |
Табличные пользовательские функции
create function имя_функции
(
[ @имя_параметра тип_данных [= значение_по_умолчанию] ] ,..
)
returns table as
return (оператор_select)
create function имя_функции
(
[ @имя_параметра тип_данных [= значение_по_умолчанию] ] ,..
)
returns @имя_таблицы table (определение_таблицы) as
begin
операторы
end
Вызов табличной пользовательской функции:
имя_функции ([аргумент ,..]) аргумент ::= {выражение | default}
Объявление курсора
|
|
|
declare имя_курсора cursor |
- |
|
|
[видимость] |
курсо |
|
|
[прокрутка] |
|
|
[тип] |
|
описание |
ра |
|
[блокировка] |
|
[type_warning] |
||
|
for оператор_select |
||
|
[for update [of имя_столбца ,..]] |
||
|
|
|
|
|
|
|
|
::= [local | global]
::= [forward_only | scroll]
::= [static | keyset | dynamic | fast_forward] ::= [read_only | scroll_locks | optimistic]
Курсорные переменные
declare имя_курсора cursor
Форма 1
описание_курсора
declare @имя_переменной cursor set @имя_переменной = имя_курсора
declare @имя_переменной cursor
Форма 2 set @имя_переменной cursor описание_курсора
Спецкурс 3 (2010-2011. 5 курс, 9 сем. ПИЭ), 40 с. |
39 |
Оператор fetch
fetch {first | last | next | prior | absolute n | relative n} from имя_или_переменная_курсора
into @имя_переменной ,..
Спецкурс 3 (2010-2011. 5 курс, 9 сем. ПИЭ), 40 с. |
40 |