Операции, требующие использования курсоров

Вернемся теперь к случаю предложения SELECT, которое продуцирует целое множество записей, а не только одну запись. Как уже было объяснено в разделе 10.2, здесь необходим механизм, обеспечивающий последовательный доступ к записям в этом множестве. Такой механизм обеспечивают курсоры. В общих чертах процесс доступа иллюстрируется в примере, приведенном на рис. 10.2, в котором предусматривается выборка деталей (полей НОМЕР_ДЕТАЛИ, НАЗВАНИЕ и СОСТОЯНИЕ) для всех поставщиков, находящихся в городе, заданном переменной включающего языка Y.

ЕХЕС SQL DECLARE X CURSOR FOR / * определить курсор X * /

SELECT НОМЕР_ПОСТАВЩИКА, НАЗВАНИЕ,

СОСТОЯНИЕ

FROM S

WHERE ГОРОД = > У;

ЕХЕС SQL OPEN X; / * исполнить запрос * /

DO WHILE (пока еще есть записи);

ЕХЕС SQL FETCH X INTO:НОМЕР_

ПОСТАВЩИКА,:НАЗВАНИЕ,:СОСТОЯНИЕ;

/ * выбрать следующего поставщика * /

END;

ЕХЕС SQL CLOSE X; / * дезактивировать курсор Х * /

Рис. 10.2. Выборка множества записей

Пояснение. Предложение DECLARE X CURSOR... определяет курсор, названный X, и ассоциированный с ним запрос, специфицированный с помощью предложения SELECT, которое образует часть этого предложения DECLARE. Указанное предложение SELECT не исполняется в данный момент, так как DECLARE CURSOR это чисто декларативное предложение. Оно исполняется, когда открывается курсор в процедурной части программы. Предложение FETCH... INTO... (выбрать... в...) используется для выборки записей результирующего множества и присваивает найденные значения переменным включающего языка в соответствии со спецификациями фразы INTO в этом предложении. Для простоты в приведенном примере переменным включающего языка даны те же самые имена, что и соответствующим полям базы данных. Заметим, что предложение SELECT в объявлении курсора не содержит фразы INTO. Поскольку в результате будет получено множество записей, предложение FETCH будет обычно входить в некоторый цикл (в языке ПЛ/1—DO... END). Этот цикл будет повторяться до тех пор, пока в этом результирующем множестве еще существуют непросмотренные записи. При выходе из цикла курсор Х закрывается (дезактивируется) с помощью соответствующего предложения CLOSE(закрыть).

Давайте теперь рассмотрим курсоры и операции над курсорами более подробно. Прежде всего нужно отметить, что курсор объявляется с помощью предложения DECLARE CURSOR (объявить курсор), которое имеет следующий общий формат:

ЕХЕС SQL DECLARE имя — курсора CURSOR

FOR подзапрос [UNION подзапрос]...

[FOR UPDATE OF имя — столбца [,имя — столбца]...

[фраза — упорядочить — по];

Для примера обратимся к рис. 10.2. Как указывалось ранее, предложение DECLARE CURSOR является декларативным, а не исполняемым. Оно объявляет курсор с заданным именем, с которым постоянно связан специфицированный подзапрос или множество подзапросов, соединенных операций UNION. Заметим, что эти подзапросы могут включать ссылки на переменные включающего языка. Если курсор будет использоваться в предложениях UPDATE CURRENT (обновить текущую) (См. ниже в этом разделе.— Примеч пер), то его объявление должно включать фразу FOR UPDATE(для обновления), специфицирующую все поля, которые будут обновляться через этот курсор. Если курсор не используется для обновления с помощью указанного предложения, то его объявление факультативно может включать фразу ORDER BY(упорядочить по), как в обычном предложении SELECT. Эта фраза будет управлять порядком, в котором строки результата выбираются с помощью предложения FETCH. Заметим поэтому, что невозможно осуществлять выборку множества записей через курсор в некотором специфицированном порядке и в то же время обновлять (операция UPDATE) некоторые из этих записей через тот же самый курсор.

Программа может включать произвольное число предложений DECLARE CURSOR, которые, конечно, объявляют различные курсоры.

Для выполнения операций над курсорами специально обеспечиваются три исполняемых предложения: OPEN, FETCH и CLOSE.

1. Предложение

ЕХЕС SQL OPEN имя — курсора;

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

2.Предложение

ЕХЕС SQL FETCHимя — курсора INTO мишень [, мишень]...;

где каждая «мишень» имеет формат

переменная — включающего — языка [:переменная — включающего — языка]

как в единичном SELECT, и где идентифицированный курсор должен быть открыт, продвигает этот курсор к следующей записи в активном множестве, а затем присваивает значения полей из этой записи переменным включающего языка, в соответствии с фразой INTO. Как уже указывалось, предложение FETCH обычно исполняется в программном цикле (см. рис. 102). Если при исполнении FETCH не существует следующей записи, то выборка данных не производится и SQLCODE принимает значение +100.

Отметим, между прочим, что «выбрать следующую» представляет собой единственную операцию перемещения курсора. Невозможно переместить курсор, например, «вперед на три позиции» или «назад на две позиции» и т. п.

3. Предложение

ЕХЕС SQL CLOSE имя — курсора;

закрывает или дезактивирует специфицированный курсор, который в этот момент должен быть открыт. Теперь этот курсор не имеет соответствующего активного множества. Его можно, однако, теперь снова открыть. В этом случае с ним будет связано другое активное множество, вероятно, не в точности то же самое, что и ранее, особенно если значения переменных включающего языка, упоминаемые в предложении SELECT, тем временем изменились. Заметим, что изменение значений этих переменных в то время, когда курсор открыт, не оказывает влияния на активное множество.

Два следующих предложения могут включать ссылки на курсоры. Имеются формы CURRENT для предложений UPDATEи DELETE. Если, например, курсор Х в настоящее время позиционирован на конкретную запись в базе данных, то можно обновить (UPDATE) или удалить (DELETE) «текущую X», т. е. запись, на которую позиционирован X. Синтаксис этих предложений таков:

ЕХЕС SQL UPDATE имя — таблицы

SET имя — поля = выражение

[, имя — поля == выражение]...

WHERE CURRENT OF имя — курсора;

ЕХЕС SQL DELETE

FROMимя — таблицы

WHERE CURRENT OF имя — курсора;

Пример:

ЕХЕС SQL UPDATE S

SET СОСТОЯНИЕ = СОСТОЯНИЕ +:ПРИРОСТ

WHERE CURRENT OF X;

Использование предложений UPDATE CURRENT и DELETE CURRENT не допускается, если предложение SELECT в объявлении курсора включает UNION или ORDER BY, или если это предложение SELECT определяет необновляемое представление и является частью предложения CREATE VIEW (см. раздел 8.4). Как пояснялось ранее, в случае UPDATE CURRENT предложение DECLARE должно включать фразу FOR UPDATE, идентифицирующую все поля, которые входят как мишени во фразу SET предложения UPDATE CURRENT для этого курсора.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: