Сегодня будем рассматривать очень много чего интересного, например как запустить уже созданную процедуру, которая принимает параметры, массово, т.е. не только со статическим параметрами, а с параметрами, которые будут меняться, например, на основе какой-нибудь таблицы, как обычная функция, и в этом нам помогут как раз курсоры и циклы, и как это все реализовать сейчас будем смотреть.
Как Вы поняли, курсоры и циклы мы будем рассматривать применимо к конкретной задачи. А какой задачи, сейчас расскажу.
Существует процедура, которая выполняет какие-то действия, которые не может выполнить обычная функция SQL например, расчеты и insert на основе этих расчетов. И Вы ее запускаете, например вот так:
EXEC test_PROCEDURE par1, par2
Другими словами Вы запускаете ее только с теми параметрами, которые были указаны, но если Вам необходимо запустить данную процедуру скажем 100, 200 или еще более раз, то согласитесь это не очень удобно, т.е. долго. Было бы намного проще, если бы мы взяли и запускали процедуру как обычную функцию в запросе select, например:
SELECT my_fun(id) FROM test_table
Другими словами функция отработает на каждую запись таблицы test_table, но как Вы знаете процедуру так использовать нельзя. Но существует способ, который поможет нам осуществить задуманное, точнее даже два способа первый это с использованием курсора и цикла и второй это просто с использованием цикла, но уже без курсора. Оба варианта подразумевают, что мы будем создавать дополнительную процедуру, которую в дальнейшем мы будем запускать.
Примечание! Все примеры будем писать в СУБД MSSql 2008, используя Management Studio. Также все ниже перечисленные действия требуют необходимых знаний в SQL, а точнее в программировании на Transact-SQL. Могу посоветовать для начала ознакомиться со следующим материалом:
И так приступим, и перед тем как писать процедуру, давайте рассмотрим исходные данные нашего примера.
Допустим, есть таблица test_table
В нее необходимо вставлять данные, на основе каких-то расчетов, которые будет выполнять процедура my_proc_test, в данном случае она просто вставляет данные, но на практике Вы можете использовать свою процедуру, которая может выполнять много расчетов, поэтому в нашем случае именно эта процедура не важна, она всего лишь для примера. Ну, давайте создадим ее:
Она просто принимает три параметра и вставляет их в таблицу.
И допустим эту процедуру, нам нужно запустить столько раз, сколько строк в какой-нибудь таблице или представлении (VIEWS) , другими словами запустить ее массово для каждой строки источника.
И для примера создадим такой источник, у нас это будет простая таблица test_table_vrem, а у Вас это может быть, как я уже сказал свой источник, например временная таблица или представление:
Заполним ее тестовыми данными:

И теперь нашу процедуру необходимо запустить для каждой строки, т.е. три раза с разными параметрами. Как Вы понимаете значения этих полей и есть наши параметры, другими словами, если бы мы запускали нашу процедуру вручную, это выглядело вот так:
exec my_proc_test 1, ‘pole1_str1’, ‘pole2_str1’
И так еще три раза, с соответствующими параметрами.
Но нам так не охота, поэтому мы напишем еще одну дополнительную процедуру, которая и будет запускать нашу основную процедуру столько раз, сколько нам нужно.
Первый вариант.
Используем курсор и цикл в процедуре
Перейдем сразу к делу и напишем процедуру (my_proc_test_all), код я как всегда прокомментировал:
И теперь осталось нам ее вызвать и проверить результат:

Как видите, все у нас отработало как надо, другими словами процедура my_proc_test сработала все три раза, а мы всего лишь один раз запустили дополнительную процедуру.
Второй вариант.
Используем только цикл в процедуре
Сразу скажу, что здесь требуется нумерация строк во временной таблице, т.е. каждая строка должна быть пронумерована, например 1, 2, 3 таким полем у нас во временной таблице служит number.
Пишем процедуру my_proc_test_all_v2
И проверяем результат, но для начала очистим нашу таблицу, так как мы же ее только что уже заполнили по средствам процедуры my_proc_test_all:

