ОПЕРАЦИИ, ТРЕБУЮЩИЕ ИСПОЛЬЗОВАНИЯ КУРСОРОВ
Вернемся теперь к случаю предложения 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 (закрыть).
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 для этого курсора.