Как и ожидалось результат такой же, но уже без использования курсоров. Какой вариант использовать решать Вам, первый вариант хорош, тем, что в принципе не нужна нумерация, но как Вы знаете, курсоры работают достаточно долго, если строк в курсоре будет много, а второй вариант хорош тем, что отработает, как мне кажется быстрей, опять же таки, если строк будет много, но нужна нумерация, лично мне нравится вариант с курсором, а вообще решать Вам может Вы сами придумаете что-то более удобное, я всего лишь показал основы того, как можно реализовать поставленную задачу. Удачи!
Управление курсором реализуется путем выполнения следующих команд:
· DECLARE – создание или объявление курсора ;
· OPEN – открытие курсора, т.е. наполнение его данными;
· FETCH – выборка из курсора и изменение строк данных с помощью курсора;
· CLOSE – закрытие курсора ;
· DEALLOCATE – освобождение курсора, т.е. удаление курсора как объекта.
Объявление курсора
В стандарте SQL для создания курсора предусмотрена следующая команда:
::= DECLARE имя_курсора [INSENSITIVE][SCROLL] CURSOR FOR SELECT_оператор [FOR < READ_ONLY | UPDATE [OF имя_столбца[. n]]>]
При использовании ключевого слова INSENSITIVE будет создан статический курсор. Изменения данных не разрешаются, кроме того, не отображаются изменения, сделанные другими пользователями. Если ключевое слово INSENSITIVE отсутствует, создается динамический курсор.
При указании ключевого слова SCROLL созданный курсор можно прокручивать в любом направлении, что позволяет применять любые команды выборки. Если этот аргумент опускается, то курсор окажется последовательным, т.е. его просмотр будет возможен только в одном направлении – от начала к концу.
SELECT-оператор задает тело запроса SELECT, с помощью которого определяется результирующий набор строк курсора.
При указании аргумента FOR READ_ONLY создается курсор "только для чтения", и никакие модификации данных не разрешаются. Он отличается от статического, хотя последний также не позволяет менять данные. В качестве курсора "только для чтения" может быть объявлен динамический курсор, что позволит отображать изменения, сделанные другим пользователем.
Создание курсора с аргументом FOR UPDATE позволяет выполнять в курсоре изменение данных либо в указанных столбцах, либо, при отсутствии аргумента OF имя_столбца, во всех столбцах.
В среде MS SQL Server принят следующий синтаксис команды создания курсора:
::= DECLARE имя_курсора CURSOR [LOCAL | GLOBAL] [FORWARD_ONLY | SCROLL] [STATIC | KEYSET | DYNAMIC | FAST_FORWARD] [READ_ONLY | SCROLL_LOCKS | OPTIMISTIC] [TYPE_WARNING] FOR SELECT_оператор [FOR UPDATE [OF имя_столбца[. n]]]
При использовании ключевого слова LOCAL будет создан локальный курсор, который виден только в пределах создавшего его пакета, триггера, хранимой процедуры или пользовательской функции. По завершении работы пакета, триггера, процедуры или функции курсор неявно уничтожается. Чтобы передать содержимое курсора за пределы создавшей его конструкции, необходимо присвоить его параметру аргумент OUTPUT.
Если указано ключевое слово GLOBAL, создается глобальный курсор ; он существует до закрытия текущего соединения.
При указании FORWARD_ONLY создается последовательный курсор ; выборку данных можно осуществлять только в направлении от первой строки к последней.
При указании SCROLL создается прокручиваемый курсор ; обращаться к данным можно в любом порядке и в любом направлении.
При указании STATIC создается статический курсор.
При указании KEYSET создается ключевой курсор.
При указании DYNAMIC создается динамический курсор.
Если для курсора READ_ONLY указать аргумент FAST_FORWARD, то созданный курсор будет оптимизирован для быстрого доступа к данным. Этот аргумент не может быть использован совместно с аргументами FORWARD_ONLY и OPTIMISTIC.
В курсоре, созданном с указанием аргумента OPTIMISTIC, запрещается изменение и удаление строк, которые были изменены после открытия курсора.
При указании аргумента TYPE_WARNING сервер будет информировать пользователя о неявном изменении типа курсора, если он несовместим с запросом SELECT.
Открытие курсора
Для открытия курсора и наполнения его данными из указанного при создании курсора запроса SELECT используется следующая команда:
После открытия курсора происходит выполнение связанного с ним оператора SELECT, выходные данные которого сохраняются в многоуровневой памяти.
Выборка данных из курсора
Сразу после открытия курсора можно выбрать его содержимое (результат выполнения соответствующего запроса) посредством следующей команды:
При указании FIRST будет возвращена самая первая строка полного результирующего набора курсора, которая становится текущей строкой.
При указании LAST возвращается самая последняя строка курсора. Она же становится текущей строкой.
При указании NEXT возвращается строка, находящаяся в полном результирующем наборе сразу же после текущей. Теперь она становится текущей. По умолчанию команда FETCH использует именно этот способ выборки строк.
Ключевое слово PRIOR возвращает строку, находящуюся перед текущей. Она и становится текущей.
Аргумент ABSOLUTE <номер_строки | @переменная_номера_строки>возвращает строку по ее абсолютному порядковому номеру в полном результирующем наборе курсора. Номер строки можно задать с помощью константы или как имя переменной, в которой хранится номер строки. Переменная должна иметь целочисленный тип данных. Указываются как положительные, так и отрицательные значения. При указании положительного значения строка отсчитывается от начала набора, отрицательного – от конца. Выбранная строка становится текущей. Если указано нулевое значение, строка не возвращается.
Аргумент RELATIVE <кол_строки | @переменная_кол_строки>возвращает строку, находящуюся через указанное количество строк после текущей. Если указать отрицательное значение числа строк, то будет возвращена строка, находящаяся за указанное количество строк перед текущей. При указании нулевого значения возвратится текущая строка. Возвращенная строка становится текущей.
Чтобы открыть глобальный курсор, перед его именем требуется указать ключевое слово GLOBAL. Имя курсора также может быть указано с помощью переменной.
В конструкции INTO @имя_переменной [. n] задается список переменных, в которых будут сохранены соответствующие значения столбцов возвращаемой строки. Порядок указания переменных должен соответствовать порядку столбцов в курсоре, а тип данных переменной – типу данных в столбце курсора. Если конструкция INTO не указана, то поведение команды FETCH будет напоминать поведение команды SELECT – данные выводятся на экран.
Изменение и удаление данных
Для выполнения изменений с помощью курсора необходимо выполнить команду UPDATE в следующем формате:
UPDATE имя_таблицы SET <имя_столбца=< DEFAULT | NULL | выражение>>[. n] WHERE CURRENT OF <<[GLOBAL] имя_курсора>|@имя_переменной_курсора>
За одну операцию могут быть изменены несколько столбцов текущей строки курсора, но все они должны принадлежать одной таблице.
Для удаления данных посредством курсора используется команда DELETE в следующем формате:
DELETE имя_таблицы WHERE CURRENT OF <<[GLOBAL] имя_курсора>|@имя_переменной_курсора>
В результате будет удалена строка, установленная текущей в курсоре.
Закрытие курсора
После закрытия курсор становится недоступным для пользователей программы. При закрытии снимаются все блокировки, установленные в процессе его работы. Закрытие может применяться только к открытым курсорам. Закрытый, но неосвобожденный курсор может быть повторно открыт. Не допускается закрывать неоткрытый курсор.
Освобождение курсора
Закрытие курсора необязательно освобождает ассоциированную с ним память. В некоторых реализациях нужно явным образом освободить ее с помощью оператора DEALLOCATE. После освобождения курсора освобождается и память, при этом становится возможным повторное использование имени курсора.
Для контроля достижения конца курсора рекомендуется применять функцию: @@FETCH_STATUS
Функция @@FETCH_STATUS возвращает:
0, если выборка завершилась успешно;
-1, если выборка завершилась неудачно вследствие попытки выборки строки, находящейся за пределами курсора ;
-2, если выборка завершилась неудачно вследствие попытки обращения к удаленной или измененной строке.
DECLARE abc CURSOR SCROLL FOR
SELECT * FROM Клиент
Пример 13.1. Объявление курсора.
DECLARE @MyCursor CURSOR
SET @MyCursor=CURSOR LOCAL SCROLL FOR
SELECT * FROM Клиент
Пример 13.2. Использование переменной для объявления курсора.
DECLARE abc CURSOR GLOBAL SCROLL FOR
SELECT * FROM Клиент
Пример 13.3. Объявление и открытие курсора.
DECLARE @MyCursor CURSOR
Пример 13.4. Использование переменной для переприсваивания курсора.
Пример 13.5. Разработать курсор для вывода списка фирм и клиентов из Москвы.
DECLARE @firm VARCHAR(50),
PRINT ‘ Список клиентов’
DECLARE klient_cursor CURSOR LOCAL FOR
SELECT Фирма, Фамилия
ORDER BY Фирма, Фамилия
FETCH NEXT FROM klient_cursor INTO @firm, @fam
SELECT @message=’Клиент ‘+@fam+
— переход к следующему клиенту—
FETCH NEXT FROM klient_cursor
Пример 13.5. Курсор для вывода списка фирм и клиентов из Москвы.
Пример 13.6. Разработать курсор для вывода списка приобретенных клиентами из Москвы товаров и их общей стоимости. В одинкурсор заносятся все московские клиенты, затем для каждой строки курсора, т.е. для каждого клиента, определяется и распечатывается другой курсор – его покупки. Подсчитывается общая стоимость покупок клиента.
DECLARE @id_kl INT,
PRINT ‘ Список покупок’
DECLARE klient_cursor CURSOR LOCAL FOR
SELECT КодКлиента, Фирма, Фамилия
ORDER BY Фирма, Фамилия
FETCH NEXT FROM klient_cursor
INTO @id_kl, @firm, @fam
SELECT @message=’Клиент ‘+@fam+
SELECT @message=’Наименование товара Дата
DECLARE tovar_cursor CURSOR FOR
SELECT Товар.Название, Сделка.Дата,
FROM Товар INNER JOIN Сделка ON Товар.
FETCH NEXT FROM tovar_cursor
PRINT ‘ Нет покупок’
SELECT @message=’ ‘+@nam+’ ‘+
CAST(@d AS CHAR(12))+’ ‘+
FETCH NEXT FROM tovar_cursor
SELECT @message=’Общая стоимость ‘+
— переход к следующему клиенту—
FETCH NEXT FROM klient_cursor
INTO @id_kl, @firm, @fam
Пример 13.6. Курсор для вывода списка приобретенных клиентами из Москвы товаров и их общей стоимости.
Пример 13.7. Разработать прокручиваемый курсор для клиентов из Москвы. Если номер телефона начинается на 1, удалить клиента с таким номером и в первой записи курсора заменить первую цифру в номере телефона на 4.
DECLARE @firm VARCHAR(50),
PRINT ‘ Список клиентов’
DECLARE klient_cursor CURSOR GLOBAL SCROLL
SELECT Фирма, Фамилия, Телефон
ORDER BY Фирма, Фамилия
FETCH NEXT FROM klient_cursor
INTO @firm, @fam, @tel
SELECT @message=’Клиент ‘+@fam+
‘ Фирма ‘+@firm ‘ Телефон ‘+ @tel
— если номер телефона начинается на 1,
— удалить клиента с таким номером
WHERE CURRENT OF klient_cursor
— переход к следующему клиенту
FETCH NEXT FROM klient_cursor
INTO @firm, @fam, @tel
FETCH ABSOLUTE 1 FROM klient_cursor
INTO @firm, @fam, @tel
— в первой записи заменить первую цифру в
— номере телефона на 4
UPDATE Клиент SET Телефон=’4’ +
WHERE CURRENT OF klient_cursor
SELECT @message=’Клиент ‘+@fam+’ Фирма ‘+
@firm ‘ Телефон ‘+ @tel
Пример 13.7. Прокручиваемый курсор для клиентов из Москвы.
Пример 13.8. Использование курсора как выходного параметра процедуры. Процедура возвращает набор данных – списоктоваров.
CREATE PROC my_proc
@cur CURSOR VARYING OUTPUT
SET @cur=CURSOR FORWARD_ONLY STATIC FOR
SELECT Название FROM Товар
Пример 13.8. Использование курсора как выходного параметра процедуры.
Вызов процедуры и вывод на печать данных из выходного курсора осуществляется следующим образом:
ПРИМЕНЯЕТСЯ К:
SQL Server (начиная с 2008)
База данных SQL Azure
Хранилище данных SQL Azure
Parallel Data Warehouse
Определяет такие атрибуты серверного курсора языка Transact-SQL, как свойства просмотра и запрос, используемый для построения результирующего набора, на котором работает курсор. Инструкция DECLARE CURSOR поддерживает как синтаксис стандарта ISO, так и синтаксис, использующий набор расширений языка Transact-SQL.
Синтаксические обозначения в Transact-SQL
cursor_name
Имя Transact-SQL определенного серверного курсора. cursor_name должны соответствовать правилам для идентификаторов.
INSENSITIVE
Определяет курсор, который создает временную копию данных для использования курсором. Все запросы к курсору обращаются к указанной временной таблице в tempdb; таким образом, изменения базовых таблиц не отражаются в возвращенных выборками этого курсора данных, и этот курсор не допускает изменения. При использовании синтаксиса ISO, если не указан параметр INSENSITIVE, зафиксированные обновления и удаления, сделанные в базовых таблицах, отображаются в последующих выборках.
SCROLL
Указывает, что доступны все параметры выборки (FIRST, LAST, PRIOR, NEXT, RELATIVE, ABSOLUTE). Если в инструкции DECLARE CURSOR стандарта ISO не указан параметр SCROLL, то поддерживается только параметр выборки NEXT. Параметр SCROLL не может указываться вместе с параметром FAST_FORWARD.
select_statement
Стандартная инструкция SELECT, которая определяет результирующий набор курсора. Ключевые слова FOR BROWSE и INTO недопустимы в select_statement объявление курсора.
SQL Serverнеявно преобразует курсор в другой тип, если предложения в select_statement конфликт с курсором запрошенного типа.
READ ONLY
Предотвращает изменения, сделанные через этот курсор. Предложение WHERE CURRENT OF не может иметь ссылку на курсор в инструкции UPDATE или DELETE. Этот параметр имеет преимущество над установленной по умолчанию возможностью обновления курсора.
Обновление [OF column_name [,. n]]
Определяет обновляемые столбцы в курсоре. If OF column_name [,.. .n] указан, только перечисленные столбцы позволяют вносить изменения. Если инструкция UPDATE используется без списка столбцов, то обновление возможно для всех столбцов.
cursor_name
Имя Transact-SQL определенного серверного курсора. cursor_name должны соответствовать правилам для идентификаторов.
LOCAL
Указывает, что курсор является локальным по отношению к пакету, хранимой процедуре или триггеру, в котором он был создан. Имя курсора допустимо только внутри этой области. На курсор могут ссылаться локальные переменные пакета, хранимые процедуры, триггеры или выходной параметр хранимой процедуры. Параметр OUTPUT используется для передачи локального курсора вызывающему его пакету, хранимой процедуре или триггеру, который затем может присвоить параметр переменной курсора с целью последующего обращения к курсору после завершения хранимой процедуры. Курсор неявно освобождается после завершения выполнения пакета, хранимой процедуры или триггера, за исключением случая, когда курсор был передан параметру OUTPUT. Если курсор был передан параметру OUTPUT, то курсор освобождается при освобождении всех ссылающихся на него переменных или при выходе из области видимости.
GLOBAL
Указывает, что курсор является глобальным по отношению к соединению. Имя курсора может использоваться любой хранимой процедурой или пакетом, которые выполняются в соединении. Курсор неявно освобождается только в случае разрыва соединения.
| Примечание |
|---|
Если указан ни GLOBAL или LOCAL, значение по умолчанию определяется параметр по умолчанию локальный курсор параметр базы данных.
FORWARD_ONLY
Указывает, что курсор может просматриваться только от первой строки к последней. Поддерживается только параметр выборки FETCH NEXT. Если параметр FORWARD_ONLY указан без ключевых слов STATIC, KEYSET или DYNAMIC, то курсор работает как курсор DYNAMIC. Если не указаны ни аргумент FORWARD_ONLY, ни аргумент SCROLL, по умолчанию используется аргумент FORWARD_ONLY, если нет ключевых слов STATIC, KEYSET или DYNAMIC. Курсоры STATIC, KEYSET и DYNAMIC имеют значение по умолчанию SCROLL. В отличие от таких интерфейсов API баз данных, как ODBC и ADO, режим FORWARD_ONLY поддерживается следующими курсорами языка Transact-SQL: STATIC, KEYSET и DYNAMIC.
STATIC
Определяет курсор, который создает временную копию данных для использования курсором. Все запросы к курсору обращаются к указанной временной таблице в tempdb; таким образом, изменения базовых таблиц не отражаются в возвращенных выборками этого курсора данных, и этот курсор не допускает изменения.
KEYSET
Указывает, что членство или порядок строк в курсоре неизменны при его открытии. Набор ключей, однозначно определяющих строки, встроен в таблицу в tempdb называется ключей.
| Примечание |
|---|
Если запрос ссылается хотя бы на одну таблицу, не имеющую уникального индекса, курсор keyset преобразуется в статический курсор.
Изменения неключевых значений в базовых таблицах, сделанные владельцем курсора или зафиксированные другими пользователями, отображаются при просмотре курсора владельцем. Изменения, сделанные другими пользователями, не отображаются (изменения не могут быть сделаны с помощью серверного курсора языка Transact-SQL). Если удаляется строка, попытка выборки строк возвращает @@FETCH_STATUS -2. Обновления значений ключа из-за границ курсора аналогично удалению старой строки с последующей вставкой новой строки. Строка с новыми значениями не видна и попытки выборки строки со старыми значениями возвращают @@FETCH_STATUS -2. Обновления видимы сразу, если они сделаны через курсор с помощью предложения WHERE CURRENT OF.
DYNAMIC
Определяет курсор, отображающий все изменения данных, сделанные в строках результирующего набора при просмотре этого курсора. Значения данных, порядок и членство строк в каждой выборке могут меняться. Параметр выборки ABSOLUTE динамическими курсорами не поддерживается.
FAST_FORWARD
Указывает курсор FORWARD_ONLY, READ_ONLY, для которого включена оптимизация производительности. Параметр FAST_FORWARD не может указываться вместе с параметрами SCROLL или FOR_UPDATE.
| Примечание |
|---|
Оба ключевых слова FAST_FORWARD и FORWARD_ONLY могут быть использованы в одной и той же инструкции DECLARE CURSOR.
READ_ONLY
Предотвращает изменения, сделанные через этот курсор. Предложение WHERE CURRENT OF не может иметь ссылку на курсор в инструкции UPDATE или DELETE. Этот параметр имеет преимущество над установленной по умолчанию возможностью обновления курсора.
SCROLL_LOCKS
Указывает, что позиционированные обновления или удаления, осуществляемые с помощью курсора, гарантированно будут выполнены успешно. SQL Server блокирует строки по мере их считывания в курсор для обеспечения доступности этих строк для последующих изменений. Параметр SCROLL_LOCKS не может указываться вместе с параметром FAST_FORWARD или STATIC.
OPTIMISTIC
Указывает, что позиционированные обновления или удаления, осуществляемые с помощью курсора, не будут выполнены, если с момента считывания в курсор строка была обновлена. SQL Server не блокирует строки по мере их считывания в курсор. Вместо этого используются сравнения timestamp значения столбца или контрольных сумм, если в таблице нет timestamp столбец, чтобы определить, изменялась ли строка после считывания в курсор. Если строка была изменена, то попытки позиционированного обновления или удаления будут безрезультатными. Параметр OPTIMISTIC не может указываться вместе с параметром FAST_FORWARD.
TYPE_WARNING
Указывает, что клиенту будет отправлено предупреждение, если курсор неявно будет преобразован из одного запрашиваемого типа в другой.
select_statement
Стандартная инструкция SELECT, которая определяет результирующий набор курсора. Ключевые слова COMPUTE, COMPUTE BY, FOR BROWSE и INTO недопустимы в select_statement объявление курсора.
| Примечание |
|---|
Можно использовать подсказки в запросе в объявлении курсора; Однако при использовании предложения FOR UPDATE OF, укажите параметр (query_hint) после обновления ОБЪЕКТА.
SQL Serverнеявно преобразует курсор в другой тип, если предложения в select_statement конфликт с курсором запрошенного типа. Дополнительные сведения см. в разделе «Неявные преобразования курсора».
ДЛЯ обновления [OF column_name [,. n]]
Определяет обновляемые столбцы в курсоре. If OF column_name [,. n] предоставляется, только перечисленные столбцы позволяют вносить изменения. Если инструкция UPDATE используется без списка столбцов, то обновление возможно для всех столбцов, за исключением случая, когда был указан параметр параллелизма READ_ONLY.
Инструкция DECLARE CURSOR определяет такие атрибуты серверного курсора языка Transact-SQL, как свойства просмотра и запрос, используемый для построения результирующего набора, на котором работает курсор. Инструкция OPEN заполняет результирующий набор, а оператор FETCH возвращает из него строку. Инструкция CLOSE очищает текущий результирующий набор, связанный с курсором. Инструкция DEALLOCATE освобождает ресурсы, используемые курсором.
Первая форма инструкции DECLARE CURSOR использует синтаксис ISO для задания параметров работы курсора. Вторая форма инструкции DECLARE CURSOR использует расширения языка Transact-SQL, позволяющие определять курсоры с помощью таких же типов, как типы, используемые в курсорных функциях API баз данных, таких как ODBC и ADO.
Нельзя смешивать две эти формы. Если указать SCROLL или без УЧЕТА ключевые слова перед ключевым словом CURSOR, нельзя использовать ключевые слова между КУРСОРА, а также для select_statement ключевые слова. При указании ключевые слова между КУРСОРА, а также для select_statement ключевые слова, нельзя указать SCROLL или INSENSITIVE перед ключевым словом CURSOR.
Если при использовании синтаксиса языка Transact-SQL для инструкции DECLARE CURSOR не указываются параметры READ_ONLY, OPTIMISTIC или SCROLL_LOCKS, то принимается следующее значение по умолчанию.
Если инструкция SELECT не поддерживает обновления (или недостаточно разрешений, или при доступе к удаленным таблицам, не поддерживающим обновление, и т. п.), то курсору присваивается параметр READ_ONLY.
Курсоры STATIC и FAST_FORWARD по умолчанию имеют значение READ_ONLY.
Курсоры DYNAMIC и KEYSET по умолчанию имеют значение OPTIMISTIC.
Ссылки на курсоры могут производиться только другими инструкциями языка Transact-SQL. Функции API баз данных не могут ссылаться на курсоры. Например, после объявления курсора функции и методы OLE DB, ODBC или ADO не могут ссылаться на его имя. Строки курсора не могут быть выбраны с помощью соответствующих функций и методов API; для этой цели необходимо использовать инструкции FETCH языка Transact-SQL.
Приведенные ниже хранимые процедуры могут быть использованы для определения свойств курсора после его объявления.
| Системные хранимые процедуры. | Description |
|---|---|
| sp_cursor_list | Возвращает список курсоров, доступных для соединения в настоящий момент времени, а также их атрибуты. |
| sp_describe_cursor | Описывает атрибуты курсора, например имеет ли он тип «forward-only» или «scrolling». |
| sp_describe_cursor_columns | Описывает атрибуты столбцов результирующего набора. |
| sp_describe_cursor_tables | Описывает базовые таблицы, к которым курсор получает доступ. |
Переменные могут использоваться как часть select_statement , в котором объявлен курсор. Значения переменных курсора после его объявления не изменяются.
По умолчанию разрешения DECLARE CURSOR предоставляются всем пользователям, имеющим разрешение SELECT для используемых курсором представлений, таблиц и столбцов.
Нельзя использовать курсоры или триггеры в таблице с кластеризованным индексом columnstore. Это ограничение не применяется к некластеризованные индексы; можно использовать курсоры и триггеры в таблице с некластеризованным индексом columnstore.
A. Использование простого курсора и синтаксиса
Результирующий набор, создаваемый при открытии данного курсора, включает в себя все строки и столбцы таблицы. Этот курсор можно обновлять, все обновления и удаления представлены в выборке для этого курсора. FETCH«NEXT доступна только выборка, поскольку SCROLL не был указан параметр.
Б. Использование вложенных курсоров для вывода отчета
В следующем примере вложенные курсоры используются для вывода сложного отчета. Для каждого поставщика объявляется внутренний курсор.






